Skip to content

[JSC] Skip identical printable ASCII prefix in Intl.Collator ASCII fast path - #77424

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
Constellation:collator-compare
Oct 19, 2026
Merged

webkit-commit-queue merged 1 commit into
WebKit:mainfrom
Constellation:collator-compare

Conversation

@Constellation

@Constellation Constellation commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

7b2dc73

[JSC] Skip identical printable ASCII prefix in Intl.Collator ASCII fast path
https://bugs.webkit.org/show_bug.cgi?id=327979
rdar://190333228

Reviewed by Sosuke Suzuki.

compareASCIIWithUCADUCET first scanned equal-length strings with equal() and then
walked the same characters again comparing DUCET weights. For 8-bit strings, this
patch merges both into a single pass. The identical prefix is skipped 16 bytes at
a time with SIMD while every byte is printable ASCII (0x20-0x7E), since all of
those have non-zero DUCET level-1 weight and an identical run of them cannot
decide the comparison. The per-character comparison resumes from the first byte
that differs or needs checking. The final overlapping 16-byte load avoids a
per-character tail. 8-15 byte strings use two overlapping 64-bit loads instead.

The level-3 tie-break pass also starts from the first difference instead of
position 0, since the identical prefix has identical level-3 weights.

Benchmark results with --useJIT=0 are following.

                                                         ToT                     Patched

    intl-collator-compare-long-prefix-different-length
                                                  125.0767+-1.0766     ^     83.3447+-0.4762        ^ definitely 1.5007x faster
    intl-collator-compare-equal-long               85.4302+-1.0364     ^     83.0366+-0.7213        ^ definitely 1.0288x faster
    intl-collator-compare-16bit-long-prefix-primary-diff
                                                  151.4125+-0.8296     ^    121.6623+-1.5823        ^ definitely 1.2445x faster
    intl-collator-compare-long-prefix-case-diff
                                                  174.4286+-0.9481     ^     85.0297+-0.4806        ^ definitely 2.0514x faster
    intl-collator-compare-long-prefix-primary-diff
                                                  129.0799+-0.9748     ^     83.8850+-0.5827        ^ definitely 1.5388x faster
    intl-collator-compare-first-char-diff          83.3505+-0.9395     ^     81.5479+-0.5391        ^ definitely 1.0221x faster
    intl-collator-compare-sort-short-keys         164.9051+-2.5775     ^    144.1785+-0.4210        ^ definitely 1.1438x faster

Tests: JSTests/microbenchmarks/intl-collator-compare-16bit-long-prefix-primary-diff.js
       JSTests/microbenchmarks/intl-collator-compare-equal-long.js
       JSTests/microbenchmarks/intl-collator-compare-first-char-diff.js
       JSTests/microbenchmarks/intl-collator-compare-long-prefix-case-diff.js
       JSTests/microbenchmarks/intl-collator-compare-long-prefix-different-length.js
       JSTests/microbenchmarks/intl-collator-compare-long-prefix-primary-diff.js
       JSTests/microbenchmarks/intl-collator-compare-sort-short-keys.js

* JSTests/microbenchmarks/intl-collator-compare-16bit-long-prefix-primary-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-equal-long.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-first-char-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-long-prefix-case-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-long-prefix-different-length.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-long-prefix-primary-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-sort-short-keys.js: Added.
(makeKeys):
(test):
* Source/JavaScriptCore/runtime/IntlObjectInlines.h:
(JSC::identicalPrintableASCIIPrefixLength):
(JSC::compareASCIIWithUCADUCET):

Canonical link: https://commits.webkit.org/324132@main

6fd5672

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win ⏳ 🛠 ios-apple
✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ✅ 🧪 win-tests ⏳ 🛠 mac-apple
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ❌ 🧪 api-mac ✅ 🧪 api-wpe ⏳ 🛠 vision-apple
✅ 🧪 ios-wk2-wpt ✅ 🧪 api-mac-debug ✅ 🧪 jsc-wpe
✅ 🧪 jsc-x86-64 ✅ 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk3-gcc
✅ 🛠 🧪 jsc-debug-arm64 ✅ 🛠 ios-safer-cpp ✅ 🧪 mac-AS-debug-wk2 ✅ 🛠 gtk
✅ 🛠 vision ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-intel-wk2 ✅ 🧪 api-gtk
✅ 🛠 🧪 unsafe-merge ✅ 🧪 vision-wk2 ✅ 🛠 mac-safer-cpp ✅ 🛠 playstation
✅ 🛠 tv ✅ 🧪 mac-site-isolation
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@Constellation
Constellation requested a review from a team as a code owner October 18, 2026 02:59
@Constellation Constellation self-assigned this Oct 18, 2026
@Constellation Constellation added the JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues. label Oct 18, 2026
@Constellation Constellation added the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Oct 19, 2026
…st path

https://bugs.webkit.org/show_bug.cgi?id=327979
rdar://190333228

Reviewed by Sosuke Suzuki.

compareASCIIWithUCADUCET first scanned equal-length strings with equal() and then
walked the same characters again comparing DUCET weights. For 8-bit strings, this
patch merges both into a single pass. The identical prefix is skipped 16 bytes at
a time with SIMD while every byte is printable ASCII (0x20-0x7E), since all of
those have non-zero DUCET level-1 weight and an identical run of them cannot
decide the comparison. The per-character comparison resumes from the first byte
that differs or needs checking. The final overlapping 16-byte load avoids a
per-character tail. 8-15 byte strings use two overlapping 64-bit loads instead.

The level-3 tie-break pass also starts from the first difference instead of
position 0, since the identical prefix has identical level-3 weights.

Benchmark results with --useJIT=0 are following.

                                                         ToT                     Patched

    intl-collator-compare-long-prefix-different-length
                                                  125.0767+-1.0766     ^     83.3447+-0.4762        ^ definitely 1.5007x faster
    intl-collator-compare-equal-long               85.4302+-1.0364     ^     83.0366+-0.7213        ^ definitely 1.0288x faster
    intl-collator-compare-16bit-long-prefix-primary-diff
                                                  151.4125+-0.8296     ^    121.6623+-1.5823        ^ definitely 1.2445x faster
    intl-collator-compare-long-prefix-case-diff
                                                  174.4286+-0.9481     ^     85.0297+-0.4806        ^ definitely 2.0514x faster
    intl-collator-compare-long-prefix-primary-diff
                                                  129.0799+-0.9748     ^     83.8850+-0.5827        ^ definitely 1.5388x faster
    intl-collator-compare-first-char-diff          83.3505+-0.9395     ^     81.5479+-0.5391        ^ definitely 1.0221x faster
    intl-collator-compare-sort-short-keys         164.9051+-2.5775     ^    144.1785+-0.4210        ^ definitely 1.1438x faster

Tests: JSTests/microbenchmarks/intl-collator-compare-16bit-long-prefix-primary-diff.js
       JSTests/microbenchmarks/intl-collator-compare-equal-long.js
       JSTests/microbenchmarks/intl-collator-compare-first-char-diff.js
       JSTests/microbenchmarks/intl-collator-compare-long-prefix-case-diff.js
       JSTests/microbenchmarks/intl-collator-compare-long-prefix-different-length.js
       JSTests/microbenchmarks/intl-collator-compare-long-prefix-primary-diff.js
       JSTests/microbenchmarks/intl-collator-compare-sort-short-keys.js

* JSTests/microbenchmarks/intl-collator-compare-16bit-long-prefix-primary-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-equal-long.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-first-char-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-long-prefix-case-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-long-prefix-different-length.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-long-prefix-primary-diff.js: Added.
(test):
* JSTests/microbenchmarks/intl-collator-compare-sort-short-keys.js: Added.
(makeKeys):
(test):
* Source/JavaScriptCore/runtime/IntlObjectInlines.h:
(JSC::identicalPrintableASCIIPrefixLength):
(JSC::compareASCIIWithUCADUCET):

Canonical link: https://commits.webkit.org/324132@main
@webkit-commit-queue

Copy link
Copy Markdown
Collaborator

Committed 324132@main (7b2dc73): https://commits.webkit.org/324132@main

Reviewed commits have been landed. Closing PR #77424 and removing active labels.

@webkit-commit-queue
webkit-commit-queue merged commit 7b2dc73 into WebKit:main Oct 19, 2026
@webkit-commit-queue webkit-commit-queue removed the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants