Fix high CPU usage in callback thread due to incorrect timespec #782
No reviewers
Labels
No labels
3rdparty
Android
API
Author does not respond
bsd
bug
build system/CI
ci-virtual-device
CMake
Contributions Welcome
Core
dependencies
device-specific
documentation
don't_merge
duplicate
enhancement
Example
Haiku
hidraw
hotplug
info required
invalid
libusb
macOS
Misc
Not an issue
question
Release
Test
Test GUI
Windows
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-libusb/hidapi!782
Loading…
Reference in a new issue
No description provided.
Delete branch "patch-1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
@CalcProgrammer1 noticed high CPU usage (50%) on one of the threads when libusb backend is used for hotplug. It was determined that the load was caused by
hidapi_thread_cond_timedwait(), which requires an absolute timespec, while the code passes a relative value. This patch copies how the structure is filled from the other place wherehidapi_thread_cond_timedwait()is uses, which should fix the issue.@ -1215,16 +1215,16 @@ static void* callback_thread(void* user_data){I'd set it to 1 second - I've been using 1 second in multiple projects, and seems reasonable
5 second to exit the thread (effectively - to quit the application in some cases) seem a bit too much
Pull request overview
Fixes high CPU usage in the libusb hotplug callback thread by passing an absolute timeout to
hidapi_thread_cond_timedwait()(required by the pthread-backed implementation), instead of a relativetimespec.Changes:
now + 5msviahidapi_thread_gettime()+hidapi_thread_addtime().libusb/hid.c.💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
@ -1215,16 +1215,16 @@ static void* callback_thread(void* user_data){According to the call signature, the number is in milliseconds, not whole seconds.

When it comes to milliseconds, it doesn't really matter what number is set there, as execution at single milliseconds scale is likely limited by OS scheduler, not the actual number set here, so long as it's long enough to actually go idle.
A whole second here would be too long (at least to my taste), and checking every single millisecond seems a bit excessive. It can be changed later on to 20 or 40 or even 100 milliseconds if needed (i.e. if this thread makes any noticeable CPU load).
@ -1215,16 +1215,16 @@ static void* callback_thread(void* user_data){So far, the patch seems to work:
("wrapped HID devices" in this context means HID devices that use libusb backend specifically)
@ -1215,16 +1215,16 @@ static void* callback_thread(void* user_data){While modern processors are fast-enough practically not to notice wait/idle/check every 5ms, my experience tells it is a bit too often, I'd make it 100ms then.
@ -1215,16 +1215,16 @@ static void* callback_thread(void* user_data){Increased the timeout to 100
Meanwhile I'm looking at a fundamentally different aproach to fix this issue - there should be no timeout at all: #783
The approach suggested there would also work; however, the proposed change simultaneously breaks the cache of connected devices, which would lead to inability to report disconnect events.
I don't remember exactly why I started with a timed
cond_wait, it was either a precaution against infinite wait if, or the exact reason could have been resolved.@k1-801
Check the PR again - there are also a few multithreading bugs fixed.
There is a high change that because of this:
https://github.com/libusb/hidapi/pull/783/changes#diff-516ed9d234e81614e6fa65cfc81a50b8b119e8a0769b2e66a1c89166bac437f7R1286-R1288
There is exacty one reason why a timed wait should be used in cases like that - when it is impossible to single the even in a clean way in any other was. In this case - it is a 100% possible and should be done exactly like that.
#783 has been merged. Do we still need this one?
Interesting, it should have been closed on its own
Is there a new "finished" hotplug branch available? If so let me know which branch and I will update my fork and test it in OpenRGB next this weekend across Windows, Linux, and MacOS.
https://github.com/libusb/hidapi/tree/connection-callback
Not yet finished...
That's fine, I will test this latest branch. I meant finished in terms of this issue mainly.
With the updated connection-callback branch I am seeing about 0.7% CPU usage in htop from the openrgb background service on Linux, which is in line with what I would expect. I don't have the devices on me to test the wrapped/libusb backend right now but the hidraw backend successfully detects hotplug and removal. Both backends have their hotplug listening threads running as part of that 0.7%.
Pull request closed