Report: Threaded udevd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



As hinted earlier, I'm working on a threaded version of udevd.  The idea
is to processes events in threads, instead of forking a process for each
event.  I'm offended by how much cpu time udev takes during boot, and
this inefficiency seems to be the biggest culprit.

Patches will be posted as replies.

== Result ==

I've succeeded in reducing the overall cpu usage of the udevd process by
45% on my EeePC.  This is measured by oprofile using "udevadm trigger"
on a running system.

Unfortunately, bootchart shows it only reduces the real time by 0.6
seconds out of a total of 2.4 seconds in the udev initscript - thats
25%.  The difference is mainly due to 160 calls to modprobe.  This is
using the recently released modprobe release 3.5, which has optimised
binary index files.  Future optimisations might include a "modprobe daemon".

== Caveats ==

I've finished polishing this first version and fixed all the bugs I
found, but there could be some more :).  In particular, I still need to
verify that all the library functions it calls are reentrant.  The
libudev calls should be fine, but I'm not certain that all the standard
C library calls are safe.

It depends on pthreads being available - at the moment they are
compulsory.  It should be straightforward to make threading optional at
build time though.

To build with pthreads I use "acx_pthreads.m4", which is licensed under
the GPL3 with a special autoconf exception.  I think the intent of the
license is to make the file itself is GPL3, but leave the derived
configure script freely distributable.  It sounds ok, but I wouldn't
merge it without a more authoritative answer.

Timeouts are treated differently, and have not been tested.  Instead of
setting a timeout for the event as a whole, each external program is run
with a timeout.  If the timeout expires, the program is treated as if it
failed - instead of just aborting the event process.

== Justification for udev-exec ==

External programs are run from a "udev-exec" subprocess.  This was
measured as reducing the fork() overhead.  To reduce overheads further,
it allowed me to use of vfork() without temporarily suspending all the
threads.  The commands to run are passed over a unix datagram socket;
pipes for stdout / stderr pipes are passed as ancillary data.  This
udev-exec accounts for over half the code.  The message passing
shouldn't impose too much overhead.  I think udev-exec should be used
even if threading has been disabled, otherwise there would be too many
ugly #ifdefs.

udev-exec also avoids running external programs with extra file
descriptors - the problem "close on exec" was designed to solve.  I
don't think I could insist on a kernel recent enough to provide "close
on exec" support.  Plus I don't think "close on exec" helps with pipes
used to communicate with child processes.  Without this, the Ubuntu
"watershed" command seemed to complain about extra file descriptors.

Lastly, udev-exec helped with implementing timeouts - event threads just
call select() with a timeout, waiting to read the exitcode of the
command from a pipe.  None of the wait() family of commands include a
timeout.  alarm() wouldn't work because it's per-process.  Without
udev-exec, I would have to create posix timers with callbacks to signal
the correct thread - and disable SA_RESTART before waiting.

--
To unsubscribe from this list: send the line "unsubscribe linux-hotplug" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [Linux DVB]     [Asterisk Internet PBX]     [DCCP]     [Netdev]     [X.org]     [Util Linux NG]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux