Merge lp:~wgrant/launchpad/faster-binary-search into lp:launchpad

Proposed by William Grant on 2012-09-07
Status: Merged
Approved by: William Grant on 2012-09-07
Approved revision: no longer in the source branch.
Merged at revision: 15920
Proposed branch: lp:~wgrant/launchpad/faster-binary-search
Merge into: lp:launchpad
Diff against target: 431 lines (+86/-228)
6 files modified
lib/lp/archivepublisher/publishing.py (+2/-4)
lib/lp/archivepublisher/tests/test_generate_extra_overrides.py (+4/-5)
lib/lp/registry/doc/distroseries.txt (+49/-123)
lib/lp/registry/interfaces/distroseries.py (+4/-9)
lib/lp/registry/model/distroseries.py (+24/-85)
lib/lp/soyuz/model/archive.py (+3/-2)
To merge this branch: bzr merge lp:~wgrant/launchpad/faster-binary-search
Reviewer Review Type Date Requested Status
Steve Kowalik (community) code 2012-09-07 Approve on 2012-09-07
Review via email: mp+123213@code.launchpad.net

Commit Message

Fix some BinaryPackagePublishingHistory queries to filter by BPPH.binarypackagename rather than joining through BinaryPackageRelease.

Description of the Change

This branch fixes most of the remaining BinaryPackagePublishingHistory queries that filter on BinaryPackageRelease.binarypackagename to use the denormalised column instead. This gets the bad cases of methods like Archive.getAllPublishedBinaries down from ~5000ms to ~10ms.

DistroSeries.getBinaryPackagePublishing and getSourcePackagePublishingHistory also had the issue, but none of their callsites use the name filtering any more. I stripped them right down to just serve NMAF's needs, but they should eventually be replaced with methods on Archive.

To post a comment you must log in.
Steve Kowalik (stevenk) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/archivepublisher/publishing.py'
2--- lib/lp/archivepublisher/publishing.py 2012-08-17 11:15:35 +0000
3+++ lib/lp/archivepublisher/publishing.py 2012-09-07 05:49:18 +0000
4@@ -414,8 +414,7 @@
5 source_index_root, self._config.temproot, 'Sources')
6
7 for spp in distroseries.getSourcePackagePublishing(
8- PackagePublishingStatus.PUBLISHED, pocket=pocket,
9- component=component, archive=self.archive):
10+ pocket, component, self.archive):
11 stanza = spp.getIndexStanza().encode('utf8') + '\n\n'
12 source_index.write(stanza)
13
14@@ -441,8 +440,7 @@
15 di_index_root, self._config.temproot, 'Packages')
16
17 for bpp in distroseries.getBinaryPackagePublishing(
18- archtag=arch.architecturetag, pocket=pocket,
19- component=component, archive=self.archive):
20+ arch.architecturetag, pocket, component, self.archive):
21 stanza = bpp.getIndexStanza().encode('utf-8') + '\n\n'
22 if (bpp.binarypackagerelease.binpackageformat in
23 (BinaryPackageFormat.DEB, BinaryPackageFormat.DDEB)):
24
25=== modified file 'lib/lp/archivepublisher/tests/test_generate_extra_overrides.py'
26--- lib/lp/archivepublisher/tests/test_generate_extra_overrides.py 2012-08-17 11:15:35 +0000
27+++ lib/lp/archivepublisher/tests/test_generate_extra_overrides.py 2012-09-07 05:49:18 +0000
28@@ -172,8 +172,8 @@
29 source_index = RepositoryIndexFile(
30 source_index_root, script.config.temproot, "Sources")
31 for spp in distroseries.getSourcePackagePublishing(
32- PackagePublishingStatus.PUBLISHED,
33- PackagePublishingPocket.RELEASE, component=component):
34+ PackagePublishingPocket.RELEASE, component,
35+ distroseries.main_archive):
36 stanza = spp.getIndexStanza().encode("utf-8") + "\n\n"
37 source_index.write(stanza)
38 source_index.close()
39@@ -184,9 +184,8 @@
40 package_index = RepositoryIndexFile(
41 package_index_root, script.config.temproot, "Packages")
42 for bpp in distroseries.getBinaryPackagePublishing(
43- archtag=arch.architecturetag,
44- pocket=PackagePublishingPocket.RELEASE,
45- component=component):
46+ arch.architecturetag, PackagePublishingPocket.RELEASE,
47+ component, distroseries.main_archive):
48 stanza = bpp.getIndexStanza().encode("utf-8") + "\n\n"
49 package_index.write(stanza)
50 package_index.close()
51
52=== modified file 'lib/lp/registry/doc/distroseries.txt'
53--- lib/lp/registry/doc/distroseries.txt 2012-06-19 03:26:57 +0000
54+++ lib/lp/registry/doc/distroseries.txt 2012-09-07 05:49:18 +0000
55@@ -637,85 +637,47 @@
56 instance. it can also be used to generate the archive packages list in
57 the future.
58
59- >>> ubuntu = getUtility(IDistributionSet)['ubuntu']
60- >>> hoary = ubuntu['hoary']
61-
62 >>> from lp.soyuz.enums import PackagePublishingStatus
63- >>> hoary_pub_sources = hoary.getSourcePackagePublishing(
64- ... PackagePublishingStatus.PUBLISHED,
65- ... PackagePublishingPocket.RELEASE)
66-
67- >>> hoary_pub_sources.count()
68- 6
69-
70- >>> for pub in hoary_pub_sources:
71- ... print pub.displayname
72- alsa-utils 1.0.9a-4ubuntu1 in hoary
73- cnews cr.g7-37 in hoary
74- evolution 1.0 in hoary
75- libstdc++ b8p in hoary
76- linux-source-2.6.15 2.6.15.3 in hoary
77- pmount 0.1-2 in hoary
78-
79- >>> hoary_pub_source = hoary_pub_sources[0]
80-
81- >>> hoary_pub_source.sourcepackagerelease.name
82- u'alsa-utils'
83-
84- >>> hoary_pub_source.sourcepackagerelease.version
85- u'1.0.9a-4ubuntu1'
86-
87- >>> hoary_pub_source.component.name
88- u'main'
89-
90- >>> hoary_pub_source.section.name
91- u'base'
92-
93- >>> hoary.getSourcePackagePublishing(
94- ... PackagePublishingStatus.PUBLISHED,
95- ... PackagePublishingPocket.UPDATES).count()
96- 0
97-
98-This method also allow us to restrict the results to a given
99-component:
100-
101+ >>> ubuntu = getUtility(IDistributionSet)['ubuntu']
102+ >>> hoary = ubuntu['hoary']
103 >>> component_main = getUtility(IComponentSet)['main']
104- >>> hoary.getSourcePackagePublishing(
105- ... PackagePublishingStatus.PUBLISHED,
106- ... PackagePublishingPocket.RELEASE,
107- ... component=component_main).count()
108- 5
109-
110 >>> component_multiverse = getUtility(IComponentSet)['multiverse']
111- >>> hoary.getSourcePackagePublishing(
112- ... PackagePublishingStatus.PUBLISHED,
113- ... PackagePublishingPocket.RELEASE,
114- ... component=component_multiverse).count()
115- 0
116-
117-By default the IDistribution 'main_archive' is considered, but It also
118-allows the callsite to specify one and then the result will be
119-restricted to it.
120-
121 >>> debian_archive = getUtility(IDistributionSet)['debian'].main_archive
122- >>> print debian_archive.purpose.title
123- Primary Archive
124
125- >>> hoary.getSourcePackagePublishing(
126- ... PackagePublishingStatus.PUBLISHED,
127- ... PackagePublishingPocket.RELEASE,
128- ... component=component_main, archive=debian_archive).count()
129+ >>> spphs = hoary.getSourcePackagePublishing(
130+ ... PackagePublishingPocket.RELEASE, component_main,
131+ ... warty.main_archive)
132+ >>> spphs.count()
133+ 5
134+ >>> for name in sorted(set(
135+ ... pkgpub.sourcepackagerelease.sourcepackagename.name
136+ ... for pkgpub in spphs)):
137+ ... print name
138+ alsa-utils
139+ evolution
140+ libstdc++
141+ linux-source-2.6.15
142+ pmount
143+ >>> hoary.getSourcePackagePublishing(
144+ ... PackagePublishingPocket.RELEASE, component_multiverse,
145+ ... hoary.main_archive).count()
146+ 0
147+ >>> hoary.getSourcePackagePublishing(
148+ ... PackagePublishingPocket.BACKPORTS, component_main,
149+ ... hoary.main_archive).count()
150+ 0
151+ >>> hoary.getSourcePackagePublishing(
152+ ... PackagePublishingPocket.RELEASE, component_main,
153+ ... debian_archive).count()
154 0
155
156 ISPP.getPublishedBinaries returns all the binaries generated by the
157 publication in question:
158
159 >>> warty = ubuntu['warty']
160- >>> warty_pub_sources = warty.getSourcePackagePublishing(
161- ... PackagePublishingStatus.PUBLISHED,
162- ... PackagePublishingPocket.RELEASE)
163-
164- >>> warty_pub_source = warty_pub_sources[4]
165+ >>> warty_pub_source = warty.main_archive.getPublishedSources(
166+ ... distroseries=warty, name=u'mozilla-firefox',
167+ ... status=PackagePublishingStatus.PUBLISHED).one()
168 >>> warty_pub_source.sourcepackagerelease.name
169 u'mozilla-firefox'
170 >>> warty_pub_source.sourcepackagerelease.version
171@@ -749,66 +711,30 @@
172 BinaryPackagePublishingHistory objects for the DistroSeries:
173
174 >>> warty = ubuntu['warty']
175- >>> bpphs = warty.getBinaryPackagePublishing()
176+ >>> bpphs = warty.getBinaryPackagePublishing(
177+ ... "i386", PackagePublishingPocket.RELEASE, component_main,
178+ ... warty.main_archive)
179 >>> bpphs.count()
180- 10
181+ 8
182 >>> 'mozilla-firefox' in set(
183 ... pkgpub.binarypackagerelease.binarypackagename.name
184 ... for pkgpub in bpphs)
185 True
186-
187-It also allows us to pass wanted strings like: name, version, archtag and
188-sourcename.
189-
190- >>> warty.getBinaryPackagePublishing(
191- ... name="nosuchpackage").count()
192- 0
193- >>> warty.getBinaryPackagePublishing(
194- ... version="nosuchversion").count()
195- 0
196- >>> warty.getBinaryPackagePublishing(
197- ... archtag="nosucharch").count()
198- 0
199- >>> warty.getBinaryPackagePublishing(
200- ... sourcename="nosuchsource").count()
201- 0
202-
203-We can restrict the results by component:
204-
205- >>> warty.getBinaryPackagePublishing(
206- ... component=component_main).count()
207- 10
208- >>> warty.getBinaryPackagePublishing(
209- ... component=component_multiverse).count()
210- 0
211-
212-By pocket:
213-
214- >>> warty.getBinaryPackagePublishing(
215- ... pocket=PackagePublishingPocket.RELEASE).count()
216- 10
217- >>> warty.getBinaryPackagePublishing(
218- ... pocket=PackagePublishingPocket.BACKPORTS).count()
219- 0
220-
221-Or any combination of them:
222-
223- >>> warty.getBinaryPackagePublishing(
224- ... sourcename="alsa", pocket=PackagePublishingPocket.RELEASE,
225- ... component=component_main).count()
226- 0
227-
228- >>> warty.getBinaryPackagePublishing(
229- ... name="mozilla-firefox", archtag='i386',
230- ... component=component_main).count()
231- 2
232-
233-As getSourcePackagePublishing, getBinaryPublishing accepts 'archive'
234-parameter for result restriction:
235-
236- >>> warty.getBinaryPackagePublishing(
237- ... name="mozilla-firefox", archtag='i386',
238- ... component=component_main, archive=debian_archive).count()
239+ >>> warty.getBinaryPackagePublishing(
240+ ... "nope", PackagePublishingPocket.RELEASE, component_main,
241+ ... warty.main_archive).count()
242+ 0
243+ >>> warty.getBinaryPackagePublishing(
244+ ... "i386", PackagePublishingPocket.RELEASE, component_multiverse,
245+ ... warty.main_archive).count()
246+ 0
247+ >>> warty.getBinaryPackagePublishing(
248+ ... "i386", PackagePublishingPocket.BACKPORTS, component_main,
249+ ... warty.main_archive).count()
250+ 0
251+ >>> warty.getBinaryPackagePublishing(
252+ ... "i386", PackagePublishingPocket.RELEASE, component_main,
253+ ... debian_archive).count()
254 0
255
256 getAllPublishedSources will return all publications with status PUBLISHED
257
258=== modified file 'lib/lp/registry/interfaces/distroseries.py'
259--- lib/lp/registry/interfaces/distroseries.py 2012-07-03 08:04:35 +0000
260+++ lib/lp/registry/interfaces/distroseries.py 2012-09-07 05:49:18 +0000
261@@ -733,23 +733,18 @@
262 def addSection(section):
263 """SQLObject provided method to fill a related join key section."""
264
265- def getBinaryPackagePublishing(
266- name=None, version=None, archtag=None, sourcename=None, orderBy=None,
267- pocket=None, component=None, archive=None):
268+ def getBinaryPackagePublishing(archtag, pocket, component, archive):
269 """Get BinaryPackagePublishings in a DistroSeries.
270
271- Can optionally restrict the results by name, version,
272- architecturetag, pocket and/or component.
273+ Can optionally restrict the results by architecturetag, pocket and/or
274+ component.
275
276- If sourcename is passed, only packages that are built from
277- source packages by that name will be returned.
278 If archive is passed, restricted the results to the given archive,
279 if it is suppressed the results will be restricted to the
280 distribution 'main_archive'.
281 """
282
283- def getSourcePackagePublishing(status, pocket, component=None,
284- archive=None):
285+ def getSourcePackagePublishing(pocket, component, archive):
286 """Return a selectResult of ISourcePackagePublishingHistory.
287
288 According status and pocket.
289
290=== modified file 'lib/lp/registry/model/distroseries.py'
291--- lib/lp/registry/model/distroseries.py 2012-08-08 05:36:44 +0000
292+++ lib/lp/registry/model/distroseries.py 2012-09-07 05:49:18 +0000
293@@ -1141,91 +1141,30 @@
294 return SourcePackagePublishingHistory.select(
295 query, clauseTables=['Archive'], orderBy="id")
296
297- def getSourcePackagePublishing(self, status, pocket, component=None,
298- archive=None):
299- """See `IDistroSeries`."""
300- archives = self.distribution.getArchiveIDList(archive)
301-
302- clause = """
303- SourcePackagePublishingHistory.sourcepackagename=
304- SourcePackageName.id AND
305- SourcePackagePublishingHistory.distroseries=%s AND
306- SourcePackagePublishingHistory.archive IN %s AND
307- SourcePackagePublishingHistory.status=%s AND
308- SourcePackagePublishingHistory.pocket=%s
309- """ % sqlvalues(self, archives, status, pocket)
310-
311- if component:
312- clause += (
313- " AND SourcePackagePublishingHistory.component=%s"
314- % sqlvalues(component))
315-
316- orderBy = ['SourcePackageName.name']
317- clauseTables = ['SourcePackageName']
318-
319- return SourcePackagePublishingHistory.select(
320- clause, orderBy=orderBy, clauseTables=clauseTables)
321-
322- def getBinaryPackagePublishing(
323- self, name=None, version=None, archtag=None, sourcename=None,
324- orderBy=None, pocket=None, component=None, archive=None):
325- """See `IDistroSeries`."""
326- archives = self.distribution.getArchiveIDList(archive)
327-
328- query = ["""
329- BinaryPackagePublishingHistory.binarypackagerelease =
330- BinaryPackageRelease.id AND
331- BinaryPackagePublishingHistory.distroarchseries =
332- DistroArchSeries.id AND
333- BinaryPackageRelease.binarypackagename =
334- BinaryPackageName.id AND
335- BinaryPackageRelease.build =
336- BinaryPackageBuild.id AND
337- BinaryPackageBuild.source_package_release =
338- SourcePackageRelease.id AND
339- SourcePackageRelease.sourcepackagename =
340- SourcePackageName.id AND
341- DistroArchSeries.distroseries = %s AND
342- BinaryPackagePublishingHistory.archive IN %s AND
343- BinaryPackagePublishingHistory.status = %s
344- """ % sqlvalues(self, archives, PackagePublishingStatus.PUBLISHED)]
345-
346- if name:
347- query.append('BinaryPackageName.name = %s' % sqlvalues(name))
348-
349- if version:
350- query.append('BinaryPackageRelease.version = %s'
351- % sqlvalues(version))
352-
353- if archtag:
354- query.append('DistroArchSeries.architecturetag = %s'
355- % sqlvalues(archtag))
356-
357- if sourcename:
358- query.append(
359- 'SourcePackageName.name = %s' % sqlvalues(sourcename))
360-
361- if pocket:
362- query.append(
363- 'BinaryPackagePublishingHistory.pocket = %s'
364- % sqlvalues(pocket))
365-
366- if component:
367- query.append(
368- 'BinaryPackagePublishingHistory.component = %s'
369- % sqlvalues(component))
370-
371- query = " AND ".join(query)
372-
373- clauseTables = ['BinaryPackagePublishingHistory', 'DistroArchSeries',
374- 'BinaryPackageRelease', 'BinaryPackageName',
375- 'BinaryPackageBuild', 'SourcePackageRelease',
376- 'SourcePackageName']
377-
378- result = BinaryPackagePublishingHistory.select(
379- query, distinct=False, clauseTables=clauseTables, orderBy=orderBy)
380-
381- return result
382+ def getSourcePackagePublishing(self, pocket, component, archive):
383+ """See `IDistroSeries`."""
384+ return Store.of(self).find(
385+ SourcePackagePublishingHistory,
386+ SourcePackagePublishingHistory.archive == archive,
387+ SourcePackagePublishingHistory.distroseries == self,
388+ SourcePackagePublishingHistory.pocket == pocket,
389+ SourcePackagePublishingHistory.component == component,
390+ SourcePackagePublishingHistory.status ==
391+ PackagePublishingStatus.PUBLISHED)
392+
393+ def getBinaryPackagePublishing(self, archtag, pocket, component, archive):
394+ """See `IDistroSeries`."""
395+ return Store.of(self).find(
396+ BinaryPackagePublishingHistory,
397+ DistroArchSeries.distroseries == self,
398+ DistroArchSeries.architecturetag == archtag,
399+ BinaryPackagePublishingHistory.archive == archive,
400+ BinaryPackagePublishingHistory.distroarchseries ==
401+ DistroArchSeries.id,
402+ BinaryPackagePublishingHistory.pocket == pocket,
403+ BinaryPackagePublishingHistory.component == component,
404+ BinaryPackagePublishingHistory.status ==
405+ PackagePublishingStatus.PUBLISHED)
406
407 def getBuildRecords(self, build_state=None, name=None, pocket=None,
408 arch_tag=None, user=None, binary_only=True):
409
410=== modified file 'lib/lp/soyuz/model/archive.py'
411--- lib/lp/soyuz/model/archive.py 2012-08-20 14:31:11 +0000
412+++ lib/lp/soyuz/model/archive.py 2012-09-07 05:49:18 +0000
413@@ -722,7 +722,7 @@
414 BinaryPackagePublishingHistory.archive = %s AND
415 BinaryPackagePublishingHistory.binarypackagerelease =
416 BinaryPackageRelease.id AND
417- BinaryPackageRelease.binarypackagename =
418+ BinaryPackagePublishingHistory.binarypackagename =
419 BinaryPackageName.id
420 """ % sqlvalues(self)]
421 clauseTables = ['BinaryPackageRelease', 'BinaryPackageName']
422@@ -988,7 +988,8 @@
423 return store.find(
424 BinaryPackagePublishingHistory,
425 BinaryPackageName.name == dep_name,
426- BinaryPackageRelease.binarypackagename == BinaryPackageName.id,
427+ BinaryPackagePublishingHistory.binarypackagename ==
428+ BinaryPackageName.id,
429 BinaryPackagePublishingHistory.binarypackagerelease ==
430 BinaryPackageRelease.id,
431 BinaryPackagePublishingHistory.distroarchseries ==