Problem/Motivation
This might be by design but we're loading the status message twig template when we have no status messages. Not sure this makes a great deal of sense.
Proposed resolution
Don't return a render array if there are no messages.
Here's an xhprof of the frontpage after a minimal install and comparing with and without the patch.
We need to ensure that Classy's messages.css is loaded so javascript calls to add message like when re-ordering menus on admin/structure/menu/manage/tools have the same look and feel.
Remaining tasks
User interface changes
None
API changes
Well it depends if you expect the status messages to be rendered even if there are none.
Data model changes
None
Comment | File | Size | Author |
---|---|---|---|
#54 | 2853509-2-54.patch | 9.55 KB | alexpott |
#54 | 52-54-interdiff.txt | 1.45 KB | alexpott |
#52 | 2853509-2-52.patch | 9.77 KB | alexpott |
#52 | 48-52-interdiff.txt | 1.61 KB | alexpott |
#48 | 2853509-2-48.patch | 9.83 KB | alexpott |
Comments
Comment #2
alexpottComment #3
alexpottIt get's bigger with standard - because more theme layers involved.
Comment #4
Wim LeersHAHHAHAHAHAHAH. Genius.
Comment #5
Wim Leers#3 means we save about 1000 function calls on every HTML response. Including BigPipe responses. Including Dynamic Page Cache hits. But excluding Page Cache hits (since those don't do any rendering ever).
I wonder if it means we save 25 out of 80 milliseconds too? Also, WTF, do we really spend 25 ms on rendering an empty status messages template? How is this possible?
It'd be interesting to see how this impacts performance ofan authenticated response of the front page with 5 articles, and of a full node page.
Comment #6
catchYep this is a great find, massive +1.
I was concerned for a moment about #77245: Provide a common API for displaying JavaScript messages but this doesn't affect that issue either way.
Comment #9
xjmGreat find.
We also agreed to backport this in the 8.3.x beta phase. It's a totally BC-safe improvement and any disruption from not having the empty render array is quite outweighed by the performance improvement, especially before 8.3.0. Thanks!
Comment #10
Wim LeersYAY!
Comment #12
droplet CreditAttribution: droplet commentedIt breaks a lot of messages. (BC-BROKEN)
#2875947: CSS files not loaded on AJAX calls
A simple way to reproduce:
1. admin/structure/menu/manage/account
2. change menu link ordering
The patch only affected a file and can be reverted easily. So I reopen it.
Comment #13
alexpottI've posted a more forward looking fix on #2875947: CSS files not loaded on AJAX calls. I think we should consider going forward rather than backward here.
Comment #14
nod_FYI : #77245: Provide a common API for displaying JavaScript messages will need all the messages stuff on every pages, even when there are no messages (on the PHP end).
Comment #17
xjmI've reverted this issue. At a minimum, it should to be updated to include the fix from #2875947: CSS files not loaded on AJAX calls and tests for said fix. If someone can incorporate the info from the duplicate, that would be helpful.
@nod_, is there a way that #77245: Provide a common API for displaying JavaScript messages can be supported alongside the fix here? It really is quite a nice performance improvement.
Comment #18
xjmAs an aside:
was really, really quite wrong. ;)
Comment #19
xjmProposed new scope. :P
Comment #20
nod_Not sure we can.
We do need the wrapping HTML to be generated from twig by PHP, so we can inject individual messages in the message area in the frontend. I guess we could only render it if the
core/drupal.message
is used on the page, by I don't know where or how to check that.Comment #21
dmsmidtA great catch!
But I'm with @nod_, it's not trivial to get the .css dependency hell fixed and we always need to render the messages area for the JS Messages API to work. The easiest fix for that is to just add messages.css to the themes base libraries (see discussion here: #77245-227: Provide a common API for displaying JavaScript messages).
Is there another way to improve speed? Move
{{ attach_library('classy/messages') }}
down, so to only include the CSS when there are actual messages maybe? Statically cache some functions while there are no actual messages?It think we should re-title this issue to something like "improve messages performance". And maybe reopen the previously closed duplicate. Otherwise this will become a heavy blocker for JS Messages API, which in turn is needed for Inline Form Errors and Outside in / Settings tray.
Comment #22
alexpottHere's the merged patches.
@catch and I discussed before how this might affect #77245: Provide a common API for displaying JavaScript messages. It can proceed by doing something like:
Also note that even now with this patch reverted there is nothing for Javascript to add messages to because the twig templates print nothing is there are no messages.
Comment #23
alexpottThis is a critical performance improvement as per https://www.drupal.org/core/issue-priority - it's 10% improvement on user logged in pages.
Comment #24
dmsmidtQuick review, will do some extra later.
Needs better description and method name.
Same as above.
Woohoo this helps JS Message API.
Comment #25
dmsmidtManually tested the patch,
messages.js
present, even without messages on screen, in Bartik and Classy.Like all other empty post update functions, add: "// Empty post-update hook."
The rest of the logic was already RTBC-ed in #2875947: CSS files not loaded on AJAX calls.
So after these nits are fixed we are good to go it seems.
Comment #26
alexpottFixed #25. Re #24 the reason why these test names are testClassy and testBartik is because if we were to add further functional tests for these themes I would hope we can just add more to these methods. I really don't see a win in having a testClassyMessagesCss and and a testClassSomeOtherThemeThing test.
Comment #27
dmsmidtI mentioned it (#24) because of our own documentation:
https://api.drupal.org/api/drupal/core!core.api.php/group/testing/8.2.x
But, that (separating subsets) also has a negative speed impact, so I'm ok with keeping it like this for now.
Comment #28
nod_From #22
Yes, the other patch changes that. And anyway the other patch not ready yet: the data attribute is still in the wrong place.
And I'd be really curious why an empty template add a 10% overhead on logged pages, cache busting going on?
Comment #29
nod_I guess we can always duplicate the template in js. we'll need to add tests to check all this in the other issue.
Comment #30
catchI haven't profiled this yet, but there's a few things going on with the messages block specifically:
1. This is rendered in a special cased placeholder, so that it always runs as late as possible (to pick up as much from $_SESSION as it can). It's not cached, although it could probably be cached by a 'session contains messages' cache context then max-age=0 when it contains nothing (which I don't think we should implement here).
2. With dynamic page cache, at least theoretically this could be the only (or one of few) template getting rendered as opposed to pulled from cache, so there may be some overhead of loading templates, other caches etc. that in 7.x would have happened whether it gets rendered or not.
Profiling would be useful, I've opened another issue to discuss that and maybe refactoring how this works more #2877291: The late rendered messages block can take 10% of page generation time.
Happy with the patch I think, but want to give it another look over after food/caffeine before commit.
Comment #31
alexpottI profiled this again. On minimal install, front-page, logged in and render cache on, PHP5.6.
So the gains are the same.
Comment #32
alexpottI've added a comment about compatibility with #77245-238: Provide a common API for displaying JavaScript messages on that issue.
Comment #33
alexpottBack to task - this was a bug because it caused a regression but it got reverted.
Comment #34
xjmSo, the issue is still filed against 8.3.x, but now also adds a template and library change for Classy. So less sure about backporting it, especially after 8.3.0. I mean it's not going to get more broken than it was in 8.3.2 and below, I guess, but still. :P I'll get a second opinion.
This is way more than the test does... I mean, I guess other than asserting the theme by itself doesn't cause a 500 or something. :P
Apparently this was also mentioned in another review and @alexpott responded to it in #26, but I still think it's kinda a bad/misleading method name barring some specific test coverage we want to add to the method in a followup.
Comment #35
lauriiiThanks for adding the test coverage for this!
From the Classy point of view backporting this change is fine. This change doesn't cause virtually any changes to the actual rendered page. Previously the library was only attached when messages were rendered. But because messages were rendered on every page, the library was already loaded on every page.
A minor difference I could find is that there is a change in the order of the Classy CSS files. This could potentially cause a problem if someone was overriding some of the other classy component styles by replacing messages library. Personally, I wouldn't worry about this since this is an anti-pattern but would require still quite a lot of knowledge how Drupal's assets work. There are a gazillion better alternatives to achieve same.
At last, there is no harm caused by the fact that overridden templates will be still calling attach_library there since a library can be only attached once for the page.
Comment #36
alexpottGiven that we're doing an update hook I think we should put this in 8.4.x only. I like the consensus we've come to in avoid update hooks in patch releases. It makes them easier to adopt.
Also as @lauriii points out we have a change in the order of css. And, whilst this really should not matter, making this change in a patch release is also unnecessary change.
Comment #37
alexpottRe the testClassy and testBartik... yes the test don't cover all the functionality of those themes but in an ideal world those themes would already have tests and this would be a simple one liner addition to them. I think the correct unit of test is the entire theme - but this patch should only add tests for what it is changing. As noted in #26:
Comment #38
alexpottI decided to check with a bit more of real test.
Here's a xhprof comparison on php5.6:
So because of the layers of themes bartik -> classy the savings are actually bigger in terms of numbers of function calls (not as a percentage of the overall though).
Comment #39
xjmThanks @lauriii!
@alexpott:
I understand your perspective and your frustration with people adding unneeded separate methods, and that you want them to reduce test install time by adding to existing tests, but this is not the effective way to accomplish that. Without a specific idea of what test coverage we might add, and @todos and followups for their coverage, it's just overpromising and can confuse people into thinking classy already has test coverage so they don't need to write it.
If you think Classy and themes in general need test coverage of some sort, file an issue and put it in your test in a @todo. I have no concept of what test coverage themes need but lack, so if you feel they're lacking, then outline a few things you think should be tested in at least a stub followup that frontend maintainers can expand if they choose.
Or just rename the method like a couple people have suggested. :P I don't think having the method named
testClassy()
is going to increase the likelihood of tests being added in that method and not another by someone else.The update hook point is reasonable; while the docs say "changes requiring an upgrade path" and this is just a cache clear, I can see wanting to avoid that update hook, especially since we had so many problems with them with the minor update. However, yesterday I was told this issue was critical because we're saving the earth. :P If this issue is really critical and that's the only disruption per @lauriii, I can see a case for backporting it, to save the earth five months earlier.
I did confirm that there are no other updates yet since the minor:
Comment #40
xjmFor reference, these 8.2.x issues may have had an update hook after 8.2.0:
Some of those are for criticals, some are for experimental modules, but the last couple (at the top) are normal issues.
Edit: #2828559: UpdatePathTestBase tests randomly failing is a false positive; apparently I can't figure out how match grep with -S properly. But I checked the others and they are.
Comment #41
alexpottRerolled and changed the test method names for what it is worth. I disagree but it is not worth holding the patch on it since others disagree.
Comment #42
alexpottI think the most compelling reason to not apply to 8.3.x is that we're changing the order of css in classy which is a base theme we've told everyone to use for protect yourself from core theme changes. And whilst this change should have 0 impact on a well maintained theme there is a very small risk which could cause someone to delay updating and then if the next patch release is a security issue they have a problem. Still the worst that is going to happen is that some messages won't look right so we could argue that it is okay. But it does seem good to limit the points at which people have to deal with change.
Comment #43
dawehnerI agree that testClassy/testBartik is not a good name. Its not better than "test". For me tests fall under a different category of how to write them than normal code for example you can even throw them away if it actually adds more maintenance burden that profit.
From my point of view adding a new test class for bartik/classy is a good step in the right direction. It provides more context.
Regarding the method names, as we have seen in #17 we are dealing with a regression, so something like
testRegressionMissingMessagesCss
on both classes would cut it for me at least. One property of regression tests is that they can be way more specific than other tests, as they target a specific problem, rather than provide a descriptive test case, which is one of the best practises of functional tests.Comment #44
xjmI did offer a strategy to accomplish what you want in #39.
#42 seems a reasonable case not to backport; I can see that causing a disruption for some small set of sites and the fewer disruptions we put between them and sec releases the better. But let's be consistent then and not backport upgrade paths for normals.
Comment #45
alexpott@dawehner here's a patch with your suggestions. I still disagree but thanks for suggesting a method name.
\edit
@xjm yep thanks for the review and I opted for the strategy for renaming the methods.
Comment #46
xjm(Comment below was a crosspost).
There are some typos in these:
- "Its" and not "it's"
- capitialize "Classy"
- The Bartik one is confusing and sorta ungrammatical; maybe "Tests that the Bartik theme always adds its message CSS and Classy's.
Edit: also "Tests that" in the case of these sentences.
Comment #47
alexpott@xjm thanks for the review. Fixed comments.
Comment #48
alexpottBah missed a that.
Comment #49
dawehnerThis diff just proves that adding single line documentation to test methods is a bit weird in the first place.
Comment #50
xjmC&P I think and should say "Bartik theme" and mention that it's testing Bartik also?
Comment #51
xjmAlso yes to #49 but that is a battle for another day. ;) As @msonnabaum always said, we often use docs to do what the code itself should. :)
Comment #52
alexpottNow that the methods are so specific we can move the @see and also point to the relevant file that adds Bartik's messages.css to every page.
Comment #53
xjmMissed a bit here I think. Could be fixed on commit but letting tests run also.
Comment #54
alexpott@xjm ah indeed in fact this was a c&p from \Drupal\Tests\system\Kernel\Render\ClassyTest::setUp() and the manipulation of the theme registry is not necessary in BrowserTestBase. So we can do less and have less unnecessary comments.
Comment #58
catchWe discussed this on the committer triage call last week, and decide it should stay critical (although also that we need to further update the definitions for 'performance critical' on https://www.drupal.org/core/issue-priority now that 8.x is released).
Added reviewer credit from #2875947: CSS files not loaded on AJAX calls and this issue.
One the one hand the change here is minimal and is already in 8.3.x in a broken form. On the other, don't really like having to add an update to a patch release. So I'm going to mark this as fixed, but if someone feels it should be backported to 8.3.x, please re-open.
Comment #59
Graber CreditAttribution: Graber as a volunteer commentedLOOL That's some other graber you credited :) I'm here not for the credits though, hope we'll meet again, cheers!
Comment #60
catchDoh. Fixed on the issue credit anyway.
Comment #61
xjmCase-sensitive usernames FTW. ;)
Comment #63
droplet CreditAttribution: droplet commentedDing!
COMMAND:
git log -n 1 6b489d5 | grep droplet
CreditGo: She forgot you
...
(UP arrow, Press enter)
..
.
Dear @drupal,
Do you know? I re-compiled uncountable builds to identify the problem between 400 commits. No matter you acknowledge me or not. I will continue to help your back to health.
Comment #65
quietone CreditAttribution: quietone at PreviousNext commentedAdding credit for duplicate, #2601232: Follow-up for #2566597: only attach the 'classy/messages' asset library if there are messages
Comment #68
quietone CreditAttribution: quietone at PreviousNext commented