Merge lp:~ev/apport/973494 into lp:apport

Proposed by Evan on 2012-04-10
Status: Merged
Merged at revision: 2272
Proposed branch: lp:~ev/apport/973494
Merge into: lp:apport
Diff against target: 93 lines (+35/-17)
1 file modified
backends/packaging-apt-dpkg.py (+35/-17)
To merge this branch: bzr merge lp:~ev/apport/973494
Reviewer Review Type Date Requested Status
Martin Pitt 2012-04-10 Approve on 2012-04-10
Review via email: mp+101353@code.launchpad.net

Description of the Change

We've found apport-retrace and the code that wraps it in the crash database to be a bottleneck (bug 973494). In trying to improve the speed in which we can retrace core files (which is currently about 3/min), I noticed that we're constructing a new apt.Cache twice with the same data and calling update() on it twice.

This branch fixes that, and provides the following speed improvement:

ubuntu@server-8149:~$ ./judge/judge 'apport-retrace _usr_bin_gedit.1000.crash -o new.crash -S retracer/config -C cache
-c' './with_changes'
v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^

    n mean sd min max cmd
       50 29566.9ms 1206.3 27047.6 36682.3 apport-retrace _usr_bin_gedit.1000.crash -o new.crash -S retracer/config -C cache -c
          50 23592.5ms 648.8 21846.0 26651.0 ./with_changes
          -5974.360ms -20.2% p=0.000
          difference is significant at 95.0% confidence (p=0.000):
          based on these samples, suggested sample size is n>=5 to have a 1493.59ms confidence interval

I dropped the workaround for setting apt.Cache(rootdir='/') at the end of install_packages() in favor of explicitly calling apt.Cache with that parameter in _cache().

To post a comment you must log in.
Evan (ev) wrote :

I should note that this doesn't need to go into 12.04. If you're happy with the change, I can build this out of a PPA.

Martin Pitt (pitti) wrote :

+ self._sandbox_apt_cache = None
+ if self._sandbox_apt_cache or not self._apt_cache:

This looks a bit weird. I presume it is just a copy&paste error, I'll fix that, and also the documentation for the new _sandbox_cache. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'backends/packaging-apt-dpkg.py'
2--- backends/packaging-apt-dpkg.py 2012-03-22 17:10:58 +0000
3+++ backends/packaging-apt-dpkg.py 2012-04-10 10:31:20 +0000
4@@ -28,6 +28,7 @@
5
6 def __init__(self):
7 self._apt_cache = None
8+ self._sandbox_apt_cache = None
9 self._contents_dir = None
10 self._mirror = None
11
12@@ -44,15 +45,36 @@
13 def _cache(self):
14 '''Return apt.Cache() (initialized lazily).'''
15
16- if not self._apt_cache:
17+ self._sandbox_apt_cache = None
18+ if self._sandbox_apt_cache or not self._apt_cache:
19 try:
20 # avoid spewage on stdout
21- self._apt_cache = apt.Cache(apt.progress.base.OpProgress())
22+ progress = apt.progress.base.OpProgress()
23+ self._apt_cache = apt.Cache(progress, rootdir='/')
24 except AttributeError:
25 # older python-apt versions do not yet have above argument
26- self._apt_cache = apt.Cache()
27+ self._apt_cache = apt.Cache(rootdir='/')
28 return self._apt_cache
29
30+ def _sandbox_cache(self, aptroot, apt_sources, fetchProgress):
31+ '''Return apt.Cache(rootdir=) (initialized lazily).
32+ Clear the package selection on subsequent calls.'''
33+
34+ self._apt_cache = None
35+ if not self._sandbox_apt_cache:
36+ self._build_apt_sandbox(aptroot, apt_sources)
37+ rootdir = os.path.abspath(aptroot)
38+ self._sandbox_apt_cache = apt.Cache(rootdir=rootdir)
39+ try:
40+ # We don't need to update this multiple times.
41+ self._sandbox_apt_cache.update(fetchProgress)
42+ except apt.cache.FetchFailedException as e:
43+ raise SystemError(str(e))
44+ self._sandbox_apt_cache.open()
45+ else:
46+ self._sandbox_apt_cache.clear()
47+ return self._sandbox_apt_cache
48+
49 def _apt_pkg(self, package):
50 '''Return apt.Cache()[package] (initialized lazily).
51
52@@ -491,18 +513,20 @@
53 tmp_aptroot = True
54 aptroot = tempfile.mkdtemp()
55
56- self._build_apt_sandbox(aptroot, apt_sources)
57-
58 if verbose:
59 fetchProgress = apt.progress.text.AcquireProgress()
60 else:
61 fetchProgress = apt.progress.base.AcquireProgress()
62- c = apt.Cache(rootdir=os.path.abspath(aptroot))
63- try:
64- c.update(fetchProgress)
65- except apt.cache.FetchFailedException as e:
66- raise SystemError(str(e))
67- c.open()
68+ if not tmp_aptroot:
69+ c = self._sandbox_cache(aptroot, apt_sources, fetchProgress)
70+ else:
71+ self._build_apt_sandbox(aptroot, apt_sources)
72+ c = apt.Cache(rootdir=os.path.abspath(aptroot))
73+ try:
74+ c.update(fetchProgress)
75+ except apt.cache.FetchFailedException as e:
76+ raise SystemError(str(e))
77+ c.open()
78
79 obsolete = ''
80
81@@ -558,12 +582,6 @@
82 assert not real_pkgs, 'apt fetcher did not fetch these packages: ' \
83 + ' '.join(real_pkgs)
84
85- # work around python-apt bug that causes parts of the Cache(rootdir=)
86- # argument configuration to be persistent; this resets the apt
87- # configuration to system defaults again
88- apt.Cache(rootdir='/')
89- self._apt_cache = None
90-
91 return obsolete
92
93 def package_name_glob(self, nameglob):

Subscribers

People subscribed via source and target branches