]> Sergey Matveev's repositories - public-inbox.git/commitdiff
wwwlisting: avoid lazy loading JSON module
authorEric Wong <e@yhbt.net>
Thu, 19 Mar 2020 08:32:53 +0000 (03:32 -0500)
committerEric Wong <e@yhbt.net>
Fri, 20 Mar 2020 18:22:51 +0000 (18:22 +0000)
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
t/www_listing.t

index a8aecaf7402d8aa6a206649fa0b130baffa7e9f5..33cb0ace075016638227cbcce55e659d033afe3f 100644 (file)
@@ -10,11 +10,19 @@ use PublicInbox::Hval qw(ascii_html prurl);
 use PublicInbox::Linkify;
 use PublicInbox::View;
 use PublicInbox::Inbox;
 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;
 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) = @_;
 
 sub list_all_i {
        my ($ibx, $arg) = @_;
@@ -121,16 +129,6 @@ sub html ($$) {
        [ $code, $h, [ $out ] ];
 }
 
        [ $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
 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) = @_;
 # 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) {
 
        my $manifest = { -abs2urlpath => {}, -mtime => 0 };
        for my $ibx (@$list) {
@@ -221,8 +220,7 @@ sub js ($$) {
                $repo->{reference} = $abs2urlpath->{$abs};
        }
        my $out;
                $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),
        $manifest = undef;
        [ 200, [ qw(Content-Type application/gzip),
                 'Last-Modified', time2str($mtime),
index 5168e16ad90b9dd28d367e653d36ade86b1896f8..39c1957756bb367c7618541abcb3d557fc168383 100644 (file)
@@ -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;
 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';
 
 
 use_ok 'PublicInbox::Git';