I wrote a system which uses Storable::freeze() to serialize a data structure. It then uses IPC::Open2 and IO::Handle to spawn multiple child processes and write to them, reading back a status from each one.

When this runs, the children are causing huge CPU load (according to top), even when nothing is being read. I can't figure out why, probably due to my inexperience with IPC. I have RTFM'ed just about every IPC document I could get my hands on. There are multiple parents running at any given time and each parent will spawn any number of children. Right now, I'm experimenting with 10 children per parent. Some code for your review is below.

My question is: Is there something I'm missing in this code that would cause the CPUs to churn even when simply selecting and reading? Or is there something else I'm just not seeing? Snippets from the parent:
my ($readHandle, $writeHandle) = (IO::Handle->new, IO::Handle->new +); my $pid = open2($readHandle, $writeHandle, @command); $readHandle->autoflush(1); $readHandle->blocking(0); $writeHandle->autoflush(1); $writeHandle->blocking(0);
and later in the code...
## $messageForProcessing is a data structure stored as a hash refe +rence my $frozenMessage = freeze($messageForProcessing); print $writeHandle $frozenMessage . qq|\n| . $this->_messageDelimi +ter();
The children that are spawned have a method to read the data from the parent and process it (modified a bit to remove business logic):
sub processMessages { my ($this) = @_; my $endTime = time + $ENV{'MAX_LIFETIME'}; select STDOUT; $|++; # make unbuffered my $select = IO::Select->new(); $select->add(\*STDIN); my $messageDelimiter = $this->_messageDelimiter(); my $delimiterMatch = qr{\n$messageDelimiter$}; my $frozenMessage; my $messageToProcess = {}; my $stopNow = 0; while(time < $endTime) { my $offset; my ($handle) = $select->can_read(5); my $previousRead; while( ($handle) && (my $bytes = $handle->sysread($frozenMessage, 8192, $offse +t)) ) { $offset += $bytes; ## Because Storable may put newlines in the frozen object, + ## delimit messages: my $searchableText = $previousRead . $frozenMessage; if($searchableText =~ /$delimiterMatch/) { $frozenMessage =~ s/$delimiterMatch//; $messageToProcess = thaw($frozenMessage); } $previousRead = $frozenMessage; if(%$messageToProcess) { ### DO MESSAGE PROCESSING HERE ## my $outputMessage; if($processor->hasErrors()) { my $errors = $processor->getErrors(); $outputMessage = qq|$$ ERROR $errors->[0]\n|; } else { my $messageID = $processor->lastMessageID(); $outputMessage = qq|$$ SUCCESS $messageID\n|; } ## Write status back to the parent print STDOUT $outputMessage; $offset = 0; undef($frozenMessage); undef($previousRead); undef(%$messageToProcess); } } } }
At any given time, at least 5 children are running using 10% or more of CPU, up to 95%. strace on their processes shows that this might be the case even when they are not reading any data:
Process 22515 attached - interrupt to quit select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0 select(8, [0], NULL, NULL, {5, 0}) = 1 (in [0], left {5, 0}) read(0, "", 8192) = 0

In reply to Performance and CPU load: sysread, IO::Select and/or Storable::thaw by DBX

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.