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;
