Yesterday I was trying to find a way to add some performance tests to one of our add-ons and I came up with this:
I added one test to measure how long it takes to render 100 times the viewlet included in this package and I set an arbitrary value of 0.5 seconds as the limit.
To my surprise, tests are passing for Plone 4.2 and Plone 4.3 and fail in both Plone 5.0 and 5.1:
https://travis-ci.org/collective/collective.newsticker/builds/213848036
This is what I get locally on my machine:
Plone 4.3.12
*** PROFILER RESULTS ***
render (/home/hvelarde/collective/newsticker/src/collective/newsticker/tests/test_viewlet.py:149)
function called 1 times
307779 function calls (290776 primitive calls) in 0.451 seconds
Ordered by: cumulative time, internal time, call count
List reduced from 365 to 40 due to restriction <40>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.455 0.455 test_viewlet.py:149(render)
100 0.000 0.000 0.454 0.005 simpleviewclass.py:43(__call__)
100 0.000 0.000 0.453 0.005 pagetemplatefile.py:120(__call__)
100 0.001 0.000 0.453 0.005 pagetemplatefile.py:47(__call__)
100 0.001 0.000 0.448 0.004 pagetemplate.py:116(pt_render)
100 0.001 0.000 0.444 0.004 pagetemplate.py:234(__call__)
100 0.000 0.000 0.440 0.004 talinterpreter.py:267(__call__)
600/100 0.004 0.000 0.440 0.004 talinterpreter.py:328(interpret)
100 0.000 0.000 0.438 0.004 talinterpreter.py:850(do_condition)
1100/1000 0.002 0.000 0.388 0.000 tales.py:691(evaluate)
...
Plone 5.1b2
*** PROFILER RESULTS ***
render (/home/hvelarde/collective/newsticker/src/collective/newsticker/tests/test_viewlet.py:149)
function called 1 times
598617 function calls (547661 primitive calls) in 0.661 seconds
Ordered by: cumulative time, internal time, call count
List reduced from 326 to 40 due to restriction <40>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.664 0.664 test_viewlet.py:149(render)
100 0.000 0.000 0.664 0.007 simpleviewclass.py:43(__call__)
100 0.000 0.000 0.663 0.007 pagetemplatefile.py:120(__call__)
100 0.001 0.000 0.663 0.007 pagetemplatefile.py:47(__call__)
100 0.001 0.000 0.658 0.007 pagetemplate.py:116(pt_render)
100 0.001 0.000 0.654 0.007 engine.py:86(__call__)
100 0.001 0.000 0.653 0.007 pagetemplate.py:128(render)
100 0.001 0.000 0.652 0.007 template.py:209(render)
100 0.001 0.000 0.650 0.007 template.py:165(render)
100 0.005 0.000 0.648 0.006 d13e2e5858eac1ff5089660f6bd49440.py:22(render)
...
As you can see, there are many more function calls in Plone 5.1b2 and main suspect here seems to be Chameleon.
UPDATE 1: Plone 5 includes Chameleon 2.25; I made a test with Chameleon 3.1 but it remained almost unchanged:
Plone 5.1b2 (Chameleon 3.1)
*** PROFILER RESULTS ***
render (/home/hvelarde/collective/newsticker/src/collective/newsticker/tests/test_viewlet.py:149)
function called 1 times
598817 function calls (547861 primitive calls) in 0.652 seconds
Ordered by: cumulative time, internal time, call count
List reduced from 326 to 40 due to restriction <40>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.655 0.655 test_viewlet.py:149(render)
100 0.000 0.000 0.655 0.007 simpleviewclass.py:43(__call__)
100 0.000 0.000 0.654 0.007 pagetemplatefile.py:120(__call__)
100 0.001 0.000 0.654 0.007 pagetemplatefile.py:47(__call__)
100 0.001 0.000 0.649 0.006 pagetemplate.py:116(pt_render)
100 0.001 0.000 0.646 0.006 engine.py:86(__call__)
100 0.001 0.000 0.645 0.006 pagetemplate.py:128(render)
100 0.001 0.000 0.643 0.006 template.py:229(render)
100 0.001 0.000 0.642 0.006 template.py:165(render)
100 0.005 0.000 0.639 0.006 b2d962c72225cfd129cfe757d1259927.py:23(render)
...
UPDATE 2: I made another test adding Chameleon 3.1 to Plone 4.3.12 and the results show that Chameleon is in fact making Plone slower:
Plone 4.3.12 (Chameleon 3.1)
*** PROFILER RESULTS ***
render (/home/hvelarde/collective/newsticker/src/collective/newsticker/tests/test_viewlet.py:149)
function called 1 times
267070 function calls (250767 primitive calls) in 0.499 seconds
Ordered by: cumulative time, internal time, call count
List reduced from 319 to 40 due to restriction <40>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.502 0.502 test_viewlet.py:149(render)
100 0.001 0.000 0.502 0.005 simpleviewclass.py:43(__call__)
100 0.000 0.000 0.500 0.005 pagetemplatefile.py:120(__call__)
100 0.002 0.000 0.500 0.005 pagetemplatefile.py:47(__call__)
100 0.001 0.000 0.493 0.005 pagetemplate.py:116(pt_render)
100 0.001 0.000 0.487 0.005 engine.py:86(__call__)
100 0.002 0.000 0.486 0.005 pagetemplate.py:128(render)
100 0.002 0.000 0.483 0.005 template.py:229(render)
100 0.002 0.000 0.481 0.005 template.py:165(render)
100 0.007 0.000 0.479 0.005 b9624fa8db166ff12860b946044af1cd.py:23(render)
...
Can someone explain this?