Needs work
Project:
Drupal core
Version:
main
Component:
theme system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
26 Jul 2026 at 12:38 UTC
Updated:
16 Sep 2026 at 14:28 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #3
catchConfirmed that this cache is more or less write only. There's an attempt to read it when twig templates are built, when it will be empty. The only case a non-empty cache can be read is via an inline template when autorefresh is on, which wouldn't do anything very useful anyway.
Umami tests don't catch this because they ensure the twig template cache (on disk) is warm before collecting performance data even for the 'cold cache' case, standard tests apparently aren't quite as careful.
There's probably more clean-up we can do here - like not including the cache backend at all, but could use another set of eyes.
Found this because I started looking at twig caching as a possible way to speed up functional tests. The first request to a page on a fresh install can spend up to about a second building twig templates. If we were able to share the twig cache between installs for the same template + code base + installed modules, it might be possible to cut that down.
Comment #4
smustgrave commentedSeems to have a test failure. Also possible that contrib module could be using it?
Comment #5
catchI can't see how a contrib module would ever be using it.
Can't reproduce the test failure locally, but could reproduce the previous one before that one. StandardPerformanceTest should probably be explicitly avoiding twig template cache misses similar to the Umami tests.
Comment #6
smustgrave commentedShould it be NW for that?
Comment #7
sjpagan commentedThe timestamp is read when auto_reload is on. Twig's own test defines the semantics: with getTimestamp() returning 0 the loader is never asked and write() is called, so the template is recompiled and rewritten on every request. See EnvironmentTest::testAutoReloadCacheMiss.
default.services.yml recommends enabling auto_reload rather than disabling the cache, so that path is a documented setup.
An alternative is to read the timestamp from the compiled file. MTimeProtectedFastFileStorage::save() already sets the containing directory mtime to the file mtime, so the value is there. The cache writes still go away and the interface keeps returning a real timestamp.
Measured on current main with only the class change: CacheSetCount in StandardPerformanceTest goes from 42 to 32, and those ten cids are all twig:. The other expectation changes in the MR do not reproduce here.
I have a patch with kernel test coverage, and can open a follow-up if you prefer the plain removal here.
Comment #8
sjpagan commentedThanks for picking this one up, and sorry for the slow reply.
In #4 you mentioned you could not reproduce the test failure locally. I had a go at it, and I think the good news is that the failure is not coming from your change.
Your own pipeline shows the same thing. Job https://git.drupalcode.org/project/drupal/-/jobs/11177159 on pipeline 902253 fails in
testStandardPerformance, on the$expected_queriesassertion insidetestAnonymous(), withFailed asserting that two arrays are identical. Four queries are in the expected array and never turn up in the recorded one:They all come from the State cache collector. They clearly run on your machine, and they do not run on the runners or here. I could not work out what makes the difference, so that part is over to you: you know your setup far better than I can guess at it.
I then ran three variants on main
ef161e27d8, to see which of the expectation changes reproduce outside your machine.Your branch as it is fails on
$expected_queries, the same way your CI does.Your code change, with the test file taken from main, passes
$expected_querieshappily. The only failure left isCacheSetCount: 42 expected, 32 recorded.Reading the timestamp from the mtime of the compiled file, with the test from main and
CacheSetCountset to 32, passes with 52 assertions.So
CacheSetCount42 to 32 looks like the only expectation change in the MR that reproduces outside your machine. main still expectsQueryCount => 10.One more thing, in case it saves you a look:
PHPUnit Unit (Component): [8.6-ubuntu]is green on current main. It failed on 902253, but that based97ade0537(26 July) predates0439c440a2(29 July), which is the PHP 8.6 fix forFileStorageTestfrom #3613160: PHP 8.6 failure in FileStorageTest. So that one is not yours either.Environment here: DDEV, PHP 8.5, MariaDB 10.11, selenium standalone-chrome:133.0.
On the approach, I pushed a variant to
3613278-timestamp-from-mtimeon this issue fork, with kernel test coverage, in case it is useful. It reads the timestamp from the mtime of the compiled file rather than returning 0, so the cache writes still go away andgetTimestamp()keeps returning a real value. Your branch is untouched.Related: #2888082: Deploying Twig template changes is too expensive: it requires all caches to be completely invalidated, as well as all reverse proxies covers the same ground on the deployment side.
What would you like me to do from here? I am happy to open a merge request for it, push to your branch, or leave the approach as it is and just drop the
$expected_querieschange so your MR can go green. Just let me know which one helps, or if something else would be more useful.Comment #9
smustgrave commented@sjpagan thanks for contributing but just a few notes.
Based on previous posts, not just here but on several others, it seems like AI has been heavily used so please take a moment and read https://www.drupal.org/docs/develop/issues/issue-procedures-and-etiquett....
If AI is used it needs to be disclosed and written in your own words. Phrase like "Thanks for picking this one up, and sorry for the slow reply." when the previous comment was from yourself make it seems like it was just copy and paste from Claude. Instead you should read the output and write it yourself.
There's no rule against using AI at all but again please read the issue etiquette page.
Thanks.
Comment #10
sjpagan commentedPushed a commit restoring the testAnonymous() expectations to main.
CacheSetCount 42 to 32 stays.
Pipeline 915363 is green. Functional Javascript 1/3 passes. The two failing
PHP 8.6 jobs allow failure; Unit (Component) is #3613160, which landed after this branch's base.
I also warmed node/1 before the cache clear to see if that changed anything, and no metric moved. The user page I left alone.
If you put the cache write back, StandardPerformanceTest fails on its own, so the removal already has coverage.
Comment #11
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #12
catchThe mtime approach makes sense to me - that way it's a bit closer to the original intent. Could you create an MR for that? Will probably need a rebase too.
Comment #14
catchRebased.
Comment #15
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #16
catchThis no longer shows up in performance tests - we had one standard test that wasn't priming the twig template cache (which all other performance tests do), and now that test no longer exists. However the previous test changes show it was doing what it's supposed to and I've also verified that locally.
Comment #17
berdir