Good morning starshine,

The other day Artur Bergman described to me a patch for
POE::Wheel::Readwrite that triggers a flush of a handle automatically
when you put() and a few conditions are met. The end result is a huge
improvement speed-wise. The problem is that it changes some semantics of
the wheel.

Does anyone depend on get_driver_out_octets and get_driver_out_messages
as in the following example?

my $wheel = POE::Wheel::ReadWrite->new( yadda );
$wheel->put( 'DATA' );
my $pending_octets = $wheel->get_driver_out_octets();
my $pending_messages = $wheel->get_driver_out_messages();

In current poe:
$pending_octets = 4
$pending_messages = 1

With this patch this is no longer deterministic. The result is:
$pending_octets <= 4
$pending_messages <= 1

The real result depends on how much buffer space is still free on the
handle.

I also have graphs showing that the result is indeed faster: (SVG only
for this first pass)
http://hachi.kuiki.net/stuff/bench-hachi-embedded.svg
http://hachi.kuiki.net/stuff/bench-xantus.svg

Blue is patched, Red is not
The X axis is ticked in units of one and describes the message size
doubling for each tick. (ie. 1, 2, 4, 8, 16)
The Y axis is bytes/second throughput, I've forgotten what the ticks are
at (something like 1000000 bytes/sec)

As you can see, the patch is obviously faster until you hit message
sizes of about 2^15 bytes (32768 bytes) where the graph begins to
go haywire. I'm going to study the results a bit more, make some more
graphs with labels.

Anyone got better ideas? take a peek at the patch, attached.

Cheers,
Jonathan Steinert
? CHANGES
? META.yml
? fasttest.pl
? foo
? poe.diff
? rt15215.pl
? sky.patch
Index: lib/POE/Wheel/ReadWrite.pm
===================================================================
RCS file: /cvsroot/poe/poe/lib/POE/Wheel/ReadWrite.pm,v
retrieving revision 1.73
diff -u -r1.73 ReadWrite.pm
--- lib/POE/Wheel/ReadWrite.pm  29 Aug 2005 20:35:04 -0000      1.73
+++ lib/POE/Wheel/ReadWrite.pm  21 Jan 2006 04:19:10 -0000
@@ -28,6 +28,7 @@
 sub STATE_WRITE                () { 14 }
 sub STATE_READ                 () { 15 }
 sub UNIQUE_ID                  () { 16 }
+sub SESSION_ID                () { 17 }
 
 sub CRIMSON_SCOPE_HACK ($) { 0 }
 
@@ -130,6 +131,7 @@
     undef,                            # STATE_READ
     # Unique ID.
     &POE::Wheel::allocate_wheel_id(), # UNIQUE_ID
+    $poe_kernel->get_active_session()->ID()    # SESSION_ID
   ], $type;
 
   if (scalar keys %params) {
@@ -416,16 +418,24 @@
 sub put {
   my ($self, @chunks) = @_;
 
+  my $driver = $self->[DRIVER_BOTH];
+  my $handle = $self->[HANDLE_OUTPUT];
+
   my $old_buffered_out_octets = $self->[DRIVER_BUFFERED_OUT_OCTETS];
   my $new_buffered_out_octets =
-    $self->[DRIVER_BUFFERED_OUT_OCTETS] =
-    $self->[DRIVER_BOTH]->put($self->[FILTER_OUTPUT]->put([EMAIL PROTECTED]));
+    $driver->put($self->[FILTER_OUTPUT]->put([EMAIL PROTECTED]));
 
   # Resume write-ok if the output buffer gets data.  This avoids
   # redundant calls to select_resume_write(), which is probably a good
   # thing.
   if ($new_buffered_out_octets and !$old_buffered_out_octets) {
-    $poe_kernel->select_resume_write($self->[HANDLE_OUTPUT]);
+    if ($self->[DRIVER_BUFFERED_OUT_OCTETS] = $driver->flush( $handle )) {
+      $poe_kernel->select_resume_write($handle);
+    }
+    else {
+      $self->[EVENT_FLUSHED] and
+        $poe_kernel->post($self->[SESSION_ID], $self->[EVENT_FLUSHED], 
$self->[UNIQUE_ID]);
+    }
   }
 
   # If the high watermark has been reached, return true.

Reply via email to