Problem/Motivation
@yched has reported slowness generating valid css class names in template_preprocess and was proposed a solution for this
// Initialize html class attribute for the current hook.
- $variables['classes_array'] = array($hook);
+ $variables['classes_array'] = array(drupal_html_class($hook));
But drupal_html_class also is slow and this runs on every template call.
Proposed resolution
A proposed resolution provided by @effulgentsia in comment #9 but was not approved by @Dries (comment #12)
Personally, I think this extra parameter is a little bit of a hack that degrades the DX.
And @webchick also agree with that at that moment (comment #50)
Last word on this patch was that Dries didn't like it, so once again leaving for The Spikey Haired One.
(Though I agree that it seems hackish, and it would also introduce an API change for people calling drupal_html_class() in order to take advantage of a 0.5% performance benefit outlined in #9. Not sure it's really worth it at this point, honestly.)
Remaining tasks
Patch in comment #28 fail, needs review.
Patch in comment #23 it's ok but needs approval. This patch changes the new parameter name from $underscores_only to $is_machine_name. To make to impression of less hacky.
Original report by yched
// Initialize html class attribute for the current hook.
- $variables['classes_array'] = array($hook);
+ $variables['classes_array'] = array(drupal_html_class($hook));
Not visible currently because the only templates that currently use $classes / $classes_array correspond to one-word theme hooks: theme('node'), theme('comment')...
Comments
Comment #1
yched CreditAttribution: yched commentedThe remark above also means the patch won't change any existing markup nor break CSS or jQuery behaviors.
Comment #2
agentrickardThis is correct, according to the new API for class names.
Comment #3
webchickHm. Is it possible to write a test for this?
Comment #4
yched CreditAttribution: yched commentedHmm, not sure how this can be tested right now, actually.
From the OP:
"the only templates that currently use $classes / $classes_array correspond to one-word theme hooks: theme('node'), theme('comment')..."
#499192: Fix display and forms for "Fieldable terms" changes that fact, but before this lands, I don't really see us defining a dummy test template just to check the class name :-/.
Comment #5
webchickOk, fair enough.
Committed to HEAD.
Comment #6
yched CreditAttribution: yched commentedReopening, drupal_html_class() is slow, and this runs on every template call.
In this specific case we can be smarter - a valid theme hook name is [az_].
Sorry about that.
Comment #7
effulgentsia CreditAttribution: effulgentsia commentedYes. This one's a no-brainer. The same hunk is in #652246-10: Optimize theme('field') and use it for comment body with a discussion about its impact. That hunk also has a more detailed code comment, if that's of interest. Makes sense for this hunk to land separately of that other issue which is still being worked on.
Comment #8
yched CreditAttribution: yched commentedCrap, I didn't notice that this change was already included in the perf measures over there. I was hoping we'd get a couple ms more :-(.
Agreed that it's best committed separately anyway.
Comment #9
effulgentsia CreditAttribution: effulgentsia commentedSorry for downgrading an RTBC patch, but whether in core or contrib, there's gonna be other places where only underscore -> hyphen conversion is needed and needed quickly (for example, template_preprocess_field()), and it would help code readability and greppability to still call drupal_html_class(). So, what do you think of this? If you don't like it, feel free to re-upload #6 and mark it RTBC.
Benchmarking front page with 10 article teasers:
HEAD: 82.46ms
Patch #6: 81.96ms
Patch #9: 82.00ms
There's definitely other pages with MANY more calls to template_preprocess(), but even for this simple page, there's >0.5% savings with either #6 or #9, and not much difference between the two.
Comment #10
yched CreditAttribution: yched commentedFully agreed, this approach is better.
Comment #11
effulgentsia CreditAttribution: effulgentsia commentedUpdating title and tags for #9.
Comment #12
Dries CreditAttribution: Dries commentedPersonally, I think this extra parameter is a little bit of a hack that degrades the DX.
Comment #13
moshe weitzman CreditAttribution: moshe weitzman commentedYes it is a tiny hack, but I think it is a bit much to say that it degrades DX. No developer outside of a core theme system hacker has to care about this. This is just the sort of hack that you have to accept in order to speed up core. My .02.
Comment #14
catchAgreed. Bad DX is atrocities like hook_mail(), not optional parameters to largely internal functions.
Tiny, self-contained, documented hacks which only a handful of people will ever see but speed things up are completely harmless. Needless CPU usage on tens of thousands of servers running Drupal sites isn't. We don't have a lot of space to reduce PHP overhead for Drupal 7 despite it being so poor, so we need to do what we can.
Comment #17
effulgentsia CreditAttribution: effulgentsia commentedspam sucks (#15,#16).
Comment #18
webchickLeaving for Dries to respond to this one.
Comment #19
sunerrr, an additional confusing argument for 0.04 ms? Are you serious, guys?
Comment #20
moshe weitzman CreditAttribution: moshe weitzman commentedwe said before that these benchmarks are done on a very simple page. they will be more favorable on real pages that theme the value every cell in a table (Views) or list lots of username and so on.
Comment #21
effulgentsia CreditAttribution: effulgentsia commentedRe #19: #6 and #9 are essentially equivalent performance-wise. Either one vs. HEAD is what's important (>0.5% on a simple page, more on complex pages as Moshe points out). Personally, I think #9 is better than #6 in terms of code readability, especially if we find places other than template_preprocess() that can benefit from the same optimization (and we most certainly will).
Comment #22
sunok, let's do this.
Comment #23
effulgentsia CreditAttribution: effulgentsia commented@Dries, #12:
This patch changes the new parameter name from $underscores_only to $is_machine_name. Does that make it feel less hacky?
Comment #24
JohnAlbinThe reason why drupal_html_class() wasn't originally included in template_preprocess() was because of the performance issues. I'm glad the bug (whoops!) was fixed in #5 above and I am totally cool with the added parameter. It means we can use a drupal_html_class() in more places without killing performance.
In fact, here's eff's patch with a few more places using the new is_machine_name parameter. I've also added a test for the new parameter.
Comment #26
JohnAlbinAnd here's the patch where the test that checks the $is_machine_name parameter is no longer broken and actually uses said parameter. :-p
Comment #28
JohnAlbinBah. Attached the wrong patch in #26. This is the one I meant.
Comment #29
yched CreditAttribution: yched commentedPatch should be ready, it's now a question of whether we want to do this.
Back to RTBC for Dries / webchick. Discussion is in #12-#24 above.
Comment #30
sunReady to fly.
Comment #31
yched CreditAttribution: yched commentedEr, yes, that's what I meant. /me slaps himself.
Comment #32
catchIf we don't do this version of the patch, then we should go through and convert all the places that need the optimization to strtr(), per #6.
Comment #33
quicksketchI know this is already RTBC, but we could we get one further change into this issue? Right now the template_preprocess() function is super-aggressive when it comes to creating these variables. Could we wrap them in an isset() check?
In template_preprocess():
In theme.inc template_process()...
BTW, what's up with a function named template_preprocess() and one with template_process()? I was literally looking for 5 minutes to distinguish the difference between the two names.
Comment #34
quicksketchTo elaborate on the problem in #33, I actually had a template that used a variable called "classes", that wasn't even related to CSS at all. It was literally an array of courses (as in for teaching). But because template_preprocess() runs on all templates, it kept blowing it away with the name of the template instead. I appreciate the "help" the theme system was providing, but it was a downright baffling experience trying to figure out what was happening to my variables.
Comment #35
effulgentsia CreditAttribution: effulgentsia commented@quicksketch (re #33/#34): Let's discuss that in a separate issue, please. Please open one, post a patch, and link from here.
The D7 theme() function preprocesses variables in two phases. It does all the *_preprocess()/*_preprocess_HOOK() functions first, as in D6. Then, new in D7, a 2nd phase where it calls *_process()/*_process_HOOK() functions. I'm not sure that "process" was the best choice for the name of the 2nd phase, but "postpreprocess" or "latepreprocess" have their own ugliness too. Too late for changing the naming approach for D7, but let's improve it for D8.
Comment #36
quicksketchI'll wait for this issue to complete. I can't post a patch with the overlap. In the mean time I've just renamed the variable to "courses".
Comment #37
axyjo CreditAttribution: axyjo commented#28: template_preprocess_class-680022-28.patch queued for re-testing.
It's been a long time since it was rolled. Let's see if it still applies/passes.
Comment #38
aspilicious CreditAttribution: aspilicious commented#28: template_preprocess_class-680022-28.patch queued for re-testing.
Comment #39
aspilicious CreditAttribution: aspilicious commented*Retesting old patches*
Comment #40
catchold again..
Comment #41
sun#28: template_preprocess_class-680022-28.patch queued for re-testing.
Comment #42
sunAlthough badly needed, this is D8 material according to the rules (I had to learn today). It may be backported at a later point in time (though that's unlikely).
Comment #43
mlncn CreditAttribution: mlncn commentedThis is a performance improvement not affecting external APIs. Could have been committed months ago. If the testbot still likes it, it's RTBC for D7.
Comment #44
mlncn CreditAttribution: mlncn commented#28: template_preprocess_class-680022-28.patch queued for re-testing.
Comment #45
mlncn CreditAttribution: mlncn commentedAnd it still passes. The test is a little ... weird, but back to RTBC. This is a performance enhancement that does not endanger any code, in core or contrib (if the extra parameter isn't passed, it works just the same as before). So a tiny API extension that rfay can decide if it even gets a mention ;-)
Comment #46
webchickDo we need to revisit this in light of #902644: Machine names are too hard to implement. Date types and menu names are not validated?
Comment #47
webchick#28: template_preprocess_class-680022-28.patch queued for re-testing.
Comment #48
tom_o_t CreditAttribution: tom_o_t commented#28: template_preprocess_class-680022-28.patch queued for re-testing.
Comment #49
moshe weitzman CreditAttribution: moshe weitzman commented1 failure in DrupalHTMLIdentifierTestCase
Comment #50
webchickLast word on this patch was that Dries didn't like it, so once again leaving for The Spikey Haired One.
(Though I agree that it seems hackish, and it would also introduce an API change for people calling drupal_html_class() in order to take advantage of a 0.5% performance benefit outlined in #9. Not sure it's really worth it at this point, honestly.)
Comment #51
catchComment #52
xjmTagging issues not yet using summary template.
Comment #53
catch#28: template_preprocess_class-680022-28.patch queued for re-testing.
Comment #54.0
xcafebabe CreditAttribution: xcafebabe commentedCreating an Issue summary for a concise overview of this issue
Comment #55
jiv_e CreditAttribution: jiv_e as a volunteer commentedThis issue seems to be completely outdated because of these changes:
https://www.drupal.org/node/2121713
https://www.drupal.org/node/1305882
The issue title is also confusing because it doesn't touch template_preprocess() function anymore. Reopen if you disagree with my decision to close!