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

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

PapaGrande created an issue. See original summary.

jrockowitz’s picture

Status: Active » Postponed (maintainer needs more info)
FileSize
5.19 KB

I 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.

PapaGrande’s picture

Status: Postponed (maintainer needs more info) » Active
FileSize
216.58 KB

Try this file. (I did not create this form.) Thanks.

jrockowitz’s picture

For 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?

PapaGrande’s picture

Status: Active » Postponed (maintainer needs more info)

I do not. Thanks for the suggestion.

That obviously means there is an even deeper root cause. I'll see what else I can find.

PapaGrande’s picture

Just 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?

jrockowitz’s picture

Version: 8.x-5.12 » 8.x-5.x-dev
Status: Postponed (maintainer needs more info) » Needs work

Wow! 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.

jrockowitz’s picture

Status: Needs work » Needs review
FileSize
4.17 KB
25.16 KB

The attached webform's performance was improve by 10% using the attached patch.

The attached webform's benchmarks.

  • With three conditional handlers: 510ms
  • With three conditional handlers + patch: 460ms (50ms removed)
  • Without any handlers: 430ms
  • WebformSubmissionConditionsValidator::validateConditions calls without patch: 908
  • WebformSubmissionConditionsValidator::validateConditions calls with patch: 5

The patch does not decrease performance but it increases performance as more handlers with more conditions are added.

jrockowitz’s picture

Title: Form with webform_contact elements is extremely slow » Improve webform handler with conditional logic performance
jrockowitz’s picture

The 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.

jrockowitz’s picture

PapaGrande’s picture

Status: Needs review » Reviewed & tested by the community

Wow! 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!

jrockowitz’s picture

@PapaGrande For reference, how many form elements and conditional handlers do you have on your test webform?

PapaGrande’s picture

FileSize
458.64 KB

Looks like over 500 conditions. I've attached a redacted export of the whole form.

Again, I did not create this form.

jrockowitz’s picture

So the trick for that form is to use the 'pattern' trigger.

Instead of

- ':input[name="customer_return_address[country]"]':
    value: 'Antigua and Barbuda'
- or
- ':input[name="customer_return_address[country]"]':
    value: Angola

...use...

':input[name="customer_return_address[country]"]':
  value:
    pattern: '(Antigua and Barbuda|Angola)'
jrockowitz’s picture

The other solution is to use a Computed Twig element maybe with a custom Twig function to determine is_customer_return_address_us

  • jrockowitz authored 8af7319 on 8.x-5.x
    Issue #3154034 by jrockowitz, PapaGrande: Improve webform handler with...

  • jrockowitz authored 8af7319 on 6.x
    Issue #3154034 by jrockowitz, PapaGrande: Improve webform handler with...
jrockowitz’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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