Hi Andreas,

Axel Beckert wrote:
> Andreas Beckmann wrote:
> > Checking intel-mkl (pre-built binaries in non-free) with lintian is very
> > slow. A full build (i.e. source+all+any) on amd64 takes nearly 18 hours
> > to check with
> >   lintian -i -E -L ">=pedantic" -v intel-mkl_2020.4.304-4_amd64.changes
> > on my local machine (8 cores, 64 GB, tmpfs on /tmp, storage on nvme).

Took about 4 hours here (with about the same specs, but a quite recent
CPU: i7-11700 with 8 cores, 16 threads, 64 GB RAM and all NVMe
storage, including /tmp/), but still far too long.

> I'll check if --perf-debug brings up anything helpful.

Here's the break down on any check that took more than 10 seconds,
sorted by Lintian check:

Binary checks:

Check binaries/corrupted for binary:libmkl-computational-dev_2020.4.304-4_amd64 
done (2494.134s)
Check binaries/corrupted for binary:libmkl-interface-dev_2020.4.304-4_amd64 
done (104.566s)
Check binaries/corrupted for binary:libmkl-threading-dev_2020.4.304-4_amd64 
done (34.574s)
Check binaries/hardening for binary:libmkl-computational-dev_2020.4.304-4_amd64 
done (2233.613s)
Check binaries/hardening for binary:libmkl-interface-dev_2020.4.304-4_amd64 
done (98.522s)
Check binaries/hardening for binary:libmkl-threading-dev_2020.4.304-4_amd64 
done (34.621s)
Check binaries/obsolete/crypt for 
binary:libmkl-computational-dev_2020.4.304-4_amd64 done (2206.171s)
Check binaries/obsolete/crypt for 
binary:libmkl-interface-dev_2020.4.304-4_amd64 done (99.777s)
Check binaries/obsolete/crypt for 
binary:libmkl-threading-dev_2020.4.304-4_amd64 done (34.487s)
Check libraries/static for binary:libmkl-computational-dev_2020.4.304-4_amd64 
done (2176.996s)
Check libraries/static for binary:libmkl-interface-dev_2020.4.304-4_amd64 done 
(124.188s)
Check libraries/static for binary:libmkl-threading-dev_2020.4.304-4_amd64 done 
(38.784s)
Check libraries/static/link-time-optimization for 
binary:libmkl-computational-dev_2020.4.304-4_amd64 done (2062.453s)
Check libraries/static/link-time-optimization for 
binary:libmkl-interface-dev_2020.4.304-4_amd64 done (106.561s)
Check libraries/static/link-time-optimization for 
binary:libmkl-threading-dev_2020.4.304-4_amd64 done (34.848s)
Check libraries/static/no-code for 
binary:libmkl-computational-dev_2020.4.304-4_amd64 done (2209.059s)
Check libraries/static/no-code for 
binary:libmkl-interface-dev_2020.4.304-4_amd64 done (128.671s)
Check libraries/static/no-code for 
binary:libmkl-threading-dev_2020.4.304-4_amd64 done (42.731s)

Source check:

Check debian/control/field/rules-requires-root for 
source:intel-mkl_2020.4.304-4 done (499.496s)

So basically the long-taking tests all took about the same time for
each package. So I assume they all had the same issues for each
package, just to different amounts:

* 2000-2500s for libmkl-computational-dev
*  100-130s  for libmkl-interface-dev
*   30-45s   for libmkl-threading-dev

So I've ran Lintian under a profiler on the smallest of these
packages.

perl -d:NYTProf lintian/bin/lintian libmkl-threading-dev_2020.4.304-4_amd64.deb

And indeed, all three checks stayed approximately the same time in
Lintian::Index::Item::elf_by_member() which took up to 158 seconds
(under the profiler) in 162407 calls.

So if we want to speed up analysing binaries with large .a files (up
to 640 MB in this case), we should clearly speed elf_by_member().

And inside it, it's this line which took all but 1 second of it:

my %copy = %{$self->index->elf_storage_by_member->{$self->name} // {} };

So basically copying data in RAM around seems to be the main cause for
taking so long on these binary packages.

Accordingly I've made this temporary local change to check what it
would be without copying around that data:

diff --git a/lib/Lintian/Index/Item.pm b/lib/Lintian/Index/Item.pm
index 7ef6c0994..87d766cbe 100644
--- a/lib/Lintian/Index/Item.pm
+++ b/lib/Lintian/Index/Item.pm
@@ -1434,9 +1434,10 @@ sub elf_by_member {
         return ();
     }
 
-    my %copy = %{$self->index->elf_storage_by_member->{$self->name} // {} };
+    #my %copy = %{$self->index->elf_storage_by_member->{$self->name} // {} };
 
-    return \%copy;
+    #return \%copy;
+    return $self->index->elf_storage_by_member->{$self->name} // {};
 }
 
 =item pointer

(Patch and all tests based on the 2.116.3 release.) 

Not copying that data and just returning the original cuts the run
time down from 5m 7s to 1m 56s, i.e. by about 60%.

On the largest package (libmkl-computational-dev) it went down even a
much bigger percentage, from close to 3 hours (178 minutes) down to only 3
minutes and 32 seconds.

The question is now: Do we really need a separate copy of that data
for each call? Sure, if it's modified afterwards, this makes sense.
But I have no idea where this might happen.

So I've run the test suite on the above mentioned modification and to
my surprise it passed. 😲

Since the variable was explicitly called %copy, I'm sure, the copying
was on purpose. But which purpose? — Because the test suite found no
difference in behaviour.

Bastien Roucariès wrote:
> Please note that cruft source could be run in parallel if needed.

According to the man page, lintian runs stuff in parallel where
possible. But there's a good chance that not all places that could
support parallelism also actually support it. Haven't looked deeper
into that, though. Running against multiple *.deb at the same time
probably can be parallelised as well, probably at the cost of loading
other things multiple times.

The main issue here (or at least what I looked at because it was the
biggest chunk of time when checking both, binaries and source
packages) unfortunately seems not to get that much gain from
parallelising, and if it does, it mainly depends on if memory copying
can be parallelised well enough, too.

                Regards, Axel
-- 
 ,''`.  |  Axel Beckert <a...@debian.org>, https://people.debian.org/~abe/
: :' :  |  Debian Developer, ftp.ch.debian.org Admin
`. `'   |  4096R: 2517 B724 C5F6 CA99 5329  6E61 2FF9 CD59 6126 16B5
  `-    |  1024D: F067 EA27 26B9 C3FC 1486  202E C09E 1D89 9593 0EDE

Attachment: signature.asc
Description: PGP signature

Reply via email to