From d00087bcdf3a4c2411ecdf75b4f7ee583db530fb Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 21 Mar 2023 23:07:26 +0000 Subject: ds: @post_loop_do replaces SetPostLoopCallback This allows us to avoid repeatedly using memory-intensive anonymous subs in CodeSearchIdx where the callback is assigned frequently. Anonymous subs are known to leak memory in old Perls (e.g. 5.16.3 in enterprise distros) and still expensive in newer Perls. So favor the (\&subroutine, @args) form which allows us to eliminate anonymous subs going forward. Only CodeSearchIdx takes advantage of the new API at the moment, since it's the biggest repeat user of post-loop callback changes. Getting rid of the subroutine and relying on a global `our' variable also has two advantages: 1) Perl warnings can detect typos at compile-time, whereas the (now gone) method could only detect errors at run-time. 2) `our' variable assignment can be `local'-ized to a scope --- xt/mem-imapd-tls.t | 7 +++---- xt/mem-nntpd-tls.t | 8 ++++---- xt/net_writer-imap.t | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'xt') diff --git a/xt/mem-imapd-tls.t b/xt/mem-imapd-tls.t index 75f2911f..00199a9b 100644 --- a/xt/mem-imapd-tls.t +++ b/xt/mem-imapd-tls.t @@ -82,7 +82,7 @@ sub once { 0 }; # stops event loop # setup the event loop so that it exits at every step # while we're still doing connect(2) PublicInbox::DS->SetLoopTimeout(0); -PublicInbox::DS->SetPostLoopCallback(\&once); +local @PublicInbox::DS::post_loop_do = (\&once); my $pid = $td->{pid}; if ($^O eq 'linux' && open(my $f, '<', "/proc/$pid/status")) { diag(grep(/RssAnon/, <$f>)); @@ -101,14 +101,13 @@ foreach my $n (1..$nfd) { if (!($n % 128) && $DONE != $n) { diag("nr: ($n) $DONE/$nfd"); PublicInbox::DS->SetLoopTimeout(-1); - PublicInbox::DS->SetPostLoopCallback(sub { $DONE != $n }); + local @PublicInbox::DS::post_loop_do = (sub { $DONE != $n }); # clear the backlog: PublicInbox::DS::event_loop(); # resume looping PublicInbox::DS->SetLoopTimeout(0); - PublicInbox::DS->SetPostLoopCallback(\&once); } } @@ -116,7 +115,7 @@ foreach my $n (1..$nfd) { diag "done?: @".time." $DONE/$nfd"; if ($DONE != $nfd) { PublicInbox::DS->SetLoopTimeout(-1); - PublicInbox::DS->SetPostLoopCallback(sub { $DONE != $nfd }); + local @PublicInbox::DS::post_loop_do = (sub { $DONE != $nfd }); PublicInbox::DS::event_loop(); } is($nfd, $DONE, "$nfd/$DONE done"); diff --git a/xt/mem-nntpd-tls.t b/xt/mem-nntpd-tls.t index 6e34d233..a861e318 100644 --- a/xt/mem-nntpd-tls.t +++ b/xt/mem-nntpd-tls.t @@ -105,7 +105,7 @@ sub once { 0 }; # stops event loop # setup the event loop so that it exits at every step # while we're still doing connect(2) PublicInbox::DS->SetLoopTimeout(0); -PublicInbox::DS->SetPostLoopCallback(\&once); +local @PublicInbox::DS::post_loop_do = (\&once); foreach my $n (1..$nfd) { my $io = tcp_connect($nntps, Blocking => 0); @@ -120,14 +120,14 @@ foreach my $n (1..$nfd) { if (!($n % 128) && $n != $DONE) { diag("nr: ($n) $DONE/$nfd"); PublicInbox::DS->SetLoopTimeout(-1); - PublicInbox::DS->SetPostLoopCallback(sub { $DONE != $n }); + @PublicInbox::DS::post_loop_do = (sub { $DONE != $n }); # clear the backlog: PublicInbox::DS::event_loop(); # resume looping PublicInbox::DS->SetLoopTimeout(0); - PublicInbox::DS->SetPostLoopCallback(\&once); + @PublicInbox::DS::post_loop_do = (\&once); } } my $pid = $td->{pid}; @@ -141,7 +141,7 @@ $dump_rss->(); # run the event loop normally, now: if ($DONE != $nfd) { PublicInbox::DS->SetLoopTimeout(-1); - PublicInbox::DS->SetPostLoopCallback(sub { + @PublicInbox::DS::post_loop_do = (sub { diag "done: ".time." $DONE"; $DONE != $nfd; }); diff --git a/xt/net_writer-imap.t b/xt/net_writer-imap.t index 333e0e3b..f7796e8e 100644 --- a/xt/net_writer-imap.t +++ b/xt/net_writer-imap.t @@ -1,5 +1,5 @@ #!perl -w -# Copyright (C) 2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; use v5.10.1; use PublicInbox::TestCommon; use Sys::Hostname qw(hostname); @@ -233,7 +233,7 @@ EOM my $pub_cfg = PublicInbox::Config->new; PublicInbox::DS->Reset; my $ii = PublicInbox::InboxIdle->new($pub_cfg); - my $cb = sub { PublicInbox::DS->SetPostLoopCallback(sub {}) }; + my $cb = sub { @PublicInbox::DS::post_loop_do = (sub {}) }; my $obj = bless \$cb, 'PublicInbox::TestCommon::InboxWakeup'; $pub_cfg->each_inbox(sub { $_[0]->subscribe_unlock('ident', $obj) }); my $w = start_script(['-watch'], undef, { 2 => $err_wr }); -- cgit v1.2.3-24-ge0c7