From fbcd2b5eb401a8e1811d803cef9b1c156acb50f6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 24 Jun 2019 02:52:54 +0000 Subject: daemon: use FreeBSD accept filters on non-NNTP Similar to TCP_DEFER_ACCEPT on Linux, FreeBSD has a 'dataready' accept filter which we can use to reduce wakeups when doing TLS negotiation or plain HTTP. There's also a 'httpready' which we can use for plain HTTP connections. --- lib/PublicInbox/Daemon.pm | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'lib/PublicInbox') diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index 8b59b65f..cf011a20 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -8,7 +8,8 @@ use warnings; use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/; use IO::Handle; use IO::Socket; -use Socket qw(IPPROTO_TCP); +use Socket qw(IPPROTO_TCP SOL_SOCKET); +sub SO_ACCEPTFILTER () { 0x1000 } use Cwd qw/abs_path/; STDOUT->autoflush(1); STDERR->autoflush(1); @@ -553,20 +554,25 @@ sub tls_start_cb ($$) { } } -sub defer_accept ($) { +sub defer_accept ($$) { + my ($s, $af_name) = @_; + return unless defined $af_name; if ($^O eq 'linux') { - my ($s) = @_; my $x = getsockopt($s, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT()); return unless defined $x; # may be Unix socket my $sec = unpack('i', $x); return if $sec > 0; # systemd users may set a higher value setsockopt($s, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT(), 1); + } elsif ($^O eq 'freebsd') { + my $x = getsockopt($s, SOL_SOCKET, SO_ACCEPTFILTER); + return if defined $x; # don't change if set + my $accf_arg = pack('a16a240', $af_name, ''); + setsockopt($s, SOL_SOCKET, SO_ACCEPTFILTER, $accf_arg); } - # TODO FreeBSD accf_http / accf_data } -sub daemon_loop ($$$) { - my ($refresh, $post_accept, $nntpd) = @_; +sub daemon_loop ($$$$) { + my ($refresh, $post_accept, $nntpd, $af_default) = @_; PublicInbox::EvCleanup::enable(); # early for $refresh my %post_accept; while (my ($k, $v) = each %tls_opt) { @@ -599,7 +605,7 @@ sub daemon_loop ($$$) { # NNTPS, HTTPS, HTTP, and POP3S are client-first traffic # NNTP and POP3 are server-first - defer_accept($_) if $tls_cb || !$nntpd; + defer_accept($_, $tls_cb ? 'dataready' : $af_default); # this calls epoll_create: PublicInbox::Listener->new($_, $tls_cb || $post_accept) @@ -612,8 +618,9 @@ sub daemon_loop ($$$) { sub run ($$$;$) { my ($default, $refresh, $post_accept, $nntpd) = @_; daemon_prepare($default); + my $af_default = $default =~ /:8080\z/ ? 'httpready' : undef; daemonize(); - daemon_loop($refresh, $post_accept, $nntpd); + daemon_loop($refresh, $post_accept, $nntpd, $af_default); } sub do_chown ($) { -- cgit v1.2.3-24-ge0c7