Skip Menu |

This queue is for tickets about the Mail-IMAPClient CPAN distribution.

Report information
The Basics
Id: 5962
Status: resolved
Priority: 0/
Queue: Mail-IMAPClient

People
Owner: Nobody in particular
Requestors: colin [...] spamjab.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



From: "Colin Robertson" <colin [...] spamjab.com>
To: bug-Mail-IMAPClient [...] rt.cpan.org
Subject: IMAPClient eats CPU while waiting for a response
Date: Wed, 7 Apr 2004 10:41:21 +0100
I've been using Mail::IMAPClient 2.2.9 for a while, and I've found a problem in its handling of a 0 timeout. Looking at the _read_line method, I see that when the timeout is set to 0 IMAPClient will poll as fast as it can to read new data. This means that it swallows up as many CPU cycles as it can get. This can be demonstrated by setting up an IMAP server that sends no response to a login command and attempting to connect with Mail::IMAPClient. Running top will show the client using all the CPU time on the system. As a suggestion, when the timeout is 0 it might be reasonable to call $self->{_select}->can_read with an arbitrary timeout and, when it returns an empty list, just call it again. This would drastically reduce the CPU usage in this case. colin
From: Jules Agee
[colin@spamjab.com - Wed Apr 7 05:41:32 2004]: Show quoted text
> I've been using Mail::IMAPClient 2.2.9 for a while, and I've found a > problem > in its handling of a 0 timeout. Looking at the _read_line method, I > see that > when the timeout is set to 0 IMAPClient will poll as fast as it can to > read > new data. This means that it swallows up as many CPU cycles as it can > get.
I ran into the same problem. Attached is da patch I used.
--- IMAPClient.pm 2004-11-26 23:56:07.000000000 -0800 +++ IMAPClient.pm.new 2004-11-24 18:01:04.000000000 -0800 @@ -1805,13 +1805,17 @@ sub _sysread { my $self = shift @_; if ( exists $self->{Readmethod} ) { return $self->Readmethod->($self,@_) ; } else { my($handle,$buffer,$count,$offset) = @_; - return sysread( $handle, $$buffer, $count, $offset); + my $retval = sysread( $handle, $$buffer, $count, $offset); + if ($! eq "Resource temporarily unavailable" ) { + CORE::select(undef, undef, undef, .001); + } + return $retval; } } =begin obsolete sub old_read_line {
On Wed Apr 07 05:41:32 2004, colin@spamjab.com wrote: Show quoted text
> As a suggestion, when the timeout is 0 it might be reasonable to call > $self->{_select}->can_read with an arbitrary timeout and, when it > returns an > empty list, just call it again. This would drastically reduce the CPU > usage in > this case.
New maintainer. I think that the solution is much simpler. The timeout parameter of select() makes a difference between 0 and undef. In case of 0, the select does not wait at all. For undef, it waits blocking. I think the latter is what is meant. In 2.99_02, the code will be: select( , , , $timeout||undef) -- MarkOv
probably working. Ticket closed.
Subject: [rt.cpan.org #5962] $timeout || undef doesn't seem to fix excessive CPU consumption
Date: Tue, 13 Nov 2007 13:19:02 -0500
To: bug-Mail-IMAPClient [...] rt.cpan.org
From: John Morrissey <jwm [...] horde.net>
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/ __(_)/_(_)________/ \_______(_) /_(_)__
Subject: Re: [rt.cpan.org #5962] $timeout || undef doesn't seem to fix excessive CPU consumption
Date: Wed, 14 Nov 2007 09:03:19 +0100
To: "jwm [...] horde.net via RT" <bug-Mail-IMAPClient [...] rt.cpan.org>
From: NLnet webmaster <webmaster [...] nlnet.nl>
* jwm@horde.net via RT (bug-Mail-IMAPClient@rt.cpan.org) [071113 18:19]: Show quoted text
> Queue: Mail-IMAPClient > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=5962 > > > 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:
This is a known problem. Try 2.99_06. It has a few dozen more useful fixes. -- MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions drs Mark A.C.J. Overmeer MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
Subject: Re: [rt.cpan.org #5962] $timeout || undef doesn't seem to fix excessive CPU consumption
Date: Wed, 14 Nov 2007 14:40:37 -0500
To: bug-Mail-IMAPClient [...] rt.cpan.org
From: John Morrissey <jwm [...] horde.net>
Show quoted text
> On Wed, 14 Nov 2007 09:03:19 +0100, NLnet webmaster wrote: > * jwm[...]horde.net via RT (bug-Mail-IMAPClient[...]rt.cpan.org) [071113 18:19]:
> > Queue: Mail-IMAPClient > > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=5962 > > > > > 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:
> > This is a known problem. Try 2.99_06. It has a few dozen more > useful fixes.
I'm using IMAPClient with imapsync. I grabbed Mail-IMAPClient-2.99_07 and imapsync-1.233 (the latest revisions of both). Unfortunately, all connections seem to time out: Can not open imap connection on [imap.example.com] with user [example] : Timeout after 30 seconds during read from server strace(1) output is thus: connect(3, {sa_family=AF_INET, sin_port=htons(143), sin_addr=inet_addr("1.2.3.4")}, 16) = 0 select(8, [3], NULL, NULL, {30, 0}) = 1 (in [3], left {29, 992000}) read(3, "* OK IMAP4 server (InterMail vM."..., 4096) = 111 select(8, [3], NULL, NULL, {30, 0}) = 0 (Timeout) This is more FWIW than anything; I'm going to stick to the older versions of Mail-IMAPClient (plus the artificial-delay kludge I mentioned earlier) and imapsync, since I just don't have the time to plumb this rabbit hole right now. john -- John Morrissey _o /\ ---- __o jwm@horde.net _-< \_ / \ ---- < \, www.horde.net/ __(_)/_(_)________/ \_______(_) /_(_)__
CC: mark [...] overmeer.net
Subject: [rt.cpan.org #5962] attempt at new Mail-IMAPClient revision
Date: Wed, 14 Nov 2007 15:53:47 -0500
To: bug-Mail-IMAPClient [...] rt.cpan.org
From: John Morrissey <jwm [...] horde.net>
Show quoted text
> On Wed, 14 Nov 2007 09:03:19 +0100, NLnet webmaster wrote: > * jwm[...]horde.net via RT (bug-Mail-IMAPClient[...]rt.cpan.org) [071113 18:19]:
> > Queue: Mail-IMAPClient > > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=5962 > > > > > 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:
> > This is a known problem. Try 2.99_06. It has a few dozen more > useful fixes.
I'm using IMAPClient with imapsync. I grabbed Mail-IMAPClient-2.99_07 and imapsync-1.233 (the latest revisions of both). Unfortunately, all connections seem to time out: Can not open imap connection on [imap.example.com] with user [example] : Timeout after 30 seconds during read from server strace(1) output is thus: connect(3, {sa_family=AF_INET, sin_port=htons(143), sin_addr=inet_addr("1.2.3.4")}, 16) = 0 select(8, [3], NULL, NULL, {30, 0}) = 1 (in [3], left {29, 992000}) read(3, "* OK IMAP4 server (InterMail vM."..., 4096) = 111 select(8, [3], NULL, NULL, {30, 0}) = 0 (Timeout) This is more FWIW than anything; I'm going to stick to the older versions of Mail-IMAPClient (plus the artificial-delay kludge I mentioned earlier) and imapsync, since I just don't have the time to plumb this rabbit hole right now. john -- John Morrissey _o /\ ---- __o jwm@horde.net _-< \_ / \ ---- < \, www.horde.net/ __(_)/_(_)________/ \_______(_) /_(_)__
When the users do not care, who am I to invest my sparse time in it?