Problem/Motivation

This is a critical performance regression found by #2552873: node/1 flamegraphs, see the issue summary and last few comments.

Proposed resolution

Add back the #create_placeholder = > TRUE in CommentDefaultFormatter for the #lazy_builder element so that the max-age=0 of the comment form (i.e. of the comment form's CSRF token) doesn't bubble up to nodes.

The combination of #2463567: Push CSRF tokens for forms to placeholders + #lazy_builder and #2578855: Form tokens are now rendered lazily, allow forms to opt in to be cacheable will address this in a much nicer way and can revert this fix again.

Remaining tasks

We need some sort of test coverage to make sure that comment forms don't make nodes uncacheable I think.

User interface changes

None.

API changes

None.

Data model changes

None.

Comments

Berdir created an issue. See original summary.

dawehner’s picture

Well, could we render a single render array of a node and check the max-age / cache contexts of it?

sasanikolic’s picture

Assigned: Unassigned » sasanikolic
sasanikolic’s picture

Status: Active » Needs review
StatusFileSize
new652 bytes

Reverted back the create_placeholder. Need some input how to test that.

alexpott’s picture

Well first up it would be great to see evidence of manual performance testing that this fixing the issue.

wim leers’s picture

Issue tags: +Needs tests, +D8 cacheability

Thanks, @sasanikolic!

To test this, you can do something like this, in a kernel test:

// First, ensure some node bundle has a comment field.
$build = NodeViewBuilder::view($node_of_bundle_that_has_a_comment_field);
$this->renderer->renderRoot($build);
$this->assertIdentical(Cache::PERMANENT, $build['#cache']['max-age']);
$this->assertFalse(isset($build['#printed']), 'Cache hit');
wim leers’s picture

Issue summary: View changes
sasanikolic’s picture

I have extended the test, but it fails. Also, together with @berdir, we tried with render and renderRoot. With render, something is changing the max-age from -1 to 0 (appartently in accessCheck), with renderRoot it was false, which makes no sense.

Status: Needs review » Needs work

The last submitted patch, 9: prevent_comment_forms-2579021-9.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new2.89 KB
new2.44 KB

Ok, had to get creative a bit with the test, see code and inline comments. Using a nested element for the entity so I can simulate how a real (page) render array that has entities somewhere down in the tree behaves, so I can test both their cache max-age and that of the whole render array.

Also a fix for entity_test_entity_access(), that currently forces a max-age 0 on *every* entity access check, in this case it was the filter access check for the text field.

berdir’s picture

Forgot the test-only patch.

fabianx’s picture

renderRoot won't work, because it renders all placeholders including the comment form (per definition).

So you need to use:

$context = new RenderContext();
$renderer->executeInRenderContext(function($context) use ($renderer, &$build) {
  $renderer->render($build);
});

// etc.

Edit: Disregard - I see what you did there now :).

The above works fine, because what berdir did above there is to use a child element and then check the cacheability of the child element, which is enough.

The last submitted patch, 11: prevent_comment_forms-2579021-11.patch, failed testing.

fabianx’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -622,6 +622,10 @@ function entity_test_entity_prepare_view($entity_type, array $entities, array $d
+  // Only apply to entity_test entity types.
+  if ($entity->getEntityType()->getProvider() != 'entit_test') {
+    return AccessResult::neutral();
+  }

I believe this typo is the reason for the test fails.

The last submitted patch, 12: prevent_comment_forms-2579021-11-test-only.patch, failed testing.

wim leers’s picture

Fixing the typo.

wim leers’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new3.13 KB
new897 bytes

Patch looks great, just one nitpick to fix:

+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -622,6 +622,10 @@ function entity_test_entity_prepare_view($entity_type, array $entities, array $d
+  // Only apply to entity_test entity types.

s/entity types/entities/

Fixed.


Since my only work on the actual code here is a typo fix in #17, the docs typo fix here, and pointing people in the right direction on how to write a regression test, I think it's fine for me to RTBC this.

fabianx’s picture

RTBC + 1 - if tests pass

(please add me to commit credit if deemed okay)

wim leers’s picture

Issue summary: View changes

Clarified IS.

The last submitted patch, 17: prevent_comment_forms-2579021-17-test-only.patch, failed testing.

The last submitted patch, 17: prevent_comment_forms-2579021-17-test-only.patch, failed testing.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

We've got tests and fix - this is good to go. Committed 18d4de1 and pushed to 8.0.x. Thanks!

  • alexpott committed 18d4de1 on 8.0.x
    Issue #2579021 by Wim Leers, Berdir, sasanikolic, Fabianx: Prevent...

The last submitted patch, 9: prevent_comment_forms-2579021-9.patch, failed testing.

The last submitted patch, 11: prevent_comment_forms-2579021-11.patch, failed testing.

The last submitted patch, 12: prevent_comment_forms-2579021-11-test-only.patch, failed testing.

Status: Fixed » Closed (fixed)

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