Problem/Motivation
I was profiling a node with 49 products on it with Xhprof and noticed that the t() function was getting called a bunch. Further more it was inside commerce_product_field_extra_fields() that would get called for each product on that page. I have 5 or 6 product variations.
Proposed resolution
Static cache commerce_product_field_extra_fields().
Remaining tasks
User interface changes
API changes
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | 2354561-1.patch | 3.22 KB | joelpittet |
| xhprof-commerce_product_field_extra_fields.png | 207.29 KB | joelpittet |

Comments
Comment #1
joelpittetHere's what I did for the performance boost. Any drawbacks?
Comment #2
rszrama commentedWow. I don't see any drawbacks here. Honestly, it seems like an issue that core would do well to optimize in general; it has a static cache for field info, why not for extra field info? Otherwise we're left having to implement our own static cache for every entity type. : P
That said, I'm not opposed to implemented the static cache here and simultaneously opening a core issue. I don't suppose you'd have a moment to search and see if someone's already working on a core fix?
Comment #3
joelpittetThis is the only one I could find #870292: hook_field_extra_fields() results should be cached by language that was similar but doesn't static cache and doesn't look like it caches... but the title says otherwise.
And this issue says it is cached... but I don't think it is:S
#730308-9: taxonomy_vocabulary_get_names() called on every field_attach_view()
Comment #4
fabianx commentedDepending how often this is called, might consider the drupal_static_fast pattern here instead.
I think it would make sense.
Comment #5
torgospizzaThis patch seemed to have a positive effect on our performance as well. Any chance we can get it rolled in?
Comment #6
rszrama commentedGuess I kinda lost track of this. Committed. : )
Comment #7
torgospizzaThanks Ryan!
Comment #8
joelpittetThanks @rszrama.
@Fabianx I am curious to know where I can read up on the different between the two drupal static caching patterns? They look very similar and @dawehner tried to explain it but didn't quite sink in, the differences and when to use them.
Comment #9
fabianx commented@joelpittet drupal static fast saves the function call to &drupal_static() basically.
It does so by using a static var that references the one retrieved from drupal_static.
Therefore drupal_static_reset still works, but it is still fast. Quite some reference trick!
I hope that helps.
Comment #10
joelpittetOh I think it's coming back to me thanks @Fabianx. It's intention is to reduce the # of function calls as well, specifically to drupal_static(). so in this case we wouldn't see 345 new calls to drupal_static(), just one call.
So although drupal_static() is cached and fast, not having to call it would be a bit faster if you have many calls. And in this case we have 300+ calls which could be significantly more...
Since I don't see a commit message on this issue, maybe it hasn't been committed and I can roll another patch for that @rszrama?
Comment #11
rszrama commentedI suppose I'm not opposed, but is it really necessary? We aren't using this pattern anywhere else, and I'm not sure how much performance impact we actually expect it to have relative to the other things that eat up time / memory in Commerce / Drupal 7.
Comment #12
joelpittetIt can be huge...
Run the above in test.php
drush scr test.phpMy results were 55 seconds vs 34 seconds.
But with an example even 100 times what we are dealing with here of 347 calls:
And with exactly 345 calls:
So IMO, it's not completely necessary in this case but handy to know if the # calls is > 5000 it could have some nice savings.
Comment #13
rszrama commentedHah, funny. I didn't catch what was going on at first, but it's interesting that we're now reverting to the pre-drupal_static() pattern of static caching. I mean, why even use drupal_static() at all in this case? You lose the benefit of being able to flush the static cache remotely, so we could just ditch it entirely, no?
Comment #14
joelpittet@rszrama not sure I follow.
We should be using the &drupal_static. Just not a huge win on the fast drupal_static pattern unless there are a fairly large numbers of calls.
Comment #15
joelpittet@rszrama I downloaded -dev and it didn't have this patch applied so I'm moving back to NR.
Comment #17
rszrama commentedIt just wasn't pushed b/c I didn't see a bogus authentication error last time I tried a push.
What I was saying previously is just that the "new" pattern may as well bypass drupal_static() entirely and just use a local static variable. That's what we did before drupal_static() came along, but the rationale with an external static variable manager was that we'd be able to clear those caches from external scopes.
Not a big deal. Just pointing out how funny it is that we engineered our way to worse performance and have now invented a reverted pattern without just jettisoning the drupal_static() altogether. : P
Comment #18
joelpittet@rszrama ah haha I see now. static -> drupal_static -> drupal_static + static. A bit over engineered yes but I guess like you and @Fabianx said we still can externally clear them out.
Thanks for committing this:) I've heard that bogus auth error happen to a few committers so far on push.
Comment #19
torgospizzaOddly enough, after pushing this patch and getting a big surge of traffic last night, performance actually seems to be worse. Not sure if it has to do with us also using Memcache+Panels+Panelizer, but in the panels_render_display()'s call to field_info_extra_fields(), the commerce_product_reference implementation is now the slowest.
This is all coming from New Relic when viewing a Panelized node. I'll keep digging.
Comment #20
joelpittet@torgosPizza looking at this patch I think it would be very unlikely to be this patch that caused the performance issue. It just caches the building of the extra form element building and all the extra calls to t() that were happening on every node view mode display.
Maybe the only way it could get worse (and maybe only by a few 5ms per node) is if the static cache was getting cleared all the time. (wild guess).
Comment #21
torgospizzaYou might be right. It seems like Panels/CTools is making a lot of calls to field_info_extra_fields() so it could just be that our cache is broken. I have a few other outstanding patches related to Memcache performance, so I will check those. Thanks!
Comment #22
torgospizzaI was mistaken, it's the Product Reference's implementation of hook_field_extra_fields(). Looks like that module could use some static caching as well, so I created a new Issue: #2389573: Use a static cache in commerce_product_reference_field_extra_fields().