Problem/Motivation
I have a very complicated form with 6 tabs and 4 webform_contact elements on the 5th tab. The form initially loads very slowly and as a user submits tabs, the next one will take 30 - 40 seconds to load and sometimes times out. When I remove 3 or all 4 webform_contact elements, the tabs load under 3 seconds.
I've narrowed down the problem to Drupal\webform\WebformSubmissionConditionsValidator::validateConditions, specifically line 596 where it calls the method recursively for nested elements. If I hack the method to skip nested elements, the form loads much faster, but I assume I'm losing validation of the nested elements.
Are the later webform_contact elements nested in the previous one so that the recursive method gets worse and worse? What's the best way to fix this?
Proposed resolution
Comment | File | Size | Author |
---|---|---|---|
#14 | example.yml | 458.64 KB | PapaGrande |
#11 | 3154034-11.patch | 4.46 KB | jrockowitz |
| |||
#8 | webform.webform.test_form_long_300.yml | 25.16 KB | jrockowitz |
#8 | 3154034-8.patch | 4.17 KB | jrockowitz |
#3 | example.yml | 216.58 KB | PapaGrande |
Comments
Comment #2
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedI am not able to reproduce the performance issue using the attached webform. Please provide an example of a webform which can be used to replicate this issue.
Comment #3
PapaGrandeTry this file. (I did not create this form.) Thanks.
Comment #4
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedFor the complexity of the example webform, the performance (via the Test tab) seemed okay.
Are you still seeing performance issues, if you use https://simplytest.me?
Comment #5
PapaGrandeI do not. Thanks for the suggestion.
That obviously means there is an even deeper root cause. I'll see what else I can find.
Comment #6
PapaGrandeJust to continue this story, I found the problem is with email handlers using one field in conditions a zillion times. I'm looking at ways I can move the conditions into an alter hook, but why would the validation code be firing all the email conditions on every tab submission?
Comment #7
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedWow! That is a bottleneck. Handlers are invoked for each element.
We might be able to cache the conditions results in \Drupal\webform\Plugin\WebformHandlerBase::checkConditions.
We could store a "hash" for the submission's current data and use this value condition caching.
This issue would probably have to be fixed in 6.x.
Comment #8
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedThe attached webform's performance was improve by 10% using the attached patch.
The attached webform's benchmarks.
The patch does not decrease performance but it increases performance as more handlers with more conditions are added.
Comment #9
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedComment #10
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedThe handler method that is triggering so many calls is \Drupal\webform\Plugin\WebformHandlerInterface::alterElement which I added for #3076750: Add Webform Options Limit Handler
Correction... \Drupal\webform\Plugin\WebformHandlerInterface::accessElement is what is triggering the ::validationConditions calls.
Comment #11
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedComment #12
PapaGrandeWow! Big improvement in form processing speed--tabs now refresh in a few seconds instead of 20 - 40. I've installed the patch on a test server and testing looks good so far.
I also reviewed the code and it looks good to me.
Thanks, @jrockowitz!
Comment #13
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commented@PapaGrande For reference, how many form elements and conditional handlers do you have on your test webform?
Comment #14
PapaGrandeLooks like over 500 conditions. I've attached a redacted export of the whole form.
Again, I did not create this form.
Comment #15
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedSo the trick for that form is to use the 'pattern' trigger.
Instead of
...use...
Comment #16
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commentedThe other solution is to use a Computed Twig element maybe with a custom Twig function to determine
is_customer_return_address_us
Comment #19
jrockowitz CreditAttribution: jrockowitz as a volunteer and at The Big Blue House commented