Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stdlib] Refactor Unicode normalization #73590

Merged
merged 2 commits into from
May 31, 2024
Merged

Conversation

karwa
Copy link
Collaborator

@karwa karwa commented May 13, 2024

Refactors the standard library's internal normalization routines to make them independent of using String as a storage type.

This doesn't expose any public APIs or ABI symbols (it's all still just internal, and not @usableFromInline), and should be performance-neutral.

@karwa
Copy link
Collaborator Author

karwa commented May 13, 2024

@swift-ci please benchmark

@Azoy
Copy link
Member

Azoy commented May 13, 2024

@swift-ci please benchmark

@karwa
Copy link
Collaborator Author

karwa commented May 14, 2024

Hmm, does seem to find a regression with zalgo (so, lots of combining characters), but checking my local results, when I ran it, it was okay. Hmm....

main: {"number": 973, "name": "StringComparison_zalgo", "num_samples": 200, "min": 26000.0, "median": 26150.0, "max": 27525.0}
this: {"number": 973, "name": "StringComparison_zalgo", "num_samples": 200, "min": 25925.0, "median": 26075.0, "max": 28300.0}

Performance (x86_64): -O

Regression OLD NEW DELTA RATIO
StringComparison_zalgo 49850.0 87350.0 +75.2% 0.57x
StringHashing_zalgo 2678.846 4522.222 +68.8% 0.59x
NormalizedIterator_zalgo 2808.333 4593.75 +63.6% 0.61x
 
Improvement OLD NEW DELTA RATIO
FlattenListLoop 1362.0 976.5 -28.3% 1.39x (?)
Array.removeAll.keepingCapacity.Object 7.375 5.775 -21.7% 1.28x (?)
StringHashing_abnormal 610.959 562.933 -7.9% 1.09x (?)
ObserverForwarderStruct 621.667 573.462 -7.8% 1.08x (?)

Code size: -O

Performance (x86_64): -Osize

Regression OLD NEW DELTA RATIO
StringComparison_zalgo 49800.0 87025.0 +74.7% 0.57x
StringHashing_zalgo 2670.0 4516.667 +69.2% 0.59x
NormalizedIterator_zalgo 2751.25 4610.417 +67.6% 0.60x
StringBuilder 233.143 253.75 +8.8% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
ArrayAppendGenericStructs 1765.0 1402.5 -20.5% 1.26x (?)
StringDistance.utf16.ascii 151.0 138.882 -8.0% 1.09x (?)
StringHashing_abnormal 610.588 562.857 -7.8% 1.08x (?)

Code size: -Osize

Performance (x86_64): -Onone

Regression OLD NEW DELTA RATIO
StringComparison_zalgo 50625.0 88075.0 +74.0% 0.57x
StringHashing_zalgo 2725.0 4579.167 +68.0% 0.60x
NormalizedIterator_zalgo 2781.579 4637.5 +66.7% 0.60x
ArrayAppendGenericStructs 1145.0 1437.5 +25.5% 0.80x (?)
NSStringConversion.InlineBuffer.ASCII 5071.0 5926.0 +16.9% 0.86x (?)
NSStringConversion.InlineBuffer.UTF8 3139.0 3564.0 +13.5% 0.88x (?)
StringWithCString2 0.009 0.01 +10.0% 0.91x (?)
 
Improvement OLD NEW DELTA RATIO
Dictionary4 687.5 630.0 -8.4% 1.09x (?)
CharacterLiteralsLarge 352.0 324.667 -7.8% 1.08x (?)
StringHashing_abnormal 686.774 639.063 -6.9% 1.07x (?)

@karwa
Copy link
Collaborator Author

karwa commented May 14, 2024

@swift-ci please benchmark Apple silicon

1 similar comment
@Azoy
Copy link
Member

Azoy commented May 14, 2024

@swift-ci please benchmark Apple silicon

@karwa
Copy link
Collaborator Author

karwa commented May 15, 2024

@swift-ci please benchmark

@karwa
Copy link
Collaborator Author

karwa commented May 15, 2024

heeeey it worked, I can do it myself now :)

@karwa
Copy link
Collaborator Author

karwa commented May 15, 2024

Okay that seems to have cleared it up. I'll take a look at things like LessSubstringSubstring, but most of the changes are now indicated as "dubious", which the benchmark script defines thusly:

# Indication of dubious changes: when result's MIN falls inside the
# (MIN, MAX) interval of result they are being compared with.

(as I understand it: their error-bars overlap). So overall I think results are fairly neutral, but I'll take another look anyway.

Performance (x86_64): -O

Regression OLD NEW DELTA RATIO
Array.removeAll.keepingCapacity.Int 0.077 0.102 +32.1% 0.76x (?)
Data.hash.Medium 24.259 30.483 +25.7% 0.80x (?)
LessSubstringSubstring 24.279 29.613 +22.0% 0.82x (?)
EqualSubstringString 24.382 29.719 +21.9% 0.82x (?)
LessSubstringSubstringGenericComparable 24.486 29.829 +21.8% 0.82x
EqualSubstringSubstring 24.583 29.926 +21.7% 0.82x (?)
EqualSubstringSubstringGenericEquatable 24.719 29.733 +20.3% 0.83x (?)
EqualStringSubstring 24.808 29.708 +19.8% 0.84x (?)
Array.removeAll.keepingCapacity.Object 6.057 7.253 +19.7% 0.84x (?)
StringComparison_longSharedPrefix 206.909 240.7 +16.3% 0.86x (?)
FlattenListFlatMap 3299.0 3821.0 +15.8% 0.86x (?)
NormalizedIterator_fastPrenormal 468.654 533.913 +13.9% 0.88x (?)
NormalizedIterator_emoji 316.0 349.63 +10.6% 0.90x (?)
NaiveRRC.init.largeContiguous 5.451 6.028 +10.6% 0.90x (?)
DropLastSequenceLazy 297.0 328.143 +10.5% 0.91x (?)
DropLastSequence 298.333 328.333 +10.1% 0.91x (?)
DropLastAnySequence 299.286 327.833 +9.5% 0.91x (?)
StringComparison_abnormal 945.882 1026.383 +8.5% 0.92x (?)
NormalizedIterator_latin1 170.778 183.7 +7.6% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
StringComparison_zalgo 49525.0 40425.0 -18.4% 1.23x (?)
NormalizedIterator_zalgo 2757.143 2393.182 -13.2% 1.15x
StringHashing_zalgo 2658.333 2312.5 -13.0% 1.15x (?)
StringBuilderLong 970.625 848.235 -12.6% 1.14x (?)
SubstringEquatable 335.167 297.0 -11.4% 1.13x (?)
SubstringEqualString 174.8 156.7 -10.4% 1.12x
StringBuilderWithLongSubstring 1135.385 1021.818 -10.0% 1.11x (?)
DropWhileAnySequenceLazy 412.25 378.0 -8.3% 1.09x (?)
Set.isDisjoint.Int.Empty 52.077 47.917 -8.0% 1.09x (?)
Set.isSuperset.Seq.Empty.Int 50.862 47.388 -6.8% 1.07x (?)

Code size: -O

Performance (x86_64): -Osize

Regression OLD NEW DELTA RATIO
FlattenListLoop 1031.0 1637.0 +58.8% 0.63x (?)
Array.removeAll.keepingCapacity.Object 5.62 7.198 +28.1% 0.78x (?)
Data.hash.Medium 24.258 30.483 +25.7% 0.80x (?)
EqualSubstringSubstringGenericEquatable 24.279 29.8 +22.7% 0.81x (?)
EqualSubstringSubstring 24.281 29.72 +22.4% 0.82x (?)
EqualStringSubstring 24.269 29.6 +22.0% 0.82x (?)
EqualSubstringString 24.816 30.16 +21.5% 0.82x (?)
LessSubstringSubstringGenericComparable 24.93 30.281 +21.5% 0.82x
LessSubstringSubstring 25.029 30.258 +20.9% 0.83x (?)
StringComparison_longSharedPrefix 202.8 238.3 +17.5% 0.85x (?)
Dictionary4 215.571 251.0 +16.4% 0.86x (?)
ArrayInClass 175.0 200.484 +14.6% 0.87x (?)
DataReplaceMedium 2818.605 3095.313 +9.8% 0.91x (?)
PrefixWhileSequence 200.778 219.667 +9.4% 0.91x (?)
PrefixWhileAnySequence 200.667 219.25 +9.3% 0.92x (?)
RemoveWhereFilterInts 22.455 24.359 +8.5% 0.92x (?)
StringComparison_abnormal 946.8 1025.217 +8.3% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
StringComparison_zalgo 49775.0 40325.0 -19.0% 1.23x (?)
StringHashing_zalgo 2665.0 2298.438 -13.8% 1.16x
NormalizedIterator_zalgo 2748.81 2400.0 -12.7% 1.15x
SubstringEquatable 346.0 303.833 -12.2% 1.14x (?)
LineSink.characters.alpha 74.576 66.167 -11.3% 1.13x (?)
SubstringEqualString 179.1 159.545 -10.9% 1.12x
Set.isSubset.Int.Empty 55.0 50.1 -8.9% 1.10x (?)
DropFirstAnySequence 1080.5 987.0 -8.7% 1.09x (?)
String.initRepeating.longMixStr.Count100 725.667 676.0 -6.8% 1.07x (?)

Code size: -Osize

Performance (x86_64): -Onone

Regression OLD NEW DELTA RATIO
CxxStringConversion.cxx.to.swift 115.5 154.0 +33.3% 0.75x (?)
ArrayAppendGenericStructs 1387.5 1785.0 +28.6% 0.78x (?)
LessSubstringSubstringGenericComparable 27.224 32.667 +20.0% 0.83x (?)
EqualSubstringSubstringGenericEquatable 27.654 33.083 +19.6% 0.84x (?)
Data.hash.Medium 28.667 34.211 +19.3% 0.84x (?)
LessSubstringSubstring 28.381 33.862 +19.3% 0.84x (?)
EqualSubstringString 28.625 34.071 +19.0% 0.84x (?)
EqualStringSubstring 28.957 34.182 +18.0% 0.85x
Set.isSubset.Seq.Int50 1369.0 1585.0 +15.8% 0.86x (?)
EqualSubstringSubstring 29.4 34.034 +15.8% 0.86x (?)
Set.isSubset.Seq.Int25 685.667 793.667 +15.8% 0.86x (?)
Set.isSubset.Seq.Int100 2778.0 3165.0 +13.9% 0.88x (?)
SIMDReduce.Int8 6525.0 7175.0 +10.0% 0.91x (?)
 
Improvement OLD NEW DELTA RATIO
StringComparison_zalgo 50675.0 41350.0 -18.4% 1.23x (?)
StringHashing_zalgo 2718.333 2371.875 -12.7% 1.15x (?)
NormalizedIterator_zalgo 2763.333 2426.563 -12.2% 1.14x (?)
Set.subtracting.Seq.Empty.Int 353.667 321.714 -9.0% 1.10x (?)
Dictionary4 692.0 630.667 -8.9% 1.10x (?)
String.initRepeating.longMixStr.Count100 725.5 677.0 -6.7% 1.07x (?)

@Azoy
Copy link
Member

Azoy commented May 15, 2024

@swift-ci please benchmark

@karwa
Copy link
Collaborator Author

karwa commented May 15, 2024

@swift-ci please benchmark apple silicon

@shahmishal is there an issue with that command? Neither of my attempts actually got enqueued, and neither was Alejandro’s.

@karwa
Copy link
Collaborator Author

karwa commented May 16, 2024

@Azoy After investigating, it appears EqualSubstringString and friends are just flaky. Firstly, even though it sounds normalisation-related, they don't actually hit the normalising slow-path. Secondly, lots of other PRs show the same kind of sporadic results for these benchmarks.

Example: An Array PR https://ci.swift.org/view/Pull%20Requests/job/swift-PR-macos-perf/920/

Benchmarks showed the same regressions as here:

LessSubstringSubstring                    | 24.061    | 29.719    | +23.5% | **0.81x (?)**
EqualSubstringSubstringGenericEquatable   | 24.506    | 30.156    | +23.1% | **0.81x (?)**
LessSubstringSubstringGenericComparable   | 24.382    | 29.938    | +22.8% | **0.81x (?)**
EqualSubstringSubstring                   | 24.51     | 30.053    | +22.6% | **0.82x**
EqualSubstringString                      | 24.4      | 29.842    | +22.3% | **0.82x (?)**
UTF8Decode_InitFromCustom_contiguous      | 143.733   | 175.545   | +22.1% | **0.82x (?)**
EqualStringSubstring                      | 24.806    | 30.269    | +22.0% | **0.82x**

Example 2: Optimised isASCII check https://ci.swift.org/view/Pull%20Requests/job/swift-PR-macos-perf/899/

Same thing:

EqualSubstringSubstring                    | 24.5    | 30.25     | +23.5% | **0.81x (?)**
EqualSubstringString                       | 24.279  | 29.839    | +22.9% | **0.81x (?)**
EqualStringSubstring                       | 24.385  | 29.96     | +22.9% | **0.81x (?)**
LessSubstringSubstring                     | 24.292  | 29.833    | +22.8% | **0.81x**
LessSubstringSubstringGenericComparable    | 24.594  | 30.038    | +22.1% | **0.82x (?)**
EqualSubstringSubstringGenericEquatable    | 24.5    | 29.84     | +21.8% | **0.82x (?)**
UTF8Decode_InitFromData                    | 149.417 | 175.727   | +17.6% | **0.85x (?)**
UTF8Decode_InitFromBytes                   | 153.818 | 179.75    | +16.9% | **0.86x (?)**
StringComparison_longSharedPrefix          | 211.444 | 242.5     | +14.7% | **0.87x (?)**
NormalizedIterator_fastPrenormal           | 516.429 | 579.75    | +12.3% | **0.89x (?)**

The zalgo thing was a much clearer indication of a performance issue from suboptimal inlining. If all we have left are some dubious results from known-flaky benchmarks (with the same kind of numbers, too), I don't think that's any indication of a regression.

@karwa
Copy link
Collaborator Author

karwa commented May 16, 2024

Also, can you share any info about why the string normalisation tests are disabled? They work for me locally if I remove the REQUIRES lines.

@karwa
Copy link
Collaborator Author

karwa commented May 17, 2024

@swift-ci please smoke test

@karwa karwa marked this pull request as ready for review May 17, 2024 17:23
@karwa karwa requested a review from a team as a code owner May 17, 2024 17:23
Copy link
Member

@Azoy Azoy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I don't see anything here that affects the actual normalization logic, so the stream work looks pretty trivial on top of it.

@milseman
Copy link
Contributor

@swift-ci please benchmark

@milseman
Copy link
Contributor

@swift-ci please test macOS platform

@karwa
Copy link
Collaborator Author

karwa commented May 30, 2024

@milseman Are you okay with me merging this?

@milseman milseman merged commit 7a57bd8 into apple:main May 31, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants