Merge lp:~jtv/launchpad/templates-listing into lp:launchpad
| Status: | Merged | ||||
|---|---|---|---|---|---|
| Approved by: | Aaron Bentley on 2010-09-13 | ||||
| Approved revision: | no longer in the source branch. | ||||
| Merged at revision: | 11542 | ||||
| Proposed branch: | lp:~jtv/launchpad/templates-listing | ||||
| Merge into: | lp:launchpad | ||||
| Diff against target: |
716 lines (+500/-86) 7 files modified
lib/lp/translations/browser/distroseries.py (+9/-2) lib/lp/translations/browser/potemplate.py (+142/-0) lib/lp/translations/browser/productseries.py (+8/-2) lib/lp/translations/browser/tests/test_seriestemplatesview.py (+332/-0) lib/lp/translations/stories/standalone/xx-potemplate-edit.txt (+1/-3) lib/lp/translations/stories/standalone/xx-series-templates.txt (+4/-8) lib/lp/translations/templates/object-templates.pt (+4/-71) |
||||
| To merge this branch: | bzr merge lp:~jtv/launchpad/templates-listing | ||||
| Related bugs: |
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Aaron Bentley (community) | Approve on 2010-09-13 | ||
| Launchpad code reviewers | code | 2010-09-11 | Pending |
|
Review via email:
|
|||
Commit Message
Move DistroSeries:
Description of the Change
= Bug 608349 =
Even after the phenomenal optimization job Adi and Danilo did on the DistroSeries:
In this hobby branch I move the rendering of the template listing rows from the TAL into the browser code. This keeps the TAL cleaner and simpler, takes the TAL parser out of the critical loop, and allows for more conventional optimization. I hope the new browser code in its own way exposes the structure more clearly than the TAL with its conditionals and irregularly-sized columns did.
On my local machine, this speeds up an Ubuntu-sized +templates page by 2—3×.
I did keep the central loop in TAL. Growing one huge string for potentially thousands of templates could get quite unwieldy; the templating engine will hopefully do things in a more "streaming" fashion. With any luck the listing's HTML can start flowing to the client before rendering has completed.
Two "conventional optimizations" are noteworthy:
* The view classes can (and do) provide their own, faster alternatives to canonical_url.
* Using self.user instead of context/
By far most of the new code is actually in a new unit-test for the views. The browser-code approach allows for much more extensive and detailed testing. In particular of course the test verifies that the optimized URL generation code is equivalent to canonical_url. It actually produces shorter, relative URLs; this is the only semantic change and it affected two of our existing test stories in a very minor way. The rest of the HTML also got about 40% shorter (or 50% in number of lines), and I think easier to read.
Jeroen
| Robert Collins (lifeless) wrote : | # |
| Jeroen T. Vermeulen (jtv) wrote : | # |
> This isn't a review, but I'm curious how you've established that this
> is faster
I haven't actually established that it is faster; I would like to do that based on timings on actual production data on one of the test servers. In practice it's not so much the speed of producing these listings that we care about, as it is the speed of producing specifically the Ubuntu listings.
> Also, we have a new template engine in the
> pipeline :- we probably don't want a lot of procedural code doing
> template-work (or we want all our code doing that).
This is a bit of a special case given the enormous amounts of data that show up in the page. (There are good reasons for doing it this way, so "just batch it" is a poor plan B).
If the new template engine turns out to be faster than straight-through python code, then we should probably scuttle this branch.
> Uhm for generating big texts in python, do this:
> buffer = []
> for <blah>:
> buffer.
> ...
> return ''.join(buffer)
>
> This isn't as efficient as a pure chunking end-to-end implementation,
> but it is the next best thing.
I do that for smaller chunks. For the page as a whole however I think the templating engine is likely to be better tuned. With literally thousands of lines on a page, the ability to start sending HTML before the full list has been rendered could be a real plus.
> Lastly, you might like to nab Gary or someone from foundations to talk
> about the implications of canonical_url returning relative paths :
> we've got some stuff changing in that area just recently.
Something I didn't make clear in the cover letter: it's only a very specific use-case of canonical_url, on one kind of page and for one kind of object that it replaces. The tests should expose any changes that break the equivalence to canonical_url.
Jeroen
| Robert Collins (lifeless) wrote : | # |
On Sat, Sep 11, 2010 at 10:37 PM, Jeroen T. Vermeulen <email address hidden> wrote:
>> This isn't a review, but I'm curious how you've established that this
>> is faster
>
> I haven't actually established that it is faster; I would like to do that based on timings on actual production data on one of the test servers. In practice it's not so much the speed of producing these listings that we care about, as it is the speed of producing specifically the Ubuntu listings.
Staging is currently not suitable for perf testing except under quite
controlled circumstances (see my bug on foundations - 'staging gets
overloaded') - just a heads up. If I was doing this I think I'd
compare the page before and after locally using the comment field to
get local timings.
>> Also, we have a new template engine in the
>> pipeline :- we probably don't want a lot of procedural code doing
>> template-work (or we want all our code doing that).
>
> This is a bit of a special case given the enormous amounts of data that show up in the page. (There are good reasons for doing it this way, so "just batch it" is a poor plan B).
>
> If the new template engine turns out to be faster than straight-through python code, then we should probably scuttle this branch.
I don't really like batching most of the time either. As for template
being faster - I wouldn't necessarily expect that, but the tradeoff
between understandability and performance might be less skewed with
chameleon. You could try it - its in the tree now.
>> This isn't as efficient as a pure chunking end-to-end implementation,
>> but it is the next best thing.
>
> I do that for smaller chunks. For the page as a whole however I think the templating engine is likely to be better tuned. With literally thousands of lines on a page, the ability to start sending HTML before the full list has been rendered could be a real plus.
With our current design we simply cannot do that:
- any exception before publication finishes generates an OOPS
- so no data is sent until we know we won't have an OOPS
-> Don't worry about incremental performance here, worry about total
performance.
-Rob
| Jeroen T. Vermeulen (jtv) wrote : | # |
I don't know what you mean with the part about the comment field. Perhaps you're thinking of my Librarian branch that deals with discrepancies between the choices of default or slave stores?
Anyway, the reason I'm not testing locally is memory. If I create the thousands of packages and templates I need for a realistic test, the differences in caching characteristics between my local system and a production system would probably invalidate the results.
| Robert Collins (lifeless) wrote : | # |
On Sun, Sep 12, 2010 at 4:45 PM, Jeroen T. Vermeulen <email address hidden> wrote:
> I don't know what you mean with the part about the comment field. Perhaps you're thinking of my Librarian branch that deals with discrepancies between the choices of default or slave stores?
No. View the source of a page - at the bottom there is a comment
listing some stats, including the time to render.
> Anyway, the reason I'm not testing locally is memory. If I create the thousands of packages and templates I need for a realistic test, the differences in caching characteristics between my local system and a production system would probably invalidate the results.
The theory is that everything is fast except for rendering: adding
thousands of templates on on package should be fine : even at 1K per
row, that would be MB's, not 100's of MB's of increased:
- pgsql buffer
- storm buffer
- objects in memory.
As long as you don't drive yourself into swap you'll be able to tell,
with a much lower turnaround time than reproducing on the actual
dataset.
If you aren't in swap, and this branch is a faster - say 15%
consistently faster - then its a pretty good sign.
-Rob
| Jeroen T. Vermeulen (jtv) wrote : | # |
Okay, I tried it locally. I hadn't thought of the HTML comment as a "field" before, hence my confusion.
At any rate, using "wget" to eliminate as many extraneous factors as I could, the code I present here was more than twice as fast as the code we have in devel for about 1,400 templates. When I increased the number of templates by another 1,000, my version came closer to 3× as fast as devel. I think that's worthwhile.
| Jeroen T. Vermeulen (jtv) wrote : | # |
I just realized I should have posted this as a reply, not a separate comment. In a nutshell: two to three times faster, gaining more with larger data sets; and 40% smaller output (though I didn't particularly aim for it, just something nicer to read) with less than half the number of lines.
I do agree that in principle we should use the TAL. In this case however, with the variable columns list, it was a small step from (pre) moving into the view all cyclomatic complexity that shouldn't have been in the TAL in the first place, to (post) rendering entire rows there.
| Aaron Bentley (abentley) wrote : | # |
You haven't tested with chameleon, but you've said that even if switching to chameleon gives us tech debt, this approach gets rid of some other tech debt, and I'm happy with that.
It does suggest that we should put some work into speeding up canonical_url-- perhaps we really want "canonical_urls".
| Jeroen T. Vermeulen (jtv) wrote : | # |
Thanks. I wouldn't be surprised if after this, we could get yet another speedup from having some cleverly optimized bulk version of canonical_url.

This isn't a review, but I'm curious how you've established that this +assignments. Also, we have a new template engine in the
is faster (so that I can have a look in the same way at
ubuntu/
pipeline :- we probably don't want a lot of procedural code doing
template-work (or we want all our code doing that).
Uhm for generating big texts in python, do this: append( somestring)
buffer = []
for <blah>:
buffer.
...
return ''.join(buffer)
This isn't as efficient as a pure chunking end-to-end implementation,
but it is the next best thing.
Lastly, you might like to nab Gary or someone from foundations to talk
about the implications of canonical_url returning relative paths :
we've got some stuff changing in that area just recently.
-Rob