On a front page with 10 article teasers, template_preprocess() is called 40 times (10 times for 'node', 10 times for 'field', 10 times for 'user_picture', 5 times for 'region', 3 times for 'block', once for 'page' and once for 'html').

On a node with 50 comments, template_preprocess() is called 114 times (50 for 'comment', 51 for 'user_picture', and another 13). If #538164: Comment body as field lands, and if the hack that's bypassing field theming is removed from it, that will add another 50 calls, because there's a desire to preserve field.tpl.php as a template and not convert it to a function (#659788-3: [meta issue] theme('field') is too slow, which is inhibiting its more widespread use) if possible.

So, here's a patch that optimizes template_preprocess(). In preliminary benchmarks, I'm seeing a 1% improvement for the 10 node teasers page and a 2% improvement for the node with 50 comments page, but I'd appreciate someone confirming that from another system.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

effulgentsia’s picture

Issue tags: +Performance

tagging

effulgentsia’s picture

+++ includes/theme.inc	16 Dec 2009 00:51:02 -0000
@@ -2234,34 +2234,57 @@ function template_preprocess(&$variables
+  if (!isset($default_variables) || ($user != $default_variables['user'])) {

s/!=/!==/

This review is powered by Dreditor.

yched’s picture

Just wondering:

+  $default_variables = &$drupal_static[__FUNCTION__];
+  // Global $user object shouldn't change during a page request once rendering
+  // has started, but if there's an edge case where it does, re-fetch the
+  // variables appropriate for the new user.
+  if (!isset($default_variables) || ($user != $default_variables['user'])) {
+    $default_variables = _template_preprocess_default_variables();
+  }
+  $variables += $default_variables;

Won't that cause alterations on $variables later down the road affect the $default_variables used for other preprocess calls, by the game of var references ?

moshe weitzman’s picture

$user != $default_variables['user']

can you compare stdClass objects like that? How is equality determined?

i have a minor, non specific worry about this patch. static caching stuff like db_is_active() seems wrong. but i'm ok with this given that our test suite would catch any big mistake.

effulgentsia’s picture

Re #3: I don't think so. $default_variables is a reference, but $variables += $default_variables does a by-value copy of the items within $default_variables to $variables.

Re #4: Patch #2 fixed that to !== which is true if the two objects are not the same instance of the same class: http://php.net/manual/en/language.oop5.object-comparison.php.

catch’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
55.31 KB
82.36 KB

I had previously opened #537094: Optimize template_preprocess() (300% speedup) but won't fixed it again due to similar concerns to Moshe, and it being a relatively small optimization over the whole request. However this has additional optimizations I'd not spotted, and was before we had the new drupal_static() pattern, so it looks a lot cleaner. Also I think it's really unlikely that the return value of db_is_active() changes between one call to template_preprocess() and the next during a request, and if it does then something much worse is going on.

I did a before/after comparison on the front page with ten nodes, viewed by a normal authenticated user with only default permissions. This reduces total time spent in 38 calls to template_preprocess() down from 1.72% of the request, to 0.25%. That's less than 1/6th the time, which is great. My previous patch had reduced down from 3% of the request (when called 478 times) down to 1% - so it's twice as fast as that too. Screenshots attached, there's also before/after screenshots on the other issue for addtional data on what this looks like when called more often (i.e. a comment listing).

I'm happy with the answers in #5 to yched and moshe, and this is a very nice improvement which will make field API a lot less costly, so RTBC.

moshe weitzman’s picture

OK, I'm +1 for this too. Lets remove the stigma that templates are significantly slower than theme functions.

effulgentsia’s picture

re-rolled.

effulgentsia’s picture

Oops. #10 was a bad re-roll that failed to take full advantage of the recently committed improvement to the advanced drupal_static() pattern. This one fixes it.

Here's more benchmark summary to complement #8. Specifically, I started this issue to get us to the point where comment body can be themed using theme('field') without it incurring an unacceptable performance penalty, so the benchmark summary here follows the same pattern as on #678714-5: Unify use of theme hook / template suggestions, fix clobbering problems, and improve suggestion discovery performance for viewing node with 50 comments:

HEAD: 201.1ms
HEAD plus allowing comment body to use theme('field') (i.e., remove the hack in comment_build_content()): 214.3ms (+6.6%)
HEAD plus allowing comment body to use theme('field') plus this patch: 212.1ms (+5.5%)

In other words, once we enable comment body to be themed as a normal field, this patch gives us a net 1% savings. Not all of that is from optimizing the theme('field') call, since this patch also optimizes all calls to template_preprocess(). Also note that the reason for the difference in the above 6.6% number from the other issue's 7.6% number is partially because #667038: Optimize template_process() landed which is already helping theme('field') have a little less overhead. Finally, the savings from here is additive with the one in #678714: Unify use of theme hook / template suggestions, fix clobbering problems, and improve suggestion discovery performance, so if both land, allowing comment body to be themed with theme('field') would only cost ~4% on a node with 50 comments. More improvements may still be possible: what's our target?

webchick’s picture

Status: Reviewed & tested by the community » Needs work

This looks harmless enough.

However, it no longer applies.

effulgentsia’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
3.16 KB

Caught me just before I was stepping away from the computer :)

Re-rolled.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Thanks! Committed to HEAD.

Status: Fixed » Closed (fixed)
Issue tags: -Performance

Automatically closed -- issue fixed for 2 weeks with no activity.