prepend_to_selector: optimized with str_replace()#76556
Conversation
After talking it over with Claude Code, it turns out we can squeeze out a
bit more performance from `prepend_to_selector()` by getting `str_replace()`
to do most of the work.
For one site I was using to test with I found that there were over 4,000
calls to `prepend_to_selector()` just to bootstrap WordPress. Each one
runs very quickly, but with that volume it would be nice to make it a bit
faster.
For this test with over 4,000 calls, here are the before and after numbers:
Before:
- p75: 0.008032 ms
After:
- p75: 0.006198 ms
While those raw times are going to vary depending on the site and server,
the relative time is what I would focus on. That 0.001834 ms improvement
is 22.8%.
I had curl make 100 requests and had it log the time via:
```php
$start = hrtime( true );
$elements = static::get_block_element_selectors( $root_selector );
error_log( ( hrtime( true ) - $start ) / 1e6 );
```
Then sorted the logged results with:
```bash
tail -n 100 /tmp/php-errors | awk '{print $NF}' | sort -n | awk 'NR==50{p50=$1} NR==75{p75=$1} END{print "p50:",p50,"\np75:",p75}'
```
I also did a comparison run to make sure that all 4,000+ results were the
same before and after this change. To `protect prepend_to_selector()` in
the future I also had Claude Code generate tests.
There is also a completely stand alone benchmark script to compare both of
these at https://gist.github.com/josephscott/254521a43dee3300448ef288dd2ea1f2
While not my original focus for this change, it does have a small reduction
in the amount of memory used.
Before:
- p75: 17,874,280 bytes
After:
- p75: 17,870,680 bytes
The 3,600 bytes is veryminor, but nice to see.
Another thing that I considered was getting rid of the separate method
call entirely, since it is only called in one place - inside the
`get_block_element_selectors()` loop. Now that it is only 4 lines long there
is not much point to calling out to separate method. Again, trying to
squeeze everything we can out of something called 4,000+ times. But this
method has been around for a few years, so I didn't worry about that.
See WordPress#50266 for the original PR
that created `prepend_to_selector()`.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @josephscott! In case you missed it, we'd love to have you join us in our Slack community. If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information. |
youknowriad
left a comment
There was a problem hiding this comment.
The change makes sense to me. Thanks.
After talking it over with Claude Code, it turns out we can squeeze out a bit more performance from
prepend_to_selector()by gettingstr_replace()to do most of the work.For one site I was using to test with I found that there were over 4,000 calls to
prepend_to_selector()just to bootstrap WordPress. Each one runs very quickly, but with that volume it would be nice to make it a bit faster.For this test with over 4,000 calls, here are the before and after numbers:
Before:
After:
While those raw times are going to vary depending on the site and server, the relative time is what I would focus on. That 0.001834 ms improvement is 22.8%.
I had curl make 100 requests and had it log the time via:
Then sorted the logged results with:
I also did a comparison run to make sure that all 4,000+ results were the same before and after this change. To
protect prepend_to_selector()in the future I also had Claude Code generate tests.There is also a completely stand alone benchmark script to compare both of these at https://gist.github.com/josephscott/254521a43dee3300448ef288dd2ea1f2
While not my original focus for this change, it does have a small reduction in the amount of memory used.
Before:
After:
The 3,600 bytes is very minor, but nice to see.
Another thing that I considered was getting rid of the separate method call entirely, since it is only called in one place - inside the
get_block_element_selectors()loop. Now that it is only 4 lines long there is not much point to calling out to separate method. Again, trying to squeeze everything we can out of something called 4,000+ times. But this method has been around for a few years, so I didn't worry about that.See #50266 for the original PR that created
prepend_to_selector().What?
Closes
Why?
How?
Testing Instructions
Testing Instructions for Keyboard
Screenshots or screencast
Use of AI Tools
Claude Code was used to come up with ideas for performance improvements and it wrote the new tests.