I noticed this behavior recently, with IMAPClient 2.2.9.
strace(1) shows the socket in non-blocking mode and IMAPClient in a tight
loop trying to read the server's response:
read(3, "* 1 FETCH (FLAGS (\\Seen) UID 100"..., 4096) = 36
read(3, "169 OK UID FETCH completed\r\n", 4096) = 28
write(5, "266 UID store 1 +FLAGS (\\Seen)\r\n", 32) = 32
read(5, 0x85f5698, 4096) = -1 EAGAIN (Resource temporarily unavailable)
read(5, 0x85f5698, 4096) = -1 EAGAIN (Resource temporarily unavailable)
read(5, 0x85f5698, 4096) = -1 EAGAIN (Resource temporarily unavailable)
read(5, 0x85f5698, 4096) = -1 EAGAIN (Resource temporarily unavailable)
read(5, 0x85f5698, 4096) = -1 EAGAIN (Resource temporarily unavailable)
read(5, 0x85f5698, 4096) = -1 EAGAIN (Resource temporarily unavailable)
As mentioned in this bug, I tried changing the timeout arguments to
CORE::select() to '$timeout || undef', but this did not seem to have any
impact on CPU consumption (sorry, the diff is backward):
--- IMAPClient.pm 2007-11-09 19:52:28.000000000 +0000
+++ IMAPClient.pm.orig 2007-11-09 19:40:06.000000000 +0000
@@ -1690,7 +1690,7 @@
unless ( CORE::select( $ready = $rvec,
undef,
$errors = $rvec,
- $timeout || undef)
+ $timeout)
) {
# Select failed; that means bad news.
# Better tell someone.
@@ -1966,7 +1962,7 @@
unless ( CORE::select( $ready = $rvec,
undef,
$errors = $rvec,
- $timeout || undef)
+ $timeout)
) {
# Select failed; that means bad news.
# Better tell someone.
but this had no effect on CPU consumption. Jules Agee's proposed solution
(Sat Nov 27 03:40:50 2004) decreases CPU consumption *dramatically* by
sleeping for a small amount of time between EAGAIN read() calls. FWIW, I'll
post the exact diff we used (again, sorry for the backward diff):
--- IMAPClient.pm 2007-11-09 19:52:28.000000000 +0000
+++ IMAPClient.pm.orig 2007-11-09 19:40:06.000000000 +0000
@@ -1813,11 +1813,7 @@
return $self->Readmethod->($self,@_) ;
} else {
my($handle,$buffer,$count,$offset) = @_;
- my $retval = sysread( $handle, $$buffer, $count, $offset);
- if ($! eq "Resource temporarily unavailable") {
- CORE::select(undef, undef, undef, .001);
- }
- return $retval;
+ return sysread( $handle, $$buffer, $count, $offset);
}
}
This change drops CPU usage from 100% to 10-15% at peak, 5-8% typical. I
didn't try using a longer timeout to see what effect that had.
john
--
John Morrissey _o /\ ---- __o
jwm@horde.net _-< \_ / \ ---- < \,
www.horde.net/ __(_)/_(_)________/ \_______(_) /_(_)__