[Framework-Team] Some preliminary Plone 3.0 profiling results

Martin Aspeli optilude at gmx.net
Tue Nov 14 14:14:38 UTC 2006

Hi Alex,

I take it someone fixed PTProfiler for you?

On 11/14/06, Alexander Limi <limi at plone.org> wrote:
> Some preliminary results of running a quick PTProfiler session on Plone
> 3.0 and trying to figure out what is slowing it down.
> I was prompted to do this when I discovered that anonymous view of Plone
> 3.0 was about 30% slower than 2.5. Take these numbers as a general guide
> only, it's still early in the 3.0 process, and there's bound to be lots of
> improvement potential here.
> ANONYMOUS: 10 loads of front page, in seconds
> Template                               Total  Hits Per hit
> ==========================================================
> document_view.pt                       3.9707  10  0.3971
> plone_javascript_variables.js.pt       0.0441  10  0.0044
> portlet_navtree_macro.pt               0.0899  10  0.009
> portlets/browser/templates/column.pt   2.3798  20  0.119
> portlets/portlets/classic.pt           2.0051  50  0.0401
> portlets/portlets/events.pt            0.0221  10  0.0022
> portlets/portlets/login.pt             0.2678  10  0.0268
> portlets/portlets/news.pt              0.021   10  0.0021
> Breakdown of document_view shows (same order/units as above):
> path: plone_view/globalize             0.232   10  0.0232
> The rest of the things here use much less time, but there's probably some
> interesting things there too.
> It seems the portlets stuff is what is making it slower (more about that
> below), along with globalize.

classic.pt is nasty, because it calls globalize *for each portlet*.
This is basically to work around namespace issues (the global
namespace isn't available inside the page template).


For classic portlets, you need to have the global variables around,
obviously. I'd like to find a better way to carry that namespace over
or at least do some more clever cacheing, though. Suggestions welcome!

I'm a bit surprised by the login portlet:


It's a complex view, and maybe it needs some cacheing. It should
probably cache tools looked up with getToolByName(), if nothing else.

> LOGGED IN: 10 loads of front page, in seconds
> Template                               Total  Hits Per hit
> ==========================================================
> contentmenu.pt                         3.476   10  0.3476

There is a lot going on in the content menu, which was previously in a
template. I'd be surprised if the new code was *slower*, but it may be
that it needs to duplicate some action lookup that would otherwise be
in global_defines. In particular, there are multiple calls to
listFilteredActionsFor(). I thought this was faster now in CMF 2.1,
but maybe it's a bottleneck still.


Again, comments welcome!

If we don't mind customisation, btw, I can cut out some template fat
that was an attempt to let old customisations of global_contentmenu.pt

> document_view.pt                      10.563   10  1.0563
> plone_javascript_variables.js.pt      0.0464   10  0.0046
> portlet_navtree_macro.pt              0.0934   10  0.0093
> portlets/browser/templates/column.pt  3.0892   20  0.1545

Bear in mind this renders all portlets.

> portlets/portlets/classic.pt          2.9249   50  0.0585

As above.

> portlets/portlets/events.pt           0.0211   10  0.0021
> portlets/portlets/login.pt            0.005    10  0.0005
> portlets/portlets/news.pt             0.0183   10  0.0018
> Breakdown of document_view shows (same order/units as above):
> path: plone_view/globalize            0.8519s  10  0.08519s

This is some portlets BBB stuff for people with main_template
customisations that make globalize do slightly silly things. We could
probably cut that out if we don't mind breaking some customisations.

At the same time, I think the check for 'visible' in _prepare_slots()
(http://svn.plone.org/svn/plone/CMFPlone/trunk/browser/plone.py) may
be the source of some grief. This could end up calculating the
portlets for a particular user once to determine whether the column
should be shown, and then again to find the actual portlets to show.

This one is a bit nasty, because we need to know before-the-fact
whether there are any portlets so that we can put a tal:condition on
the <td> that is the left/right column, but without globalizing more
stuff, we may not be able to keep that information around until the
actual rendering takes place. Before, we were just acquiring a
property and seeing if it was empty. Now we look in annotations,
annotations of parents, and a site-local store of user, group and
content type portlets. It's not massively slow, but it's probably not

> python: [history[i] for i in (…)      0.8055s  10  0.08055s

What is this?

> So for logged-in, "globalize" and the versioning stuff seems to be the two
> biggest offenders by an order of magnitude, and seem to both take about
> the same amount of time.
> The portlets also seem to be inefficient both for logged in or not, but a
> lot of this time is spent in classic.pt, which we should be able to
> eliminate (since we should convert all the portlets to new-style portlets
> before shipping the release). I'm not sure if column.pt wraps/includes the
> classic.pt time.

column.pt should include the classic.pt time, since all column.pt does
is loop over each portlet (after finding them, as above) and then
render each one.

> Of course, all this might be wrong, but that's what happens when you let
> the UI guy do your benchmarking. ;)

It's useful!


More information about the Framework-Team mailing list