Performance: Limit maximum ASCII byte scan range to codepoint limit it _wp_scan_utf8#12214
Performance: Limit maximum ASCII byte scan range to codepoint limit it _wp_scan_utf8#12214sirreal wants to merge 7 commits into
Conversation
When _wp_scan_utf8() is called with max_code_points but no max_bytes, the ASCII fast path previously called strspn() across the entire remaining ASCII run before checking the code point limit. This made _wp_utf8_codepoint_span( large ASCII text, 0, 5 ) scan the full string. Bound strspn() by the remaining code point budget. ASCII code points are one byte, so this preserves the returned span and found count while avoiding work past the budget. Local benchmark, 10 MB ASCII _wp_utf8_codepoint_span( ..., 0, 5 ): original 3.183709 ms, patched 0.001250 ms. Differential fuzz: 189847 span/found cases and 2750 valid mb_substr sanity cases, no mismatches.
|
Hi there! 👋 Thank you for your contribution to WordPress! 💖 It looks like this is your first pull request to No one monitors this repository for new pull requests. Pull requests must be attached to a Trac ticket to be considered for inclusion in WordPress Core. To attach a pull request to a Trac ticket, please include the ticket's full URL in your pull request description. Pull requests are never merged on GitHub. The WordPress codebase continues to be managed through the SVN repository that this GitHub repository mirrors. Please feel free to open pull requests to work on any contribution you are making. More information about how GitHub pull requests can be used to contribute to WordPress can be found in the Core Handbook. Please include automated tests. Including tests in your pull request is one way to help your patch be considered faster. To learn about WordPress' test suites, visit the Automated Testing page in the handbook. If you have not had a chance, please review the Contribute with Code page in the WordPress Core Handbook. The Developer Hub also documents the various coding standards that are followed:
Thank you, |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
|
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 Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
dmsnell
left a comment
There was a problem hiding this comment.
Noting the missing @ticket reference in the tests, but this is great work. Thanks for finding this and adding the limit.
The ASCII fast-path in `_wp_scan_utf8()` uses `strspn()` to skip past ASCII bytes. When a code point limit was provided without a byte limit, the scan would include the rest of the input even when there was a code point limit. Because ASCII characters are single-byte code points, the fast-path scan length can be bounded by the number of remaining code points. This improves performance when working with some large documents. Developed in #12214. Follow-up to [60768]. Props jonsurrell, dmsnell, zieladam. Fixes #65483. See #63863. git-svn-id: https://develop.svn.wordpress.org/trunk@62523 602fd350-edb4-49c9-b593-d223f7449a82
The ASCII fast-path in `_wp_scan_utf8()` uses `strspn()` to skip past ASCII bytes. When a code point limit was provided without a byte limit, the scan would include the rest of the input even when there was a code point limit. Because ASCII characters are single-byte code points, the fast-path scan length can be bounded by the number of remaining code points. This improves performance when working with some large documents. Developed in WordPress/wordpress-develop#12214. Follow-up to [60768]. Props jonsurrell, dmsnell, zieladam. Fixes #65483. See #63863. Built from https://develop.svn.wordpress.org/trunk@62523 git-svn-id: http://core.svn.wordpress.org/trunk@61804 1a063a9b-81f0-0310-95a4-ce76da25c4cd
The ASCII fast-path in `_wp_scan_utf8()` uses `strspn()` to skip past ASCII bytes. When a code point limit was provided without a byte limit, the scan would include the rest of the input even when there was a code point limit. Because ASCII characters are single-byte code points, the fast-path scan length can be bounded by the number of remaining code points. This improves performance when working with some large documents. Developed in WordPress#12214. Follow-up to [60768]. Props jonsurrell, dmsnell, zieladam. Fixes #65483. See #63863. git-svn-id: https://develop.svn.wordpress.org/trunk@62523 602fd350-edb4-49c9-b593-d223f7449a82
The ASCII fast-path in `_wp_scan_utf8()` uses `strspn()` to skip past ASCII bytes. When a code point limit was provided without a byte limit, the scan would include the rest of the input even when there was a code point limit. Because ASCII characters are single-byte code points, the fast-path scan length can be bounded by the number of remaining code points. This improves performance when working with some large documents. Developed in WordPress#12214. Follow-up to [60768]. Props jonsurrell, dmsnell, zieladam. Fixes #65483. See #63863. git-svn-id: https://develop.svn.wordpress.org/trunk@62523 602fd350-edb4-49c9-b593-d223f7449a82
The ASCII fast-path in `_wp_scan_utf8()` uses `strspn()` to skip past ASCII bytes. When a code point limit was provided without a byte limit, the scan would include the rest of the input even when there was a code point limit. Because ASCII characters are single-byte code points, the fast-path scan length can be bounded by the number of remaining code points. This improves performance when working with some large documents. Developed in WordPress#12214. Follow-up to [60768]. Props jonsurrell, dmsnell, zieladam. Fixes #65483. See #63863. git-svn-id: https://develop.svn.wordpress.org/trunk@62523 602fd350-edb4-49c9-b593-d223f7449a82
The ASCII fast-path in `_wp_scan_utf8()` uses `strspn()` to skip past ASCII bytes. When a code point limit was provided without a byte limit, the scan would include the rest of the input even when there was a code point limit. Because ASCII characters are single-byte code points, the fast-path scan length can be bounded by the number of remaining code points. This improves performance when working with some large documents. Developed in WordPress#12214. Follow-up to [60768]. Props jonsurrell, dmsnell, zieladam. Fixes #65483. See #63863. git-svn-id: https://develop.svn.wordpress.org/trunk@62523 602fd350-edb4-49c9-b593-d223f7449a82
When
_wp_scan_utf8()is invoked with a maximum number of codepoints, the ASCII fast-path will still scan the entire input string. In the case of long ASCII-only strings searching for a limited number of codepoints, this is wasteful and can be optimized by only searching up to remaining number of desired codepoints.ASCII are all 1-byte UTF-8 codepoints, so the maximum number of ASCII bytes can be limited by the maximum number of remaining codepoints.
See the demonstration below.
wordpress-develop/src/wp-includes/compat-utf8.php
Lines 56 to 69 in c710ca6
Demonstration
php \ -d memory_limit=8G \ -d opcache.enable_cli=1 \ -d opcache.enable=1 \ -d opcache.jit_buffer_size=128M \ -d opcache.jit=tracing \ test.phpOutput diff:
trunk@ c710ca6This seems to address a performance issue noted by @adamziel when reading codepoints in a 10MB XML file. The file is mostly ASCII (>98%), and at each codepoint boundary the rest of the document was scanned to find the ASCII code point count, often reading very large chunks of the document repeatedly. This is fixed by recognizing the max codepoint limit in the ASCII fast path.
performance benchmark results
Before (trunk@ c710ca6 )
Timed:
8.93s user 0.02s system 99% cpu 8.982 totalAfter (branch@ 5829e04 )
Timed:
0.19s user 0.01s system 96% cpu 0.214 totalFollow-up to: r60768
Trac ticket: https://core.trac.wordpress.org/ticket/65483
Use of AI Tools
AI assistance: Yes
Tool(s): Claude (Fable 5, Opus 4.8, etc.), Codex (GPT 5.5)
Used for: Fuzz testing and discovery, implementation, testing..
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.