HTMLScanner.scanName: ASCII fast-path for the per-char inner loop#171
Merged
Merged
Conversation
scanName runs once per element and once per attribute name and is one of the hottest frames in a parser-only profile (~5% self-time on a typical HTML page). The inner loop calls Character.isLetterOrDigit, Character.isLowerCase / isUpperCase, and Character.toLowerCase / toUpperCase per character, none of which are JIT-inlineable -- the existing comment in the same method already hand-tunes the whitespace check around this exact concern. HTML element/attribute names are virtually always lowercase ASCII, so: - For the strict-mode "is name char?" check: explicit ASCII branch (a-z / A-Z / 0-9 / - . : _) before falling through to Character.isLetterOrDigit only for c >= 0x80. - For NAMES_LOWERCASE: if c is uppercase ASCII, lowercase via c | 0x20 (no JDK call); only Character.toLowerCase for non-ASCII chars that aren't already lowercase. Symmetric for NAMES_UPPERCASE. Behavior is preserved for all inputs, including non-ASCII names that fall through to the JDK methods. JMH HtmlUnitBenchmark.JMH on a ~30 KB HTML page (5 forks x 3 warmup x 5 measurement = 25 samples, paired sequentially in one JMH session on top of a corresponding htmlunit-side change that defers the HtmlPage id/name index build): before: 593.611 +- 13.110 us/op after: 564.642 +- 11.833 us/op delta: -29.0 us, -4.9% Tests: full htmlunit-neko suite (mvn -Dgpg.skip test) -- 8407 tests, 0 failures, 0 errors. CanonicalSAXTest / CanonicalTest / CanonicalDomFragmentTest (1156 cases each, the scanner-correctness suites) all pass.
|
Member
|
Great, many thanks.... |
Member
|
5.0.0-SNAPSHOT updated |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



scanNameruns once per element and once per attribute name and is one of the hottest frames in a parser-only profile (~5% self-time on a typical HTML page). The inner loop callsCharacter.isLetterOrDigit,Character.isLowerCase/isUpperCase, andCharacter.toLowerCase/toUpperCaseper character, none of which are JIT-inlineable -- the existing comment in the same method already hand-tunes the whitespace check around this exact concern.HTML element/attribute names are virtually always lowercase ASCII, so:
Character.isLetterOrDigitonly forc >= 0x80.NAMES_LOWERCASE: ifcis uppercase ASCII, lowercase viac | 0x20(no JDK call); onlyCharacter.toLowerCasefor non-ASCII chars that aren't already lowercase. Symmetric forNAMES_UPPERCASE.Behavior is preserved for all inputs, including non-ASCII names that fall through to the JDK methods.
JMH HtmlUnitBenchmark.JMH on a ~30 KB HTML page (5 forks x 3 warmup x 5 measurement = 25 samples, paired sequentially in one JMH session on top of a corresponding htmlunit-side change that defers the HtmlPage id/name index build):
before: 593.611 +- 13.110 us/op
after: 564.642 +- 11.833 us/op
delta: -29.0 us, -4.9%
Tests: full htmlunit-neko suite (mvn -Dgpg.skip test) -- 8407 tests, 0 failures, 0 errors. CanonicalSAXTest / CanonicalTest / CanonicalDomFragmentTest (1156 cases each, the scanner-correctness suites) all pass.