From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id C0B221F61D for ; Thu, 19 Mar 2020 08:32:56 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 3/6] wwwlisting: avoid lazy loading JSON module Date: Thu, 19 Mar 2020 03:32:53 -0500 Message-Id: <20200319083256.15593-4-e@yhbt.net> In-Reply-To: <20200319083256.15593-1-e@yhbt.net> References: <20200319083256.15593-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We already lazy-load WwwListing for the CGI script, and hiding another layer of lazy-loading makes things difficult to do WWW->preload. We want long-lived processes to do all long-lived allocations up front to avoid fragmentation in the allocator, but we'll still support short-lived processes by lazy-loading individual modules in the PublicInbox::* namespace. Mixing up allocation lifetimes (e.g. doing immortal allocations while a large amount of space is taken by short-lived objects) will cause fragmentation in any allocator which favors large contiguous regions for performance reasons. This includes any malloc implementation which relies on sbrk() for the primary heap, including glibc malloc. --- lib/PublicInbox/WwwListing.pm | 26 ++++++++++++-------------- t/www_listing.t | 4 ++-- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/PublicInbox/WwwListing.pm b/lib/PublicInbox/WwwListing.pm index a8aecaf7..33cb0ace 100644 --- a/lib/PublicInbox/WwwListing.pm +++ b/lib/PublicInbox/WwwListing.pm @@ -10,11 +10,19 @@ use PublicInbox::Hval qw(ascii_html prurl); use PublicInbox::Linkify; use PublicInbox::View; use PublicInbox::Inbox; -use bytes (); +use bytes (); # bytes::length use HTTP::Date qw(time2str); use Digest::SHA (); use File::Spec (); *try_cat = \&PublicInbox::Inbox::try_cat; +our $json; +if (eval { require IO::Compress::Gzip }) { + for my $mod (qw(JSON::MaybeXS JSON JSON::PP)) { + eval "require $mod" or next; + # ->ascii encodes non-ASCII to "\uXXXX" + $json = $mod->new->ascii(1); + } +} sub list_all_i { my ($ibx, $arg) = @_; @@ -121,16 +129,6 @@ sub html ($$) { [ $code, $h, [ $out ] ]; } -my $json; -sub _json () { - for my $mod (qw(JSON::MaybeXS JSON JSON::PP)) { - eval "require $mod" or next; - # ->ascii encodes non-ASCII to "\uXXXX" - return $mod->new->ascii(1); - } - die; -} - sub fingerprint ($) { my ($git) = @_; # TODO: convert to qspawn for fairness when there's @@ -201,7 +199,8 @@ sub manifest_add ($$;$$) { # manifest.js.gz sub js ($$) { my ($env, $list) = @_; - eval { require IO::Compress::Gzip } or return [ 404, [], [] ]; + # $json won't be defined if IO::Compress::Gzip is missing + $json or return [ 404, [], [] ]; my $manifest = { -abs2urlpath => {}, -mtime => 0 }; for my $ibx (@$list) { @@ -221,8 +220,7 @@ sub js ($$) { $repo->{reference} = $abs2urlpath->{$abs}; } my $out; - IO::Compress::Gzip::gzip(\(($json ||= _json())->encode($manifest)) => - \$out); + IO::Compress::Gzip::gzip(\($json->encode($manifest)) => \$out); $manifest = undef; [ 200, [ qw(Content-Type application/gzip), 'Last-Modified', time2str($mtime), diff --git a/t/www_listing.t b/t/www_listing.t index 5168e16a..39c19577 100644 --- a/t/www_listing.t +++ b/t/www_listing.t @@ -9,8 +9,8 @@ use PublicInbox::TestCommon; require_mods(qw(URI::Escape Plack::Builder Digest::SHA IO::Compress::Gzip IO::Uncompress::Gunzip HTTP::Tiny)); require PublicInbox::WwwListing; -my $json = eval { PublicInbox::WwwListing::_json() }; -plan skip_all => "JSON module missing: $@" if $@; +my $json = $PublicInbox::WwwListing::json or + plan skip_all => "JSON module missing"; use_ok 'PublicInbox::Git';