There was a problem with this patch, which unlikely got noticed due to the fact that it would not have caused an error until you used the ReadWrite wheel with a depricated filter object. The test suite does not check this behavior, so all tests and all code I ran through passed, but never the less there would have been a problem given the right circumstances.

Attached is a patch for the readwrite wheel (post applying the patches previously sent to the mailing list) and a fixed wheel's patch, incase you haven't yet applied these patches. Any further feedback would be apprecicated.

- Scott

Scott wrote:

Hello POEple.

http://poe.perl.org/?POE_RFCs/Revise_call mentions adding a POE::Session->call() method, in part of the revision of call. This new session method is intended to deny cross-session calls, which as a side effect allows extended optimization of call() bypassing garbage collection checks, as it is forced to return to a state within the same session.

After a little testing and a little thinking, I realized this could be used to speed up current POE as a whole, by utilizing this new session call() method in the POE::Wheels. So I decided to impliment this method. My personal benchmarks show it is in fact considerably faster.

Benchmark:
timing 1000000 iterations of
POE::Kernel->call(), POE::Session->call()
...

POE::Kernel->call(): 60 wallclock secs (50.39 usr + 0.22 sys = 50.61 CPU) @ 19758.94/s (n=1000000)

POE::Session->call(): 29 wallclock secs (25.64 usr + 0.01 sys = 25.65 CPU) @ 38986.35/s (n=1000000)

With these changes applied, all tests pass on my system.

All tests successful, 12 subtests skipped.
Files=40, Tests=3171, 101 wallclock secs (12.45 cusr + 0.49 csys = 12.94 CPU)


Attached is the code used for this benchmark, as well as patches which add the call() method to POE::Session, and also utilize this method in all of the current POE::Wheels packaged with the POE distribution, and the output of the test suite. If anyone has any doubts as to weither or not this is in fact a good idea, or if anyone has any objections or conditions of its implimentation prior to being applied to the current cvs tree, please let me know. I will try to meet all prerequesites, as I would like to see this patch applied in the next release.

- Scott


--- ReadWrite.pm.broked	2004-02-09 17:57:06.000000000 -0800
+++ ReadWrite.pm	2004-02-09 17:57:41.000000000 -0800
@@ -489,7 +489,7 @@
   else {
     if (defined $buf) {
       foreach my $cooked_input (@{$self->[FILTER_INPUT]->get($buf)}) {
-        $poe_kernel->get_active_session()->calli
+        $poe_kernel->get_active_session()->call
             ( $self->[EVENT_INPUT], $cooked_input, $self->[UNIQUE_ID] );
       }
     }
Common subdirectories: poe/lib/POE/Wheel/CVS and poe.session.call/lib/POE/Wheel/CVS
diff -u poe/lib/POE/Wheel/Curses.pm poe.session.call/lib/POE/Wheel/Curses.pm
--- poe/lib/POE/Wheel/Curses.pm	2003-11-20 21:08:26.000000000 -0800
+++ poe.session.call/lib/POE/Wheel/Curses.pm	2004-02-07 21:45:28.000000000 -0800
@@ -96,7 +96,7 @@
           # determined that STDIN has something for us.  Be explicit
           # about which getch() to use.
           while ((my $keystroke = Curses::getch) ne '-1') {
-            $k->call( $me, $$event_input, $keystroke, $unique_id );
+            $me->call( $$event_input, $keystroke, $unique_id );
           }
         }
       );
diff -u poe/lib/POE/Wheel/FollowTail.pm poe.session.call/lib/POE/Wheel/FollowTail.pm
--- poe/lib/POE/Wheel/FollowTail.pm	2004-01-28 15:19:11.000000000 -0800
+++ poe.session.call/lib/POE/Wheel/FollowTail.pm	2004-02-07 21:45:10.000000000 -0800
@@ -257,7 +257,7 @@
             TRACE_POLL and warn time . " raw input";
             foreach my $cooked_input (@{$filter->get($raw_input)}) {
               TRACE_POLL and warn time . " cooked input";
-              $k->call($ses, $$event_input, $cooked_input, $unique_id);
+              $ses->call($$event_input, $cooked_input, $unique_id);
             }
           }
         }
@@ -268,7 +268,7 @@
           if ($! or (-S $handle) or (-t $handle)) {
             TRACE_POLL and warn time . " error: $!";
             $$event_error and
-              $k->call($ses, $$event_error, 'read', ($!+0), $!, $unique_id);
+              $ses->call($$event_error, 'read', ($!+0), $!, $unique_id);
             $k->select($handle);
           }
           eval { IO::Handle::clearerr($handle) }; # could be a globref
@@ -326,7 +326,7 @@
               # File shrank.  Consider it a reset.  Seek to the top of
               # the file.
               if ($new_stat[7] < $last_stat->[7]) {
-                $$event_reset and $k->call($ses, $$event_reset, $unique_id);
+                $$event_reset and $ses->call($$event_reset, $unique_id);
                 sysseek($handle, 0, SEEK_SET);
               }
 
@@ -357,7 +357,7 @@
                 close $handle;
                 unless (open $handle, "<$filename") {
                   $$event_error and
-                    $k->call( $ses, $$event_error, 'reopen',
+                    $ses->call( $$event_error, 'reopen',
                               ($!+0), $!, $unique_id
                             );
                 }
@@ -375,7 +375,7 @@
             TRACE_POLL and warn time . " raw input\n";
             foreach my $cooked_input (@{$filter->get($raw_input)}) {
               TRACE_POLL and warn time . " cooked input\n";
-              $k->call($ses, $$event_input, $cooked_input, $unique_id);
+              $ses->call($$event_input, $cooked_input, $unique_id);
             }
           }
           $k->yield($state_read);
@@ -387,7 +387,7 @@
           if ($!) {
             TRACE_POLL and warn time . " error: $!\n";
             $$event_error and
-              $k->call($ses, $$event_error, 'read', ($!+0), $!, $unique_id);
+              $ses->call($$event_error, 'read', ($!+0), $!, $unique_id);
             $k->select($handle);
           }
           $k->delay($state_read, $poll_interval);
diff -u poe/lib/POE/Wheel/ListenAccept.pm poe.session.call/lib/POE/Wheel/ListenAccept.pm
--- poe/lib/POE/Wheel/ListenAccept.pm	2003-11-25 19:52:07.000000000 -0800
+++ poe.session.call/lib/POE/Wheel/ListenAccept.pm	2004-02-07 21:44:18.000000000 -0800
@@ -115,11 +115,11 @@
         my $peer = accept($new_socket, $handle);
 
         if ($peer) {
-          $k->call($me, $$event_accept, $new_socket, $peer, $unique_id);
+          $me->call($$event_accept, $new_socket, $peer, $unique_id);
         }
         elsif ($! != EWOULDBLOCK) {
           $$event_error &&
-            $k->call($me, $$event_error, 'accept', ($!+0), $!, $unique_id);
+            $me->call($$event_error, 'accept', ($!+0), $!, $unique_id);
         }
       }
     );
diff -u poe/lib/POE/Wheel/ReadWrite.pm poe.session.call/lib/POE/Wheel/ReadWrite.pm
--- poe/lib/POE/Wheel/ReadWrite.pm	2004-01-24 17:54:58.000000000 -0800
+++ poe.session.call/lib/POE/Wheel/ReadWrite.pm	2004-02-07 21:39:56.000000000 -0800
@@ -206,7 +206,7 @@
 
         # When you can't write, nothing else matters.
         if ($!) {
-          $$event_error && $k->call( $me, $$event_error,
+          $$event_error && $me->call( $$event_error,
                                      'write', ($!+0), $!, $unique_id
                                    );
           $k->select_write($handle);
@@ -222,7 +222,7 @@
           if ($$is_in_high_water_state) {
             if ( $$driver_buffered_out_octets <= $low_mark ) {
               $$is_in_high_water_state = 0;
-              $k->call( $me, $$event_low, $unique_id ) if defined $$event_low;
+              $me->call( $$event_low, $unique_id ) if defined $$event_low;
             }
           }
 
@@ -236,7 +236,7 @@
                   ( $$driver_buffered_out_octets >= $high_mark )
                 ) {
             $$is_in_high_water_state = 1;
-            $k->call( $me, $$event_high, $unique_id ) if defined $$event_high;
+            $me->call( $$event_high, $unique_id ) if defined $$event_high;
           }
         }
 
@@ -246,7 +246,7 @@
         # is 1).
         unless ($$driver_buffered_out_octets) {
           $k->select_pause_write($handle);
-          $$event_flushed && $k->call($me, $$event_flushed, $unique_id);
+          $$event_flushed && $me->call($$event_flushed, $unique_id);
         }
       }
    );
@@ -299,13 +299,13 @@
                 my $next_rec = $$input_filter->get_one();
                 last unless @$next_rec;
                 foreach my $cooked_input (@$next_rec) {
-                  $k->call($me, $$event_input, $cooked_input, $unique_id);
+                  $me->call($$event_input, $cooked_input, $unique_id);
                 }
               }
             }
             else {
               $$event_error and
-                $k->call( $me, $$event_error, 'read', ($!+0), $!, $unique_id );
+                $me->call( $$event_error, 'read', ($!+0), $!, $unique_id );
               $k->select_read($handle);
             }
           }
@@ -327,12 +327,12 @@
             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
             if (defined(my $raw_input = $driver->get($handle))) {
               foreach my $cooked_input (@{$$input_filter->get($raw_input)}) {
-                $k->call($me, $$event_input, $cooked_input, $unique_id);
+                $me->call($$event_input, $cooked_input, $unique_id);
               }
             }
             else {
               $$event_error and
-                $k->call( $me, $$event_error, 'read', ($!+0), $!, $unique_id );
+                $me->call( $$event_error, 'read', ($!+0), $!, $unique_id );
               $k->select_read($handle);
             }
           }
@@ -478,10 +478,8 @@
         my $next_rec = $self->[FILTER_INPUT]->get_one();
         last unless @$next_rec;
         foreach my $cooked_input (@$next_rec) {
-          $poe_kernel->call( $poe_kernel->get_active_session(),
-                             $self->[EVENT_INPUT],
-                             $cooked_input, $self->[UNIQUE_ID]
-                           );
+          $poe_kernel->get_active_session()->call
+              ( $self->[EVENT_INPUT], $cooked_input, $self->[UNIQUE_ID] );
         }
       }
     }
@@ -491,10 +489,8 @@
   else {
     if (defined $buf) {
       foreach my $cooked_input (@{$self->[FILTER_INPUT]->get($buf)}) {
-        $poe_kernel->call( $poe_kernel->get_active_session(),
-                           $self->[EVENT_INPUT],
-                           $cooked_input, $self->[UNIQUE_ID]
-                         );
+        $poe_kernel->get_active_session()->call
+            ( $self->[EVENT_INPUT], $cooked_input, $self->[UNIQUE_ID] );
       }
     }
   }
diff -u poe/lib/POE/Wheel/Run.pm poe.session.call/lib/POE/Wheel/Run.pm
--- poe/lib/POE/Wheel/Run.pm	2004-01-28 15:19:13.000000000 -0800
+++ poe.session.call/lib/POE/Wheel/Run.pm	2004-02-07 21:47:51.000000000 -0800
@@ -512,7 +512,7 @@
 
         # When you can't write, nothing else matters.
         if ($!) {
-          $$error_event && $k->call( $me, $$error_event,
+          $$error_event && $me->call( $$error_event,
                                      'write', ($!+0), $!, $unique_id, "STDIN"
                                    );
           $k->select_write($handle);
@@ -525,7 +525,7 @@
           # All chunks written; fire off a "flushed" event.
           unless ($$stdin_octets) {
             $k->select_pause_write($handle);
-            $$stdin_event && $k->call($me, $$stdin_event, $unique_id);
+            $$stdin_event && $me->call($$stdin_event, $unique_id);
           }
         }
       }
@@ -577,17 +577,17 @@
                 my $next_rec = $stdout_filter->get_one();
                 last unless @$next_rec;
                 foreach my $cooked_input (@$next_rec) {
-                  $k->call($me, $$stdout_event, $cooked_input, $unique_id);
+                  $me->call($$stdout_event, $cooked_input, $unique_id);
                 }
               }
             }
             else {
               $$error_event and
-                $k->call( $me, $$error_event,
+                $me->call( $$error_event,
                           'read', ($!+0), $!, $unique_id, 'STDOUT'
                         );
               unless (--$$is_active) {
-                $k->call( $me, $$close_event, $unique_id )
+                $me->call( $$close_event, $unique_id )
                   if defined $$close_event;
               }
               $k->select_read($handle);
@@ -608,16 +608,16 @@
             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
             if (defined(my $raw_input = $driver->get($handle))) {
               foreach my $cooked_input (@{$stdout_filter->get($raw_input)}) {
-                $k->call($me, $$stdout_event, $cooked_input, $unique_id);
+                $me->call($$stdout_event, $cooked_input, $unique_id);
               }
             }
             else {
               $$error_event and
-                $k->call( $me, $$error_event,
+                $me->call( $$error_event,
                           'read', ($!+0), $!, $unique_id, 'STDOUT'
                         );
               unless (--$$is_active) {
-                $k->call( $me, $$close_event, $unique_id )
+                $me->call( $$close_event, $unique_id )
                   if defined $$close_event;
               }
               $k->select_read($handle);
@@ -673,17 +673,17 @@
                 my $next_rec = $stderr_filter->get_one();
                 last unless @$next_rec;
                 foreach my $cooked_input (@$next_rec) {
-                  $k->call($me, $$stderr_event, $cooked_input, $unique_id);
+                  $me->call($$stderr_event, $cooked_input, $unique_id);
                 }
               }
             }
             else {
               $$error_event and
-                $k->call( $me, $$error_event,
+                $me->call( $$error_event,
                           'read', ($!+0), $!, $unique_id, 'STDERR'
                         );
               unless (--$$is_active) {
-                $k->call( $me, $$close_event, $unique_id )
+                $me->call( $$close_event, $unique_id )
                   if defined $$close_event;
               }
               $k->select_read($handle);
@@ -704,16 +704,16 @@
             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
             if (defined(my $raw_input = $driver->get($handle))) {
               foreach my $cooked_input (@{$stderr_filter->get($raw_input)}) {
-                $k->call($me, $$stderr_event, $cooked_input, $unique_id);
+                $me->call($$stderr_event, $cooked_input, $unique_id);
               }
             }
             else {
               $$error_event and
-                $k->call( $me, $$error_event,
+                $me->call( $$error_event,
                           'read', ($!+0), $!, $unique_id, 'STDERR'
                         );
               unless (--$$is_active) {
-                $k->call( $me, $$close_event, $unique_id )
+                $me->call( $$close_event, $unique_id )
                   if defined $$close_event;
               }
               $k->select_read($handle);
@@ -898,10 +898,8 @@
         my $next_rec = $old_output_filter->get_one();
         last unless @$next_rec;
         foreach my $cooked_input (@$next_rec) {
-          $poe_kernel->call( $poe_kernel->get_active_session(),
-                             $self->[EVENT_STDOUT],
-                             $cooked_input, $self->[UNIQUE_ID]
-                           );
+          $poe_kernel->get_active_session()->call
+              ( $self->[EVENT_STDOUT], $cooked_input, $self->[UNIQUE_ID] );
         }
       }
     }
@@ -909,10 +907,8 @@
     # Otherwise use the old get() behavior.
     else {
       foreach my $cooked_input (@{$self->[FILTER_STDOUT]->get($buf)}) {
-        $poe_kernel->call( $poe_kernel->get_active_session(),
-                           $self->[EVENT_STDOUT],
-                           $cooked_input, $self->[UNIQUE_ID]
-                         );
+        $poe_kernel->get_active_session()->call
+            ( $self->[EVENT_STDOUT], $cooked_input, $self->[UNIQUE_ID] );
       }
     }
   }
@@ -940,10 +936,8 @@
         my $next_rec = $old_output_filter->get_one();
         last unless @$next_rec;
         foreach my $cooked_input (@$next_rec) {
-          $poe_kernel->call( $poe_kernel->get_active_session(),
-                             $self->[EVENT_STDERR],
-                             $cooked_input, $self->[UNIQUE_ID]
-                           );
+          $poe_kernel->get_active_session()->call
+              ( $self->[EVENT_STDERR], $cooked_input, $self->[UNIQUE_ID] );
         }
       }
     }
@@ -951,10 +945,8 @@
     # Otherwise use the old get() behavior.
     else {
       foreach my $cooked_input (@{$self->[FILTER_STDERR]->get($buf)}) {
-        $poe_kernel->call( $poe_kernel->get_active_session(),
-                           $self->[EVENT_STDERR],
-                           $cooked_input, $self->[UNIQUE_ID]
-                         );
+        $poe_kernel->get_active_session()->call
+            ( $self->[EVENT_STDERR], $cooked_input, $self->[UNIQUE_ID] );
       }
     }
   }
diff -u poe/lib/POE/Wheel/SocketFactory.pm poe.session.call/lib/POE/Wheel/SocketFactory.pm
--- poe/lib/POE/Wheel/SocketFactory.pm	2003-11-25 19:52:07.000000000 -0800
+++ poe.session.call/lib/POE/Wheel/SocketFactory.pm	2004-02-07 21:48:20.000000000 -0800
@@ -204,14 +204,14 @@
           else {
             die "sanity failure: socket domain == $domain";
           }
-          $k->call( $me, $$event_success,
+          $me->call( $$event_success,
                     $new_socket, $peer_addr, $peer_port,
                     $unique_id
                   );
         }
         elsif ($! != EWOULDBLOCK) {
           $$event_failure &&
-            $k->call( $me, $$event_failure,
+            $me->call( $$event_failure,
                       'accept', ($!+0), $!, $unique_id
                     );
         }
@@ -271,7 +271,7 @@
         $! = unpack('i', getsockopt($handle, SOL_SOCKET, SO_ERROR));
         if ($!) {
           (defined $$event_failure) and
-            $k->call( $me, $$event_failure,
+            $me->call( $$event_failure,
                       'connect', ($!+0), $!, $unique_id
                     );
           return;
@@ -281,7 +281,7 @@
         my $peer = getpeername($handle);
         if ($!) {
           (defined $$event_failure) and
-            $k->call( $me, $$event_failure,
+            $me->call( $$event_failure,
                       'getpeername', ($!+0), $!, $unique_id
                     );
           return;
@@ -330,7 +330,7 @@
         }
 
         # Tell the session it went okay.  Also let go of the socket.
-        $k->call( $me, $$event_success,
+        $me->call( $$event_success,
                   $handle, $peer_addr, $peer_port, $unique_id
                 );
       }
@@ -361,7 +361,7 @@
           $! = unpack('i', getsockopt($handle, SOL_SOCKET, SO_ERROR));
           if ($!) {
             (defined $$event_failure) and
-              $k->call( $me, $$event_failure,
+              $me->call( $$event_failure,
                         'connect', ($!+0), $!, $unique_id
                       );
             return;

Reply via email to