Skip to content

Conversation

@glessard
Copy link
Contributor

@glessard glessard commented Jan 9, 2024

The bounds-checking approach of UnsafeBufferPointer is to bounds-check only in debug mode. We wonder whether it would be more principled to bounds-check in all cases, with an available API to intentionally elide bounds-checking entirely in performance-sensitive cases. This PR enables release-mode bounds-checking in the functions and subscripts of UnsafeBufferPointer and UnsafeMutableBufferPointer. No API for unchecked access is added at this time.

Addresses rdar://93206377

@glessard glessard requested a review from a team as a code owner January 9, 2024 20:08
@glessard glessard marked this pull request as draft January 9, 2024 20:08
@glessard
Copy link
Contributor Author

glessard commented Jan 9, 2024

@swift-ci please benchmark

@DougGregor
Copy link
Member

Performance (x86_64): -O

Regression OLD NEW DELTA RATIO
SIMDReduce.Int32x4.Initializer 33.9 71.217 +110.1% 0.48x
StringWithCString2 0.0 0.001 +100.0% 0.50x (?)
SIMDReduce.Int8x16.Initializer 51.72 85.571 +65.4% 0.60x
StaticArray 1.652 2.424 +46.7% 0.68x (?)
NibbleSort 1536.923 2235.0 +45.4% 0.69x
SIMDReduce.Int32x16.Initializer 20.904 30.258 +44.7% 0.69x (?)
SortIntPyramid 517.143 706.25 +36.6% 0.73x (?)
FlattenListFlatMap 3151.0 4096.0 +30.0% 0.77x (?)
AngryPhonebook.ASCII2.Small 113.875 147.308 +29.4% 0.77x (?)
AngryPhonebook 281.655 360.426 +28.0% 0.78x (?)
SortStrings 493.5 621.333 +25.9% 0.79x
SortAdjacentIntPyramids 877.143 1070.0 +22.0% 0.82x (?)
NormalizedIterator_fastPrenormal 464.118 538.214 +16.0% 0.86x (?)
NormalizedIterator_emoji 309.935 353.6 +14.1% 0.88x (?)
NormalizedIterator_nonBMPSlowestPrenormal 410.833 467.561 +13.8% 0.88x (?)
SubstringEquatable 297.5 335.4 +12.7% 0.89x (?)
SubstringEqualString 156.091 174.8 +12.0% 0.89x (?)
RGBHistogram 1490.0 1665.714 +11.8% 0.89x (?)
NormalizedIterator_latin1 168.96 187.714 +11.1% 0.90x (?)
SortLettersInPlace 216.111 236.714 +9.5% 0.91x (?)
NormalizedIterator_slowerPrenormal 282.442 308.704 +9.3% 0.91x (?)
ParseInt.UInt64.Hex 246.222 266.125 +8.1% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
FlattenListLoop 1623.0 977.0 -39.8% 1.66x (?)
SIMDReduce.Int8x16.Cast 70.762 44.889 -36.6% 1.58x
CxxStringConversion.cxx.to.swift 160.0 125.0 -21.9% 1.28x (?)
LessSubstringSubstring 29.5 24.064 -18.4% 1.23x (?)
EqualSubstringString 29.606 24.156 -18.4% 1.23x
LessSubstringSubstringGenericComparable 29.719 24.375 -18.0% 1.22x (?)
EqualSubstringSubstring 29.828 24.481 -17.9% 1.22x
StrToInt 542.083 445.185 -17.9% 1.22x (?)
EqualStringSubstring 30.038 24.815 -17.4% 1.21x (?)
EqualSubstringSubstringGenericEquatable 29.5 24.5 -16.9% 1.20x (?)
Data.hash.Medium 28.516 24.265 -14.9% 1.18x (?)
StringComparison_longSharedPrefix 240.125 209.889 -12.6% 1.14x (?)
Dictionary4 239.143 215.5 -9.9% 1.11x (?)
MapReduceClassShort2 98.391 89.1 -9.4% 1.10x (?)
Dictionary4OfObjects 262.833 238.833 -9.1% 1.10x (?)
StringDistance.scalars.mixed 36.483 33.712 -7.6% 1.08x (?)
StringDistance.scalars.ascii 752.667 696.667 -7.4% 1.08x

Code size: -O

Regression OLD NEW DELTA RATIO
StringInterpolation.o 6688 6896 +3.1% 0.97x
SortIntPyramids.o 8558 8822 +3.1% 0.97x
StaticArray.o 12377 12641 +2.1% 0.98x
NibbleSort.o 13368 13632 +2.0% 0.98x
SortLettersInPlace.o 8483 8643 +1.9% 0.98x
RGBHistogram.o 21165 21469 +1.4% 0.99x
Breadcrumbs.o 43827 44371 +1.2% 0.99x
 
Improvement OLD NEW DELTA RATIO
Phonebook.o 9642 9386 -2.7% 1.03x
SortLargeExistentials.o 22432 21968 -2.1% 1.02x
IntegerParsing.o 66867 65891 -1.5% 1.01x

Performance (x86_64): -Osize

Regression OLD NEW DELTA RATIO
RawBufferInitializeMemory 66.167 108.833 +64.5% 0.61x
ParseInt.IntSmall.Decimal 119.368 160.714 +34.6% 0.74x
AngryPhonebook 273.241 361.109 +32.2% 0.76x (?)
AngryPhonebook.ASCII2.Small 113.75 147.308 +29.5% 0.77x
StaticArray 1.966 2.543 +29.3% 0.77x (?)
ParseInt.UInt64.Decimal 104.391 133.167 +27.6% 0.78x (?)
ParseInt.UInt64.Hex 247.667 315.0 +27.2% 0.79x (?)
StringWalk 1340.8 1675.385 +25.0% 0.80x (?)
ObjectiveCBridgeStubDateAccess 130.75 152.5 +16.6% 0.86x (?)
ArrayInClass 174.655 201.351 +15.3% 0.87x (?)
RGBHistogram 1764.286 2018.571 +14.4% 0.87x (?)
Array.removeAll.keepingCapacity.Object 6.287 7.095 +12.8% 0.89x (?)
SubstringEquatable 310.667 347.8 +12.0% 0.89x (?)
PrefixWhileSequence 180.1 200.333 +11.2% 0.90x (?)
PrefixWhileAnySequence 179.889 199.778 +11.1% 0.90x
SortLettersInPlace 213.667 237.25 +11.0% 0.90x
SortStrings 482.75 535.75 +11.0% 0.90x (?)
CharacterRecognizer.ascii 84.571 93.647 +10.7% 0.90x (?)
StrComplexWalk 2884.286 3153.333 +9.3% 0.91x (?)
NormalizedIterator_nonBMPSlowestPrenormal 411.167 448.727 +9.1% 0.92x (?)
NormalizedIterator_emoji 323.077 351.857 +8.9% 0.92x (?)
SubstringEqualString 161.5 175.3 +8.5% 0.92x (?)
ArrayAppendAsciiSubstring 14832.0 15993.0 +7.8% 0.93x (?)
ArrayAppendLatin1Substring 15129.0 16296.0 +7.7% 0.93x (?)
ArrayAppendUTF16Substring 14769.0 15894.0 +7.6% 0.93x (?)
Phonebook 1106.0 1190.0 +7.6% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
Dictionary4 233.333 167.6 -28.2% 1.39x (?)
Dictionary4OfObjects 263.5 201.286 -23.6% 1.31x (?)
EqualSubstringSubstring 29.065 23.512 -19.1% 1.24x
EqualStringSubstring 29.065 23.517 -19.1% 1.24x (?)
EqualSubstringSubstringGenericEquatable 29.063 23.531 -19.0% 1.24x (?)
EqualSubstringString 30.038 24.605 -18.1% 1.22x (?)
LessSubstringSubstringGenericComparable 30.161 24.727 -18.0% 1.22x (?)
LessSubstringSubstring 30.161 24.821 -17.7% 1.22x
FlattenListLoop 1647.0 1381.0 -16.2% 1.19x (?)
NibbleSort 2211.111 1904.444 -13.9% 1.16x (?)
StringComparison_longSharedPrefix 237.8 205.3 -13.7% 1.16x (?)
Data.hash.Medium 28.083 24.258 -13.6% 1.16x
ParseInt.UIntSmall.Binary 358.167 318.857 -11.0% 1.12x (?)
CxxStringConversion.swift.to.cxx 105.688 95.864 -9.3% 1.10x (?)
SIMDReduce.Int32x4.Cast 30.88 28.75 -6.9% 1.07x (?)

Code size: -Osize

Regression OLD NEW DELTA RATIO
StringInterpolation.o 6320 6491 +2.7% 0.97x
SortLettersInPlace.o 7878 8060 +2.3% 0.98x
Phonebook.o 8659 8859 +2.3% 0.98x
SortIntPyramids.o 8055 8212 +1.9% 0.98x
RGBHistogram.o 18355 18671 +1.7% 0.98x
StaticArray.o 9813 9970 +1.6% 0.98x
NibbleSort.o 13187 13344 +1.2% 0.99x
 
Improvement OLD NEW DELTA RATIO
SortLargeExistentials.o 22101 21732 -1.7% 1.02x
IntegerParsing.o 61708 60733 -1.6% 1.02x

Performance (x86_64): -Onone

Regression OLD NEW DELTA RATIO
SIMDReduce.Int8x64.Initializer 288945.0 346329.0 +19.9% 0.83x (?)
SIMDReduce.Int8x16.Initializer 300424.0 357996.0 +19.2% 0.84x (?)
SIMDReduce.Int32x16.Initializer 75856.0 90138.0 +18.8% 0.84x (?)
SIMDReduce.Int32x4.Initializer 87719.0 102403.0 +16.7% 0.86x (?)
 
Improvement OLD NEW DELTA RATIO
EqualStringSubstring 35.5 28.4 -20.0% 1.25x (?)
ArrayAppendGenericStructs 1355.0 1105.0 -18.5% 1.23x (?)
EqualSubstringSubstring 34.774 28.48 -18.1% 1.22x
EqualSubstringString 35.172 28.96 -17.7% 1.21x (?)
LessSubstringSubstringGenericComparable 32.24 26.667 -17.3% 1.21x (?)
EqualSubstringSubstringGenericEquatable 33.0 27.344 -17.1% 1.21x (?)
LessSubstringSubstring 34.0 28.243 -16.9% 1.20x (?)
Data.hash.Medium 31.783 28.45 -10.5% 1.12x (?)
ArrayOfPOD 740.5 666.5 -10.0% 1.11x (?)
ArrayOfGenericPOD2 1065.0 974.0 -8.5% 1.09x (?)
ConvertFloatingPoint.MockFloat64ToDouble 1329.0 1232.0 -7.3% 1.08x (?)

Code size: -swiftlibs

How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: 6-Core Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 32 GB

@glessard glessard force-pushed the rdar93206377-always-bounds-check branch from 19ad1f0 to 4348300 Compare January 10, 2024 00:28
@glessard
Copy link
Contributor Author

@swift-ci please benchmark

@glessard
Copy link
Contributor Author

@swift-ci smoke test macOS platform

@glessard
Copy link
Contributor Author

Performance (x86_64): -O

Regression OLD NEW DELTA RATIO
SIMDReduce.Int32x4.Initializer 33.933 141.385 +316.6% 0.24x
SIMDReduce.Int8x16.Initializer 51.8 141.143 +172.5% 0.37x
SIMDReduce.Int32x16.Initializer 20.904 47.697 +128.2% 0.44x
NibbleSort 1461.111 2238.75 +53.2% 0.65x
AngryPhonebook 270.278 382.884 +41.7% 0.71x (?)
SortIntPyramid 517.0 709.0 +37.1% 0.73x
AngryPhonebook.ASCII2.Small 113.688 152.667 +34.3% 0.74x (?)
LessSubstringSubstring 24.283 29.719 +22.4% 0.82x (?)
EqualSubstringString 24.39 29.839 +22.3% 0.82x (?)
LessSubstringSubstringGenericComparable 24.5 29.923 +22.1% 0.82x (?)
EqualSubstringSubstringGenericEquatable 24.707 30.154 +22.0% 0.82x (?)
EqualSubstringSubstring 24.615 30.04 +22.0% 0.82x (?)
EqualStringSubstring 24.821 30.259 +21.9% 0.82x (?)
SortAdjacentIntPyramids 878.571 1051.875 +19.7% 0.84x (?)
StringComparison_longSharedPrefix 209.778 241.222 +15.0% 0.87x (?)
SortLettersInPlace 216.556 236.5 +9.2% 0.92x (?)
StringFromLongWholeSubstring 3.104 3.37 +8.6% 0.92x (?)
NormalizedIterator_nonBMPSlowestPrenormal 431.132 467.708 +8.5% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
Diffing.Pangrams 2692.0 1684.0 -37.4% 1.60x
Diffing.ReversedLorem 956.5 636.333 -33.5% 1.50x
Diffing.PangramToAlphabet 1021.0 799.0 -21.7% 1.28x (?)
Dictionary4 243.429 192.375 -21.0% 1.27x (?)
Data.hash.Medium 30.481 24.275 -20.4% 1.26x
StrToInt 542.609 444.737 -18.0% 1.22x (?)
Dictionary4OfObjects 267.167 219.0 -18.0% 1.22x (?)
SubstringEqualString 174.889 153.909 -12.0% 1.14x (?)
Breadcrumbs.UTF16ToIdx.longASCII 44.68 39.345 -11.9% 1.14x (?)
Phonebook 1214.0 1092.5 -10.0% 1.11x (?)
SubstringEquatable 327.667 298.0 -9.1% 1.10x (?)
StringSwitch 252.857 231.75 -8.3% 1.09x (?)
StringDistance.scalars.ascii 752.333 695.0 -7.6% 1.08x (?)
StringDistance.scalars.mixed 36.478 33.712 -7.6% 1.08x (?)

Code size: -O

Regression OLD NEW DELTA RATIO
StringInterpolation.o 6640 6832 +2.9% 0.97x
SortIntPyramids.o 8558 8758 +2.3% 0.98x
StaticArray.o 12377 12577 +1.6% 0.98x
NibbleSort.o 13368 13568 +1.5% 0.99x
Phonebook.o 9642 9786 +1.5% 0.99x
RGBHistogram.o 21165 21421 +1.2% 0.99x
SortLettersInPlace.o 8483 8579 +1.1% 0.99x
 
Improvement OLD NEW DELTA RATIO
IntegerParsing.o 66867 65891 -1.5% 1.01x

Performance (x86_64): -Osize

Regression OLD NEW DELTA RATIO
RawBufferInitializeMemory 66.24 108.857 +64.3% 0.61x
AngryPhonebook 271.444 383.047 +41.1% 0.71x
AngryPhonebook.ASCII2.Small 113.563 154.308 +35.9% 0.74x (?)
ParseInt.IntSmall.Decimal 118.778 161.357 +35.8% 0.74x (?)
SortIntPyramid 638.846 817.0 +27.9% 0.78x (?)
ParseInt.UInt64.Hex 247.889 315.143 +27.1% 0.79x (?)
ParseInt.UInt64.Decimal 104.913 133.235 +27.0% 0.79x (?)
StringWalk 1351.667 1676.364 +24.0% 0.81x (?)
EqualStringSubstring 23.828 29.28 +22.9% 0.81x (?)
EqualSubstringSubstring 23.843 29.28 +22.8% 0.81x (?)
EqualSubstringSubstringGenericEquatable 23.854 29.289 +22.8% 0.81x
LessSubstringSubstring 24.923 30.6 +22.8% 0.81x (?)
EqualSubstringString 24.824 30.258 +21.9% 0.82x (?)
LessSubstringSubstringGenericComparable 25.03 30.038 +20.0% 0.83x
StringComparison_longSharedPrefix 205.2 239.6 +16.8% 0.86x (?)
ObjectiveCBridgeStubDateAccess 130.75 152.5 +16.6% 0.86x (?)
OpenClose 54.435 63.143 +16.0% 0.86x (?)
ArrayInClass 174.718 200.917 +15.0% 0.87x
PrefixWhileAnySequence 180.375 204.571 +13.4% 0.88x (?)
PrefixWhileSequence 179.286 201.889 +12.6% 0.89x (?)
SortAdjacentIntPyramids 909.444 1000.0 +10.0% 0.91x (?)
RemoveWhereFilterInts 22.519 24.353 +8.1% 0.92x (?)
FlattenListFlatMap 3085.0 3336.0 +8.1% 0.92x (?)
FindString.Loop1.Substring 300.857 324.429 +7.8% 0.93x (?)
ArrayAppendUTF16Substring 14733.0 15867.0 +7.7% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
Diffing.Pangrams 2719.0 1676.0 -38.4% 1.62x
Diffing.ReversedLorem 950.5 633.667 -33.3% 1.50x (?)
Dictionary4OfObjects 291.2 200.5 -31.1% 1.45x (?)
Dictionary4 238.5 166.667 -30.1% 1.43x
Array.removeAll.keepingCapacity.Object 7.603 5.88 -22.7% 1.29x (?)
Diffing.PangramToAlphabet 1021.0 798.0 -21.8% 1.28x (?)
SIMDReduce.Int8x16.Cast 57.25 45.194 -21.1% 1.27x (?)
Data.hash.Medium 30.258 24.235 -19.9% 1.25x
SIMDReduce.Int32x4.Cast 30.488 26.766 -12.2% 1.14x (?)
SubstringEquatable 341.5 303.0 -11.3% 1.13x (?)
SubstringEqualString 176.222 157.75 -10.5% 1.12x (?)
ParseInt.UIntSmall.Binary 356.5 319.571 -10.4% 1.12x (?)
NibbleSort 2185.556 1964.444 -10.1% 1.11x (?)
CxxStringConversion.swift.to.cxx 105.762 95.929 -9.3% 1.10x (?)
InsertCharacterEndIndexNonASCII 31.635 28.875 -8.7% 1.10x (?)
StringSwitch 247.5 226.125 -8.6% 1.09x
Breadcrumbs.UTF16ToIdx.longASCII 42.5 39.339 -7.4% 1.08x (?)

Code size: -Osize

Regression OLD NEW DELTA RATIO
Phonebook.o 8659 9237 +6.7% 0.94x
SIMDReduceInteger.o 9103 9387 +3.1% 0.97x
StringInterpolation.o 6267 6438 +2.7% 0.97x
RGBHistogram.o 18355 18612 +1.4% 0.99x
SortIntPyramids.o 8055 8166 +1.4% 0.99x
SortLettersInPlace.o 7763 7868 +1.4% 0.99x
StaticArray.o 9813 9924 +1.1% 0.99x
DriverUtils.o 133074 134546 +1.1% 0.99x
 
Improvement OLD NEW DELTA RATIO
IntegerParsing.o 61708 60733 -1.6% 1.02x

Performance (x86_64): -Onone

Regression OLD NEW DELTA RATIO
ArrayAppendGenericStructs 1140.0 1815.0 +59.2% 0.63x (?)
EqualStringSubstring 28.852 35.273 +22.3% 0.82x (?)
EqualSubstringString 29.075 35.086 +20.7% 0.83x (?)
LessSubstringSubstringGenericComparable 26.844 32.355 +20.5% 0.83x (?)
EqualSubstringSubstring 28.96 34.652 +19.7% 0.84x (?)
LessSubstringSubstring 28.865 34.321 +18.9% 0.84x
EqualSubstringSubstringGenericEquatable 28.0 33.241 +18.7% 0.84x (?)
NSStringConversion.InlineBuffer.ASCII 5256.0 5887.0 +12.0% 0.89x (?)
NSStringConversion.InlineBuffer.UTF8 3232.0 3597.0 +11.3% 0.90x (?)
 
Improvement OLD NEW DELTA RATIO
Phonebook 36568.0 10339.0 -71.7% 3.54x
SortLargeExistentials 30050.0 8707.143 -71.0% 3.45x
RGBHistogram 45420.0 15670.0 -65.5% 2.90x
WordCountHistogramASCII 69566.667 29340.0 -57.8% 2.37x
WordCountHistogramUTF16 68366.667 29380.0 -57.0% 2.33x
RGBHistogramOfObjects 91100.0 55000.0 -39.6% 1.66x
Diffing.Pangrams 2694.0 1694.0 -37.1% 1.59x
Diffing.ReversedLorem 947.0 634.333 -33.0% 1.49x
StaticArray 592.0 436.667 -26.2% 1.36x
Diffing.PangramToAlphabet 1016.0 799.0 -21.4% 1.27x (?)
Data.hash.Medium 34.667 28.647 -17.4% 1.21x (?)
ArrayOfPOD 737.0 664.667 -9.8% 1.11x (?)
SortStrings 1322.0 1205.0 -8.9% 1.10x (?)

Code size: -swiftlibs

How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: 6-Core Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 32 GB

@apple-fcloutier
Copy link

For -fbounds-safety, we add the ConstraintsElimination pass to the LLVM optimization pipeline to eliminate bounds checks. Is Swift already doing it? Would we consider doing it if the results are good?

@geoffreygaren
Copy link

I'm totally new to this programming context, so I apologize if I'm missing something obvious.

Does this change cover UnsafeMutableRawBufferPointer's copyBytes and copyMemory functions? (Or did they do bounds checking already before this patch?)

Same question for UnsafeRawBufferPointer's load...(...) functions.

How does this change interact with copyBytes(from:) and copyBytes(to:from:) style functions in Data and DataProtocol? Does the type's public API boundary automatically enforce checking in those cases?

@glessard
Copy link
Contributor Author

glessard commented Jan 10, 2024

@apple-fcloutier The Swift compiler already uses a constraints-elimination pass. It doesn't catch everything, but it's already pretty good, as illustrated by how mild the effect was here. A notable regression involved sorting, which performs a backwards-iteration (an atypical pattern.)

@geoffreygaren We will consider separately whether to turn it on for raw buffers, and it would involve every access. This PR hasn't yet tackled everything in UnsafeBufferPointer<T>. The functions from Data and DataProtocol are unaffected, as they are in the swift-foundation project (I believe they always bounds-check, fwiw.)

@tbkka
Copy link
Contributor

tbkka commented Jan 11, 2024

These are really encouraging results. I was a little nervous about this change, but if the regressions are this modest, then I'm all for it!

@glessard glessard added the swift evolution proposal needed Flag → feature: A feature that warrants a Swift evolution proposal label Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

swift evolution proposal needed Flag → feature: A feature that warrants a Swift evolution proposal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants