Merge lp://staging/~jtv/launchpad/bug-711077 into lp://staging/launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Jeroen T. Vermeulen
Approved revision: no longer in the source branch.
Merged at revision: 12368
Proposed branch: lp://staging/~jtv/launchpad/bug-711077
Merge into: lp://staging/launchpad
Diff against target: 667 lines (+299/-120)
12 files modified
lib/lp/app/browser/configure.zcml (+6/-0)
lib/lp/app/browser/tales.py (+19/-0)
lib/lp/bugs/interfaces/bugbranch.py (+9/-5)
lib/lp/bugs/model/bugbranch.py (+44/-34)
lib/lp/bugs/tests/test_bugbranch.py (+89/-32)
lib/lp/code/browser/branchlisting.py (+19/-11)
lib/lp/code/browser/tests/test_revisionauthor.py (+82/-0)
lib/lp/code/interfaces/revision.py (+3/-0)
lib/lp/code/model/revision.py (+4/-3)
lib/lp/code/model/tests/test_revision.py (+1/-1)
lib/lp/code/templates/branch-listing.pt (+13/-30)
lib/lp/registry/model/person.py (+10/-4)
To merge this branch: bzr merge lp://staging/~jtv/launchpad/bug-711077
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
j.c.sackett (community) code* Approve
Review via email: mp+49242@code.staging.launchpad.net

Commit message

[r=jcsackett,sinzui][bug=711077] Optimize +code-index.

Description of the change

= Summary =

Some +code-index indexes were timing out.

There were several main culprits:
 * Code to figure out whether a branch is attached to bugs was too roundabout.
 * Following references between objects can be costly even from cache.
 * Authors' names and icons were retrieved one icon at a time.
 * Complex tooltips with last-revision author info were constructed in TAL.
 * Counting and querying merge proposals is complex, costly, and duplicative.
 * ValidPersonCache is now a view, and hard to cache.

== Proposed fix ==

I addressed most of the issues I found, just not the last two ones: branch merge proposals and ValidPersonCache. It might help if we could get rid of the ValidPersonCache view in the schema at some point.

Fixes:
 * A new getBranchesWithVisibleBugs queries exactly what's needed, no more.
 * Many references can be bypassed using foreign keys' numeric values.
 * A new fetchAuthorsForDisplay queries persons, along with their icon info.
 * A new link formatter renders RevisionAuthor links directly in python.

== Pre-implementation notes ==

Robert felt that GIL issues might be behind the problem, so I had a profile taken. I was unable to make much of the results though, and so focused on conventional optimization.

== Implementation details ==

Tests for getBranchesWithVisibleBugs are direct descendants of existing ones for getBugBranchesForBranches, which I gradually reworked since they weren't being used anywhere else. The new code passed the old tests, but in the end I broke them down into smaller units with more explicit test goals.

== Tests ==

I ran all non-Windmill code tests plus test_bugbranch, and have a full EC2 run underway, but for a quick peek at the most you can run:

{{{
./bin/test -vvc lp.bugs.tests.test_bugbranch -t getBranchesWithVisibleBugs
./bin/test -vvc lp.code.browser.tests.test_revisionauthor -t RevisionAuthorFormatter
./bin/test -vvc lp.code.model.tests.test_revision -t fetchAuthorsForDisplay
}}}

== Demo and Q/A ==

This is an optimization branch, so don't expect any changes in functionality. But have a look at: https://code.qastaging.launchpad.net/openobject-addons/+code-index

That page should render fast enough (once qastaging's cache is warmed up to a realistic level) and not break. In fact a cowboyed version of the branch is running on qastaging as I write this.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/code/templates/branch-listing.pt
  lib/lp/bugs/tests/test_bugbranch.py
  lib/lp/code/interfaces/revision.py
  BRANCH.TODO
  lib/lp/app/browser/configure.zcml
  lib/lp/app/browser/tales.py
  lib/lp/bugs/interfaces/bugbranch.py
  lib/lp/code/model/tests/test_revision.py
  lib/lp/bugs/model/bugbranch.py
  lib/lp/code/model/revision.py
  lib/lp/code/browser/branchlisting.py
  lib/lp/code/browser/tests/test_revisionauthor.py

To post a comment you must log in.
Revision history for this message
j.c.sackett (jcsackett) wrote :

Jeroen--

Good improvements, especially the cleaning up of the TAL.

Your tests have a recurring use of makePerson (as user in one block, as author in another) that could be done once in setUp and then reused, which would speed up the testcase.

There are a variety of other calls to makePerson which I think are only to make sure a person other than the user is involved; those could probably also be replaced by creating one other person in setUp and reusing that person.

Otherwise, this looks good.

I'm marking as Approve so you're not blocked on this when you start your day, but I would really like to see the TestCase changes made.

review: Approve (code*)
Revision history for this message
Robert Collins (lifeless) wrote :

fetchAuthorsForDisplay looks highly duplicative of
PersonSet.getPrecachedPersonsFromIDSs and
PersonSet.cacheBrandingForPeople

You might like to layer on that rather than building completely from scratch.

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Okay, I extended PersonSet.getPrecachedPersonsFromIDS (horrible name!) and used that instead. The fetchAuthorsForDisplay method grew out of something that started fetching at RevisionAuthor, which turned out to be subobtimal.

Jon: moving things into setUp doesn't save anything, since each test method gets its own TestCase object to play with. Each needs to be set up anyway. Luckily creating objects usually isn't very expensive, and we generally prefer it over hidden dependencies across arbitrary reuse. In practice, object creation in setUp can even slow things down as not all tests may make use of all the setup!

Also, we've learned that creating implicit state from setUp easily obscures what the test does, so it's generally better to create helper methods for setup than it is to chuck everything into the TestCase from setUp.

Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi Jeroen.

Thank you for integrating your work with getPrecachedPersonsFromIDS(). I think your branch is good to land.

review: Approve (code)
Revision history for this message
Robert Collins (lifeless) wrote :

Does getTipRevisions eager load revision_author ? If not, that will still be a source of late evaluation. - needs a set query on that step too.

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Yes, it does.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.