From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-3.8 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.0 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 7E14D20179 for ; Sat, 25 Jun 2016 00:45:35 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 2/4] evcleanup: micro-optimize asap function Date: Sat, 25 Jun 2016 00:45:31 +0000 Message-Id: <20160625004533.5061-3-e@80x24.org> In-Reply-To: <20160625004533.5061-1-e@80x24.org> References: <20160625004533.5061-1-e@80x24.org> List-Id: Instead of relying on a timer with immediate callback, arm a pipe to watch for writability, ensuring the callback always fires. --- lib/PublicInbox/EvCleanup.pm | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/lib/PublicInbox/EvCleanup.pm b/lib/PublicInbox/EvCleanup.pm index 5efb093..61837b8 100644 --- a/lib/PublicInbox/EvCleanup.pm +++ b/lib/PublicInbox/EvCleanup.pm @@ -5,32 +5,56 @@ package PublicInbox::EvCleanup; use strict; use warnings; +use base qw(Danga::Socket); +use fields qw(rd); +my $singleton; +my $asapq = [ [], undef ]; +my $laterq = [ [], undef ]; -my $asapq = { queue => [], timer => undef }; -my $laterq = { queue => [], timer => undef }; +sub once_init () { + my $self = fields::new('PublicInbox::EvCleanup'); + my ($r, $w); + pipe($r, $w) or die "pipe: $!"; + $self->SUPER::new($w); + $self->{rd} = $r; # never read, since we never write.. + $self; +} sub _run_all ($) { my ($q) = @_; - my $run = $q->{queue}; - $q->{queue} = []; - $q->{timer} = undef; + my $run = $q->[0]; + $q->[0] = []; + $q->[1] = undef; $_->() foreach @$run; } sub _run_asap () { _run_all($asapq) } sub _run_later () { _run_all($laterq) } +# Called by Danga::Socket +sub event_write { + my ($self) = @_; + $self->watch_write(0); + _run_asap(); +} + +sub _asap_timer () { + $singleton ||= once_init(); + $singleton->watch_write(1); + 1; +} + sub asap ($) { my ($cb) = @_; - push @{$asapq->{queue}}, $cb; - $asapq->{timer} ||= Danga::Socket->AddTimer(0, *_run_asap); + push @{$asapq->[0]}, $cb; + $asapq->[1] ||= _asap_timer(); } sub later ($) { my ($cb) = @_; - push @{$laterq->{queue}}, $cb; - $laterq->{timer} ||= Danga::Socket->AddTimer(60, *_run_later); + push @{$laterq->[0]}, $cb; + $laterq->[1] ||= Danga::Socket->AddTimer(60, *_run_later); } END {