GNOME Bugzilla – Bug 653140
gmain: use Linux eventfd() for main context wake up
Last modified: 2011-06-22 03:28:47 UTC
The Linux eventfd() call is basically tailor made for the main loop wake up pipe - all we want is a threadsafe way to write to a file descriptor, and wake up the context on the other end; we don't care about the content at all. The eventfd manual page basically explains the benefits: Applications can use an eventfd file descriptor instead of a pipe (see pipe(2)) in all cases where a pipe is used simply to signal events. The kernel overhead of an eventfd file descriptor is much lower than that of a pipe, and only one file descriptor is required (versus the two required for a pipe). When writing my multithreaded spawn test case I actually hit the 1024 file descriptor limit quickly, because we used 2 fds per main context. This brings that down to 1.
Created attachment 190400 [details] [review] gmain: use Linux eventfd() for main context wake up
Can we use this for GCancellable ? They currently use pipes too, iirc; and that is a place where you are much more likely to hit the fd limit...
Review of attachment 190400 [details] [review]: ::: glib/gmain.c @@ +579,3 @@ + efd = eventfd (0, EFD_CLOEXEC); + if (efd == -1 && errno == ENOSYS) + { Any reason to special-case ENOSYS here ? Also, ENOSYS is not documented as a possible error in eventfd(2)... @@ +2995,1 @@ } Looks like we lost a #ifndef G_OS_WIN32 here ?
Created attachment 190406 [details] [review] gmain: use Linux eventfd() for main context wake up Fix accidentally removed #ifndef G_OS_WIN32
Created attachment 190407 [details] [review] GCancellable: Use Linux eventfd() instead of pipe See commit f626dd2b4311bd82137c5b208ab2de288c3e6fae for rationale; basically it's cheaper than a pipe.
(In reply to comment #3) > > Any reason to special-case ENOSYS here ? > Also, ENOSYS is not documented as a possible error in eventfd(2)... Yeah, the idea is to handle the case of old kernels. > @@ +2995,1 @@ > } > > Looks like we lost a #ifndef G_OS_WIN32 here ? Fixed.
Review of attachment 190406 [details] [review]: Looks good, apart from the cross-compilation question. One thing I'm curious about, though: You say this is more performant ? Is this measurable ? If yes, I'd very much like to see a performance test to demonstrate this go in along with the change. ::: configure.ac @@ +2606,3 @@ +AC_MSG_CHECKING([for eventfd(2) system call]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ We should probably have an AC_CACHE_CHECK around this to help cross compilers, like we do for other instances of AC_COMPILE_IFELSE ?
Review of attachment 190407 [details] [review]: Looks good. Out of interest: do we have cancellation of GCancellable under unit test ?
yes, the unix-streams test tests multi-threaded cancellation
(In reply to comment #7) > > One thing I'm curious about, though: You say this is more performant ? Is this > measurable ? If yes, I'd very much like to see a performance test to > demonstrate this go in along with the change. I'm not even going to try looking at the difference in terms of CPU/memory overhead, I don't expect it to be noticeable relative to all the other crap we're doing. The main benefit is really just having 1 fd instead of two. The current Linux default of 1024 fds is really pretty silly in 2011 where phones have 512MB+ of RAM, and is likely to change, but we can't rely hard on that for a while yet. If you're into small scale optimization though, just compare linux/fs/pipe.c and linux/fs/eventfd.c. Pipes have to deal with allocating pages, etc., whereas eventfd boils down to a mutex around a simple struct with a uint64_t. > We should probably have an AC_CACHE_CHECK around this to help cross compilers, > like we do for other instances of AC_COMPILE_IFELSE ? To be honest I copied it from the futex() check. I'll do a patch.
Attachment 190406 [details] pushed as 3904c87 - gmain: use Linux eventfd() for main context wake up Attachment 190407 [details] pushed as fa87399 - GCancellable: Use Linux eventfd() instead of pipe