[wp-trac] [WordPress Trac] #64093: Interactivity API: Performance bottleneck in `data_wp_each_processor` due to repeated template parsing

WordPress Trac noreply at wordpress.org
Tue Oct 14 09:33:43 UTC 2025


#64093: Interactivity API: Performance bottleneck in `data_wp_each_processor` due
to repeated template parsing
-------------------------------+-----------------------------
 Reporter:  michelleeby        |      Owner:  (none)
     Type:  enhancement        |     Status:  new
 Priority:  normal             |  Milestone:  Awaiting Review
Component:  Interactivity API  |    Version:  trunk
 Severity:  normal             |   Keywords:  has-patch
  Focuses:  performance        |
-------------------------------+-----------------------------
 == Summary

 A performance bottleneck exists in
 WP_Interactivity_API::data_wp_each_processor when it processes a data-wp-
 each directive with a large number of items. The current implementation
 re-scans the entire inner template HTML for every item in the loop,
 leading to exponential performance degradation as the number of items
 increases. This ticket proposes an optimized approach using pre-
 computation and caching to parse the template only once.

 == Problem Description

 During a high-traffic load test (500 virtual users) on a production
 endpoint for a major enterprise customer, we identified
 WP_Interactivity_API::data_wp_each_processor as the primary bottleneck.
 New Relic traces consistently showed this single function consuming over
 60% of the total request time (e.g., 40.89 seconds).

 The root cause of the inefficiency lies in its nested-loop-like behavior:

 - The function iterates through the array provided to the data-wp-each
 directive (let's call the number of items N).
 - Inside every iteration, it instantiates a new WP_HTML_Tag_Processor for
 the template and recursively calls $this->process_directives().
 - This recursive call forces the WP_HTML_Tag_Processor to scan the
 template from the beginning to find all directive tags (let's say there
 are M tags to process).

 This results in a time complexity of approximately O(N⋅M), where the
 expensive work of finding all directive tags within the template is
 repeated for every single item in the source array. For a list with
 hundreds of items and a template with several directives, this becomes
 computationally prohibitive.

 == Steps to Reproduce

 - Register an interactive block or view script.
 - Use the data-wp-each directive on a <template> tag.
 - Provide a large array to the directive via wp_interactivity_state(), for
 example, an array with 500+ items.
 - Inside the <template>, include several elements with other interactivity
 directives (e.g., data-wp-text, data-wp-bind:aria-label, data-wp-class).
 - Load the page and profile the server response time. You will observe an
 extremely high execution time for the data_wp_each_processor method.

 == Proposed Solution: Pre-computation and Caching

 The proposed solution refactors the processor to adopt a "pre-compute and
 cache" strategy. Instead of re-parsing the template on every iteration, we
 can build a "blueprint" of the template once, cache it, and then use it to
 efficiently process each item.

 The new logic is as follows:

 - **Blueprint Creation:** On the first encounter of a given template HTML,
 create a "blueprint.": Instantiate a WP_HTML_Tag_Processor for the
 template. Iterate through it once to find all tags containing data-wp-
 directives. For each interactive tag found, create a bookmark using
 $p->set_bookmark().

 - **Caching:** Store the array of bookmark names in a static class
 property (private static $template_blueprints), using an md5 hash of the
 template's HTML as the cache key.

 - **Optimized Loop:** For each item in the data array: Instantiate a new
 WP_HTML_Tag_Processor with the template HTML. Instead of scanning, iterate
 through the cached bookmark names. Use $p->seek( $bookmark_name ) to jump
 directly to the next interactive tag. Finally, call the original
 process_directives() on that specific tag.

 I think this change would fundamentally alter the time complexity to
 something closer to O(M+N⋅D), where M is the one-time cost of scanning the
 template to build the blueprint, and D is the number of interactive
 directives that need processing for each of the N items. This would be a
 massive performance improvement.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/64093>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list