[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
Sat Oct 25 09:37:12 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 | Resolution:
Keywords: has-patch | Focuses: performance
-------------------------------+------------------------------
Comment (by michelleeby):
== Revised Patch 2: Directive Caching
Previous attempts to optimize
`WP_Interactivity_API::data_wp_each_processor` included 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. However, this solution did not consider how
the WP_HTML_Tag_Processor is designed.
As far as I can tell, the WP_HTML_Tag_Processor architecture works by:
- Sequentially scanning HTML to find tags (via strpos, strcspn, etc.)
- Tracking positions as byte offsets
- Modifying HTML through WP_HTML_Text_Replacement objects
It seems there's no way to "jump to position X" without scanning from the
beginning. Byte offsets shift as HTML is modified, and bookmarks are
designed for single-pass processing, not cross-rendering reuse.
Looking more carefully at the bottleneck, the real issue is that for each
item in the array, the code:
1. Create a new WP_Interactivity_API_Directives_Processor
2. Call $p->next_tag() repeatedly (which does expensive string scanning)
3. Call get_attribute_names_with_prefix('data-wp-') for each tag
4. Parse directive names and extract values
5. Evaluate directives
The optimization opportunity is steps 2-4, not step 5. The code can't
avoid re-scanning the HTML (that's how the Tag Processor works), but it
can cache what it learned about where directives are and what they are.
== Steps to Reproduce the Bottleneck
1. Download, install and activate "interactive-stress-test.zip" which is
attached to the ticket.
2. The plugin creates 3 posts, "Stress Test – Light", "Stress Test –
Medium", "Stress Test – Heavy". View "Stress Test - Light" on the
frontend.
3. Navigate to the Medium and Heavy posts on the frontend. In browser
console, observe the time that the "Interactivity API processed in".
== Steps to Run Experiments
1. Navigate to the "Stress Test – Light" post on the frontend.
2. Click the "Run Batch Test (10x)" button
3. Follow the pop up prompts. They will guide you through the medium and
heavy tests and ask to save the results as a CSV. The results can also be
seen in the browser console.
== Results
**Core WordPress**
''Summary Statistics''
||= Variation =||= Runs =||= Avg Time (ms) =||= Min Time (ms) =||= Max
Time (ms) =||
||light || 10 || 231.68 || 196.20 ||
275.80 ||
||medium || 10 || 562.00 || 511.10 ||
698.40 ||
||heavy || 10 || 1081.62 || 1051.30 ||
1148.80 ||
''Individual Run Data''
||= Variation =||= Run 1 =||= Run 2 =||= Run 3 =||= Run 4 =||= Run 5
=||= Run 6 =||= Run 7 =||= Run 8 =||= Run 9 =||= Run 10 =||
||light || 215.00 || 196.20 || 226.20 || 263.10 || 218.70
|| 272.20 || 207.00 || 211.60 || 275.80 || 231.00 ||
||medium || 514.70 || 546.30 || 646.90 || 514.00 || 554.70
|| 591.10 || 698.40 || 524.10 || 511.10 || 518.70 ||
||heavy || 1051.30 || 1053.60 || 1062.00 || 1053.60 || 1072.20
|| 1069.30 || 1148.80 || 1101.50 || 1098.00 || 1105.90 ||
**Patched WordPress**
''Summary Statistics''
||= Variation =||= Runs =||= Avg Time (ms) =||= Min Time (ms) =||= Max
Time (ms) =||
||light || 10 || 201.12 || 152.80 ||
362.50 ||
||medium || 10 || 392.73 || 366.00 ||
437.40 ||
||heavy || 10 || 796.62 || 756.80 ||
838.30 ||
''Individual Run Data''
||= Variation =||= Run 1 =||= Run 2 =||= Run 3 =||= Run 4 =||= Run 5 =||=
Run 6 =||= Run 7 =||= Run 8 =||= Run 9 =||= Run 10 =||
||light || 165.20 || 168.10 || 362.50 || 193.80 || 158.10 ||
152.80 || 157.20 || 175.10 || 254.10 || 224.30 ||
||medium || 384.50 || 369.60 || 411.60 || 366.00 || 405.30 ||
400.30 || 437.40 || 372.30 || 398.70 || 381.60 ||
||heavy || 756.80 || 791.20 || 799.30 || 776.90 || 787.20 ||
772.20 || 818.70 || 838.30 || 803.60 || 822.00 ||
--
Ticket URL: <https://core.trac.wordpress.org/ticket/64093#comment:3>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list