[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: