Skip to content

Commit

Permalink
* Cherry pick performance idea from PR stevan#61
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuelsmann committed May 16, 2019
1 parent ac7e29c commit c836493
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 16 deletions.
44 changes: 39 additions & 5 deletions lib/Promises/Deferred/AE.pm
Expand Up @@ -8,13 +8,47 @@ use AE;

use parent 'Promises::Deferred';

# Before the pipe-based approach used below, there was an AE::postpone-based
# approach for _notify_backend. The current code is much more performant:

# Original code (on a laptop on battery power):
# Backend: Promises::Deferred::AE
# Benchmark: running one, two for at least 10 CPU seconds...
# one: 44 wallclock secs @ 3083.99/s (n=31210)
# two: 29 wallclock secs @ 1723.66/s (n=17340)

# New approach:
# Backend: Promises::Deferred::AE
# Benchmark: running one, two for at least 10 CPU seconds...
# one: 11 wallclock secs @ 10457.90/s (n=108553)
# two: 11 wallclock secs @ 3878.69/s (n=40959)


my ($socket_pid, $socket_send, $socket_recv, $socket_io,
$read_buf, @io_callbacks);

sub _do_callbacks {
my @cbs = @io_callbacks;
@io_callbacks = ();
sysread $socket_recv, $read_buf, 16;
for my $cb (@cbs) {
$cb->();
}
}

sub _notify_backend {
my ( $self, $callbacks, $result ) = @_;
AE::postpone {
foreach my $cb (@$callbacks) {
$cb->(@$result);
}
};

if (! $socket_pid || $socket_pid != $$) {
$socket_pid = $$;
close($socket_send) if defined $socket_send;
close($socket_recv) if defined $socket_recv;
pipe($socket_recv, $socket_send);
$socket_io = AE::io($socket_recv, 0, \&_do_callbacks);
}

push @io_callbacks, @$callbacks;
syswrite $socket_send, ' ';
}

sub _timeout {
Expand Down
48 changes: 43 additions & 5 deletions lib/Promises/Deferred/AnyEvent.pm
Expand Up @@ -8,13 +8,51 @@ use AnyEvent;

use parent 'Promises::Deferred';

# Before the pipe-based approach used below, there was an
# AnyEvent->postpone-based approach for _notify_backend.
# The current code is much more performant:

# Original code (on a laptop on battery power):
# Backend: Promises::Deferred::AnyEvent
# Benchmark: running one, two for at least 10 CPU seconds...
# one: 47 wallclock secs @ 2754.62/s (n=32780)
# two: 37 wallclock secs @ 2450.45/s (n=24676)

# New approach:
# Backend: Promises::Deferred::AnyEvent
# Benchmark: running one, two for at least 10 CPU seconds...
# one: 10 wallclock secs @ 10182.12/s (n=106505)
# two: 10 wallclock secs @ 3847.01/s (n=39855)


my ($socket_pid, $socket_send, $socket_recv, $socket_io,
$read_buf, @io_callbacks);

sub _do_callbacks {
my @cbs = @io_callbacks;
@io_callbacks = ();
sysread $socket_recv, $read_buf, 16;
for my $cb (@cbs) {
$cb->();
}
}

sub _notify_backend {
my ( $self, $callbacks, $result ) = @_;
AnyEvent::postpone {
foreach my $cb (@$callbacks) {
$cb->(@$result);
}
};

if (! $socket_pid || $socket_pid != $$) {
$socket_pid = $$;
close($socket_send) if defined $socket_send;
close($socket_recv) if defined $socket_recv;
pipe($socket_recv, $socket_send);
$socket_io = AnyEvent->io(
fh => $socket_recv,
poll => 'r',
cb => \&_do_callbacks);
}

push @io_callbacks, @$callbacks;
syswrite $socket_send, ' ';
}

sub _timeout {
Expand Down
56 changes: 50 additions & 6 deletions lib/Promises/Deferred/EV.pm
Expand Up @@ -8,17 +8,61 @@ use EV;

use parent 'Promises::Deferred';

# Before the pipe-based approach used below, there was an EV::timer-based
# approach for _notify_backend. The current code is much more performant:

# Original code (on a laptop on battery power):
# Backend: Promises::Deferred::EV
# Benchmark: running one, two for at least 10 CPU seconds...
# Benchmark: running one, two for at least 10 CPU seconds...
# one: 67 wallclock secs @ 1755.16/s (n=17692)
# two: 53 wallclock secs @ 770.03/s (n=7785)

# New approach:
# Backend: Promises::Deferred::EV
# Benchmark: running one, two for at least 10 CPU seconds...
# one: 10 wallclock secs @ 10949.19/s (n=115076)
# two: 10 wallclock secs @ 3964.58/s (n=41747)


my ($socket_pid, $socket_send, $socket_recv, $socket_io,
$read_buf, @io_callbacks);

sub _do_callbacks {
my @cbs = @io_callbacks;
@io_callbacks = ();
sysread $socket_recv, $read_buf, 16;
for my $cb (@cbs) {
$cb->();
}
}

sub _notify_backend {
my ( $self, $callbacks, $result ) = @_;

my $w; $w = EV::timer( 0, 0, sub {
foreach my $cb (@$callbacks) {
$cb->(@$result);
}
undef $w;
});
if (! $socket_pid || $socket_pid != $$) {
$socket_pid = $$;
close($socket_send) if defined $socket_send;
close($socket_recv) if defined $socket_recv;
pipe($socket_recv, $socket_send);
$socket_io = EV::io($socket_recv, EV::READ, \&_do_callbacks);
}

push @io_callbacks, @$callbacks;
syswrite $socket_send, ' ';
}

# sub _notify_backend {
# my ( $self, $callbacks, $result ) = @_;

# my $w; $w = EV::timer( 0, 0, sub {
# foreach my $cb (@$callbacks) {
# $cb->(@$result);
# }
# undef $w;
# });
# }

sub _timeout {
my ( $self, $timeout, $callback ) = @_;

Expand Down

0 comments on commit c836493

Please sign in to comment.