Closed GoogleCodeExporter closed 9 years ago
Default Java version with Linux Mint 14:
$java -version
java version "1.7.0_09"
OpenJDK Runtime Environment (IcedTea7 2.3.4) (7u9-2.3.4-0ubuntu1.12.10.1)
OpenJDK 64-Bit Server VM (build 23.2-b09, mixed mode)
Original comment by postmark...@gmail.com
on 5 Feb 2013 at 6:03
Please unchecked all of the boxes in the demo application and check to see if
the CPU utilization is still high. Let me know how that works.
Original comment by a...@1stleg.com
on 5 Feb 2013 at 6:32
I unchecked all four boxes on the demo, and the processor was still at 100%.
This is consistent with what I saw in my application. If I comment out
addNativeKeyListener(), etc, there is no change. If I comment out
registerNativeHook(), the processor utilization returns to normal.
Original comment by postmark...@gmail.com
on 5 Feb 2013 at 2:47
I peeked at the source, and see a possible cause. Please see my explanation
that follows.
From NativeThread.c
// Async requires that we loop so that our thread does not return.
if (XRecordEnableContextAsync(disp_data, context, LowLevelProc, NULL) != 0) {
// Set the exit status.
*status = RETURN_SUCCESS;
while (running) {
XRecordProcessReplies(disp_data);
}
XRecordDisableContext(disp_ctrl, context);
}
The documentation for XRecordEnableContextAsync says:
"Each time it reads data from the server connection, Xlib will check for
incoming replies and call callback as necessary. The application may direct
Xlib explicitly to check for Record data with the XRecordProcessReplies
function."
Therefore it seems like the XRecordProcessReplies call is not needed, except in
cases such as: the applicagtion is shutting down, so you want to be sure the
Xlib event queue is empty.
I understand that you need to loop to keep the thread from exiting (because
XRecordEnableContextAsync does not block). The friendly and easy way to do
this would be:
while (running) {
//XRecordProcessReplies(disp_data); //optional, I think?
sleep(1); // this prevents 100% processor utilization
}
Please let me know what you think. In general, these types of loops cause 100%
processor utilization, so I have a feeling the sleep() call will fix the
problem.
Thanks for your help.
Original comment by postmark...@gmail.com
on 5 Feb 2013 at 3:43
I compiled with this change, and it solved the problem. Events are detected
more slowly now (because of the sleep), but for my application, that's ok.
In src/native/unix/NativeThread.c
while (running) {
XRecordProcessReplies(disp_data);
sleep(1); // this prevents 100% processor utilization
}
I think most users will want better performance, so I wouldn't mark this as
solved yet.
Is there a reason why XRECORD_ASYNC is defined? Can we use the synchronous
method instead?
Thanks.
Original comment by postmark...@gmail.com
on 5 Feb 2013 at 4:32
The reason XRECORD_ASYNC is defined is because the sync method of is broken
upstream. I will do some testing and see if I can figure out a solution.
Original comment by a...@1stleg.com
on 5 Feb 2013 at 7:49
So there doesn't appear to be a "good" solution to this problem. The reason
ASYNC is defined is outlined here
https://bugs.freedesktop.org/show_bug.cgi?id=42356 The short story is that you
cant stop it once it starts.
There are a few possible solutions:
Use pthread_yield or sched_yield. These appear pause when needed but also lead
to terrible performance.
Use sleep(1). This works fine but guarantees terrible performance.
Use usleep or nanosleep to pause execution for ~100MS. Will cause a short
delay in event delivery but will keep the cpu from burning. Drawback is that
it requires _POSIX_C_SOURCE >= 199309L.
You could also take a look at the sample code attached to the XRecord bug
report. I may have made a mistake in there due to some of the assumptions I
made that were not covered in the documentation.
The usleep or nanosleep method is probably the best approach until the bug is
fixed upstream and ASYNC can be undefined. I will add a simple implementation
to the SVN branch for 1.1 shortly.
Original comment by a...@1stleg.com
on 6 Feb 2013 at 6:18
Small update, using XSync(disp_data, false) instead of sleep(1) seems to
produce good results. Give it a try and let me know if you notice and adverse
effects particularly with registering and then un-registering the native hook.
Changes are available in the 1.1 branch.
http://jnativehook.googlecode.com/svn/branches/1.1/
Original comment by a...@1stleg.com
on 6 Feb 2013 at 7:08
The XSync update is a partial success. There are still several problems:
1) When I close the demo window, the program doesn't quit. I have to use
Ctrl-C in the console. The sleep version quits normally when I close the GUI.
2) When I'm mousing, the processor jumps to 40%. The sleep version is at 15%.
3) When I'm typing, the processor jumps to 20%. The sleep version is at 10%.
When I'm not typing or mousing, the usage is about the same between the two
versions. I also didn't have any problems registering and unregistering the
listeners (using the four checkboxes on the GUI).
Original comment by postmark...@gmail.com
on 6 Feb 2013 at 2:43
I have committed the nanosleep implementation for the time being. That looks
like it prevents the 100% CPU at idel without any side effects. The CPU still
seems to spike in the X process when events are received. Aside from the
XRecord processing, the LowLevelProc method is the one being called each time
an event is received. I tried commenting out the entire method and it seems to
supports my assertion that CPU is being eaten up by the XRecord extension. I
am going to leave this bug open until the upstream bug(s) are addressed. If
you figure out any additional information please post it here.
Original comment by a...@1stleg.com
on 6 Feb 2013 at 6:55
Mark, could you please share a .jar that you built after the change you
mentioned in #5 above?
We are facing these issues on linux systems after we integrated jnativehook
library in our in-house application. We need the version which avoids 100% CPU
utilization on linux and slow detection of events is Ok with our app. Thanks.
Original comment by avibham...@gmail.com
on 7 Feb 2013 at 7:41
Here is the jar with the nanosleep workaround. CPU at idle is low, however, it
does spike when events are received.
I am looking into the upstream XRecord issue to see if I can figure out a
better workaround.
Original comment by a...@1stleg.com
on 7 Feb 2013 at 7:48
Attachments:
Here is the jar I built with the 1 second delay, as described in #5 above.
Original comment by postmark...@gmail.com
on 8 Feb 2013 at 3:20
Attachments:
Small status update for those of you watching this bug. I have some test code
on my system that appears to work around the XRecordEnableContext (non-async)
not stopping. The problem is it's a seriously ugly hack that will need some
testing after integration and it will defiantly cause issues if fixed upstream,
however it does work for the current version of XRecord. I maybe able to add
some form of dynamic selection to work around the issue but I am not sure if
its worth the effort as it doesn't seem to produce a whole lot better CPU usage
than the current nanosleep workaround. I am still exploring a couple of other
possibilities including using some combination of pthread_kill() + sigaction()
or pthread_cancel() + pthread_cleanup_push/_pop().
Original comment by a...@1stleg.com
on 10 Feb 2013 at 1:38
I seem to have figured out a way to get the sync version of XRecord work as of
revision 694 (http://jnativehook.googlecode.com/svn/branches/1.1/). Please
test and let me know if it works for you.
Original comment by a...@1stleg.com
on 7 Mar 2013 at 12:51
This should be solved at this point. I will release 1.1.4 shortly.
Original comment by a...@1stleg.com
on 11 Mar 2013 at 11:16
Original comment by a...@1stleg.com
on 11 Mar 2013 at 11:16
Great work. Looking forward to next release specially with fixes for #37 and
#40.
Original comment by avibham...@gmail.com
on 12 Mar 2013 at 6:27
Original issue reported on code.google.com by
postmark...@gmail.com
on 5 Feb 2013 at 5:58