]> Sergey Matveev's repositories - public-inbox.git/commitdiff
listener: use edge-triggered notifications
authorEric Wong <e@80x24.org>
Thu, 27 Jun 2019 21:21:05 +0000 (21:21 +0000)
committerEric Wong <e@80x24.org>
Sat, 29 Jun 2019 19:59:00 +0000 (19:59 +0000)
We don't need extra wakeups from the kernel when we know a
listener is already active.

lib/PublicInbox/DSKQXS.pm
lib/PublicInbox/Listener.pm
lib/PublicInbox/Syscall.pm

index 364df3d68cd77838dfe56cb8598ea854e4e12488..278d3f887508509881089294683308e69883581b 100644 (file)
@@ -16,7 +16,8 @@ use warnings;
 use parent qw(IO::KQueue);
 use parent qw(Exporter);
 use IO::KQueue;
-use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLL_CTL_DEL);
+use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLLET
+       EPOLL_CTL_DEL);
 our @EXPORT_OK = qw(epoll_ctl epoll_wait);
 my $owner_pid = -1; # kqueue is close-on-fork (yes, fork, not exec)
 
@@ -25,6 +26,7 @@ sub kq_flag ($$) {
        my ($bit, $ev) = @_;
        if ($ev & $bit) {
                my $fl = EV_ADD | EV_ENABLE;
+               $fl |= EV_CLEAR if $fl & EPOLLET;
                ($ev & EPOLLONESHOT) ? ($fl | EV_ONESHOT) : $fl;
        } else {
                EV_ADD | EV_DISABLE;
index 94b2aed4db632c597eac684057e26264f80859eb..594dabb83e38eacd2b2733c952c205e3ffdc2456 100644 (file)
@@ -9,6 +9,7 @@ use base 'PublicInbox::DS';
 use Socket qw(SOL_SOCKET SO_KEEPALIVE IPPROTO_TCP TCP_NODELAY);
 use fields qw(post_accept);
 require IO::Handle;
+use PublicInbox::Syscall qw(EPOLLIN EPOLLEXCLUSIVE EPOLLET);
 
 sub new ($$$) {
        my ($class, $s, $cb) = @_;
@@ -17,15 +18,14 @@ sub new ($$$) {
        listen($s, 1024);
        IO::Handle::blocking($s, 0);
        my $self = fields::new($class);
-       $self->SUPER::new($s, PublicInbox::DS::EPOLLIN()|
-                             PublicInbox::DS::EPOLLEXCLUSIVE());
+       $self->SUPER::new($s, EPOLLIN|EPOLLET|EPOLLEXCLUSIVE);
        $self->{post_accept} = $cb;
        $self
 }
 
 sub event_step {
        my ($self) = @_;
-       my $sock = $self->{sock};
+       my $sock = $self->{sock} or return;
 
        # no loop here, we want to fairly distribute clients
        # between multiple processes sharing the same socket
@@ -35,6 +35,7 @@ sub event_step {
        if (my $addr = accept(my $c, $sock)) {
                IO::Handle::blocking($c, 0); # no accept4 :<
                $self->{post_accept}->($c, $addr, $sock);
+               $self->requeue;
        }
 }
 
index 500efa67016f80149f3723d08f0e11f5e8af71fa..d7e15c72c003e800c697449aaeea075fd9456c1f 100644 (file)
@@ -22,7 +22,7 @@ use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS $VERSION);
 $VERSION     = "0.25";
 @ISA         = qw(Exporter);
 @EXPORT_OK   = qw(sendfile epoll_ctl epoll_create epoll_wait
-                  EPOLLIN EPOLLOUT
+                  EPOLLIN EPOLLOUT EPOLLET
                   EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD
                   EPOLLONESHOT EPOLLEXCLUSIVE);
 %EXPORT_TAGS = (epoll => [qw(epoll_ctl epoll_create epoll_wait
@@ -39,7 +39,7 @@ use constant EPOLLOUT      => 4;
 # use constant EPOLLRDBAND   => 128;
 use constant EPOLLEXCLUSIVE => (1 << 28);
 use constant EPOLLONESHOT => (1 << 30);
-use constant EPOLLET => (1 << 31);
+use constant EPOLLET => (1 << 31);
 use constant EPOLL_CTL_ADD => 1;
 use constant EPOLL_CTL_DEL => 2;
 use constant EPOLL_CTL_MOD => 3;