[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. 2.5.14-90-g398f63e



The following commit has been merged in the master branch:
commit 398f63ea6e755c8ce5ee9860dda7fc53ddcdbf93
Author: Niels Thykier <niels@thykier.net>
Date:   Mon Jul 22 20:57:16 2013 +0200

    L::Relation: Reduce the memory usage of L::Relation objects
    
    This patch contains two memory optimisations for L::Relation.  The
    first is a singleton empty relation, which means that empty relation
    fields no longer pay for a new object each time.
    
    The second optimisation relies on some "perlguts" knowledge.  In C,
    storing a NULL in an array is cheaper than storing an actual element.
    In perl, storing "undef" in an array causes perl to create a new empty
    scalar (which behaves like undef) and shoves it into the array.
    
    perl allows us to do "out-of-bounds" access and just returns "undef",
    so we do not actually /need/ the arrays to be a fixed size.  So we
    abuse this fact to just pop undef elements in the list.
    
    A completely unversioned relation (without multi-arch or architecture
    qualification) will be reduced by 4 SVs[1].  Even the average
    versioned relation will still be reduced by 2 SVs.  These SVs
    accumulates to about ~0.44MB (on i386) for the binary_relation of
    source:linux alone.
    
    [1] In perl 5.19.2, a SV appears to be two 32bit ints and two
    pointers.  So 16 to 24 bytes a piece depending on the architecture.
    
    Signed-off-by: Niels Thykier <niels@thykier.net>

diff --git a/debian/changelog b/debian/changelog
index 3032eb3..2312cc1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -122,6 +122,8 @@ lintian (2.5.15) UNRELEASED; urgency=low
       was passed on the command line before the .changes file.
       Thanks to Salvo Tomaselli for reporting the bug.
       (Closes: #714437)
+  * lib/Lintian/Relation.pm:
+    + [NT] Apply some memory optimisations to some common cases.
   * lib/Lintian/Tags.pm:
     + [NT] Use croak instead of die when a check emits an
       unknown tag.  This gives the check writer a better chance
diff --git a/lib/Lintian/Relation.pm b/lib/Lintian/Relation.pm
index 8747251..523d80a 100644
--- a/lib/Lintian/Relation.pm
+++ b/lib/Lintian/Relation.pm
@@ -118,17 +118,45 @@ sub parse_element {
     /x;
 
     my ($pkgname, $march, $relop, $relver, $bdarch) = ($1, $2, $3, $4, $5);
-    # If there's no version, we don't need to do any further processing.
-    # Otherwise, convert the legacy < and > relations to the current ones.
-    return ['PRED', $pkgname, undef, undef, $bdarch, $march] if not defined $relop;
-    if ($relop eq '<') {
-        $relop = '<<';
-    } elsif ($relop eq '>') {
-        $relop = '>>';
+    my @array;
+    if (not defined($relop)) {
+        # If there's no version, we don't need to do any further processing.
+        # Otherwise, convert the legacy < and > relations to the current ones.
+        @array = ('PRED', $pkgname, undef, undef, $bdarch, $march);
+    } else {
+        if ($relop eq '<') {
+            $relop = '<<';
+        } elsif ($relop eq '>') {
+            $relop = '>>';
+        }
+        @array = ('PRED', $pkgname, $relop, $relver, $bdarch, $march);
     }
-    return ['PRED', $pkgname, $relop, $relver, $bdarch, $march];
+
+    # Optimise the memory usage of the array.  Understanding this
+    # requires a bit of "Perl guts" knowledge.  Storing "undef" in an
+    # array (or hash) actually creates a new empty "undefined" scalar.
+    # This means that we pay the full overhead of Perl's SV struct for
+    # each undef value in this array.
+    #   Combine this with the fact that at least the BD-arch qualifier
+    # is rare (in fact, always undef for binary relations) and
+    # multi-arch qualifiers equally so (at least at the moment).
+    # On unversioned relations, we end up paying for 4 (unique) empty
+    # scalars.
+    #   This overhead accumuates to 0.44M for the binary relations of
+    # source:linux (on i386).
+    #
+    # Fortunately, perl allows us to do "out-of-bounds" access and
+    # will simply return undef in this case.  This means, we can
+    # basically get away with popping elements from the right hand
+    # side of the array "for free".
+    pop(@array) while (not defined($array[-1]));
+
+    return \@array;
 }
 
+# Singleton "empty-relation" object.  Since these objects are immutable,
+# there is no reason for having multiple "empty" objects.
+my $EMPTY_RELATION = bless(['AND'], 'Lintian::Relation');
 
 # Create a new Lintian::Relation object, parsing the argument into our
 # internal format.
@@ -148,6 +176,11 @@ sub new {
             push(@result, ['OR', @alternatives]);
         }
     }
+
+    if ($class eq 'Lintian::Relation') {
+        return $EMPTY_RELATION if not @result;
+    }
+
     my $self;
     if (@result == 1) {
         $self = $result[0];
@@ -208,6 +241,11 @@ sub and {
             push @result, $rel;
         }
     }
+
+    if ($class eq 'Lintian::Relation') {
+        return $EMPTY_RELATION if not @result;
+    }
+
     my $self;
     if (@result == 1) {
         $self = $result[0];

-- 
Debian package checker


Reply to: