The following commit has been merged in the master branch:
commit 07efbb0889fcc6fab678ee727fc7c4013b163b53
Author: Modestas Vainius <[EMAIL PROTECTED]>
Date:   Fri Dec 5 13:43:37 2008 +0200

    dpkg-shlibdeps: optimize by caching symbols files and objdump objects
    
    * scripts/Dpkg/Shlibs/Objdump.pm (parse): Split into add_object()
    and parse().
    * scripts/Dpkg/Shlibs/SymbolFile.pm (merge_object_from_symfile):
    New function to reintegrate symbols from previous symfiles.
    * scripts/dpkg-shlibdeps.pl: Optimizes it by caching parsed
    symbols files and objdump objects. This way neither of the
    libraries or symbols files are parsed more than once.
    
    This patch significantly improves performance of dpkg-shlibdeps bringing
    it near to performance levels of versions prior to 1.14.8 without loosing
    any of new functionally at all. Memory requirements are reduced too.
    
    This patch SHOULD NOT change the end result of dpkg-shlibdeps. If it
    does, it is a bug.
    
    Improved-by: Raphael Hertzog <[EMAIL PROTECTED]>

diff --git a/ChangeLog b/ChangeLog
index 722b63a..781ff56 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-12-08  Modestas Vainius  <[EMAIL PROTECTED]>
+           Raphael Hertzog  <[EMAIL PROTECTED]>
+
+       * scripts/Dpkg/Shlibs/Objdump.pm (parse): Split into add_object()
+       and parse().
+       * scripts/Dpkg/Shlibs/SymbolFile.pm (merge_object_from_symfile):
+       New function to reintegrate symbols from previous symfiles.
+       * scripts/dpkg-shlibdeps.pl: Optimizes it by caching parsed
+       symbols files and objdump objects. This way neither of the
+       libraries or symbols files are parsed more than once.
+
 2008-12-05  Guillem Jover  <[EMAIL PROTECTED]>
 
        * lib/mlib.c: Remove <sys/wait.h> include.
diff --git a/debian/changelog b/debian/changelog
index 40320c4..a8cb538 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -86,6 +86,9 @@ dpkg (1.15.0) UNRELEASED; urgency=low
   * Drop some unneeded lintian overrides.
   * Fix a chmod call in dpkg-source to not fail when POSIXLY_CORRECT is set.
     Closes: #506028
+  * Optimize dpkg-shlibdeps by caching parsed symbols files and
+    objdump objects. Thanks to Modestas Vainius <[EMAIL PROTECTED]> for the
+    patch. Closes: #503954
 
   [ Pierre Habouzit ]
   * Add a --query option to update-alternatives. Closes: #336091, #441904
diff --git a/scripts/Dpkg/Shlibs/Objdump.pm b/scripts/Dpkg/Shlibs/Objdump.pm
index 577c814..411821f 100644
--- a/scripts/Dpkg/Shlibs/Objdump.pm
+++ b/scripts/Dpkg/Shlibs/Objdump.pm
@@ -30,10 +30,8 @@ sub new {
     return $self;
 }
 
-sub parse {
-    my ($self, $file) = @_;
-    my $obj = Dpkg::Shlibs::Objdump::Object->new($file);
-
+sub add_object {
+    my ($self, $obj) = @_;
     my $id = $obj->get_id;
     if ($id) {
        $self->{objects}{$id} = $obj;
@@ -41,6 +39,12 @@ sub parse {
     return $id;
 }
 
+sub parse {
+    my ($self, $file) = @_;
+    my $obj = Dpkg::Shlibs::Objdump::Object->new($file);
+
+    return $self->add_object($obj);
+}
 
 sub locate_symbol {
     my ($self, $name) = @_;
@@ -55,12 +59,17 @@ sub locate_symbol {
 
 sub get_object {
     my ($self, $objid) = @_;
-    if (exists $self->{objects}{$objid}) {
+    if ($self->has_object($objid)) {
        return $self->{objects}{$objid};
     }
     return undef;
 }
 
+sub has_object {
+    my ($self, $objid) = @_;
+    return exists $self->{objects}{$objid};
+}
+
 {
     my %format; # Cache of result
     sub get_format {
diff --git a/scripts/Dpkg/Shlibs/SymbolFile.pm 
b/scripts/Dpkg/Shlibs/SymbolFile.pm
index c79db1e..307e2ed 100644
--- a/scripts/Dpkg/Shlibs/SymbolFile.pm
+++ b/scripts/Dpkg/Shlibs/SymbolFile.pm
@@ -175,6 +175,18 @@ sub load {
     delete $seen->{$file};
 }
 
+
+# Beware: we reuse the data structure of the provided symfile so make
+# sure to not modify them after having called this function
+sub merge_object_from_symfile {
+    my ($self, $src, $objid) = @_;
+    if (not $self->has_object($objid)) {
+        $self->{objects}{$objid} = $src->{objects}{$objid};
+    } else {
+        warning(_g("Tried to merge the same object (%s) twice in a symfile."), 
$objid);
+    }
+}
+
 sub save {
     my ($self, $file, $with_deprecated) = @_;
     $file = $self->{file} unless defined($file);
diff --git a/scripts/dpkg-shlibdeps.pl b/scripts/dpkg-shlibdeps.pl
index db42614..068074d 100755
--- a/scripts/dpkg-shlibdeps.pl
+++ b/scripts/dpkg-shlibdeps.pl
@@ -131,6 +131,11 @@ my %global_soname_notfound;
 my %global_soname_used;
 my %global_soname_needed;
 
+# Symfile and objdump caches
+my %symfile_cache;
+my %objdump_cache;
+my %symfile_has_soname_cache;
+
 my $cur_field;
 foreach my $file (keys %exec) {
     $cur_field = $exec{$file};
@@ -193,17 +198,21 @@ foreach my $file (keys %exec) {
 
        # Load symbols/shlibs files from packages providing libraries
        foreach my $pkg (@{$file2pkg->{$lib}}) {
-           my $dpkg_symfile;
+           my $symfile_path;
            if ($packagetype eq "deb") {
                # Use fine-grained dependencies only on real deb
-               $dpkg_symfile = find_symbols_file($pkg, $soname, $lib);
-               if (defined $dpkg_symfile) {
-                   # Load symbol information
-                   print "Using symbols file $dpkg_symfile for $soname\n" if 
$debug;
-                   $symfile->load($dpkg_symfile);
-               }
-           }
-           if (defined($dpkg_symfile) && $symfile->has_object($soname)) {
+               $symfile_path = find_symbols_file($pkg, $soname, $lib);
+            }
+            if (defined($symfile_path)) {
+                # Load symbol information
+                print "Using symbols file $symfile_path for $soname\n" if 
$debug;
+                unless (exists $symfile_cache{$symfile_path}) {
+                    $symfile_cache{$symfile_path} =
+                        Dpkg::Shlibs::SymbolFile->new($symfile_path);
+                }
+                
$symfile->merge_object_from_symfile($symfile_cache{$symfile_path}, $soname);
+            }
+           if (defined($symfile_path) && $symfile->has_object($soname)) {
                # Initialize dependencies with the smallest minimal version
                 # of all symbols (unversioned dependency is not ok as the
                 # library might not have always been available in the
@@ -217,13 +226,17 @@ foreach my $file (keys %exec) {
                }
            } else {
                # No symbol file found, fall back to standard shlibs
-               my $id = $dumplibs_wo_symfile->parse($lib);
+                print "Using shlibs+objdump for $soname (file $lib)\n" if 
$debug;
+                unless (exists $objdump_cache{$lib}) {
+                    $objdump_cache{$lib} = 
Dpkg::Shlibs::Objdump::Object->new($lib);
+                }
+                my $libobj = $objdump_cache{$lib};
+                my $id = $dumplibs_wo_symfile->add_object($libobj);
                if (($id ne $soname) and ($id ne $lib)) {
                    warning(_g("%s has an unexpected SONAME (%s)"), $lib, $id);
                    $alt_soname{$id} = $soname;
                }
                push @soname_wo_symfile, $soname;
-               my $libobj = $dumplibs_wo_symfile->get_object($id);
                # Only try to generate a dependency for libraries with a SONAME
                if ($libobj->is_public_library() and not
                    add_shlibs_dep($soname, $pkg, $lib)) {
@@ -672,6 +685,11 @@ sub find_symbols_file {
 
 sub symfile_has_soname {
     my ($file, $soname) = @_;
+
+    if (exists $symfile_has_soname_cache{$file}{$soname}) {
+        return $symfile_has_soname_cache{$file}{$soname};
+    }
+
     open(SYM_FILE, "<", $file) ||
         syserr(_g("cannot open file %s"), $file);
     my $result = 0;
@@ -682,6 +700,7 @@ sub symfile_has_soname {
        }
     }
     close(SYM_FILE);
+    $symfile_has_soname_cache{$file}{$soname} = $result;
     return $result;
 }
 

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to