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] Random unification #16413

Merged
merged 6 commits into from May 10, 2018
Merged

[stdlib] Random unification #16413

merged 6 commits into from May 10, 2018

Conversation

Azoy
Copy link
Member

@Azoy Azoy commented May 5, 2018

Alright, lets try this again!
This is the implementation for SE-0202

Azoy and others added 3 commits May 4, 2018 21:02
Initial random api

Use C syscall for I/O

1. Fixed an issue where integers would would result in an infinite loop if they were unsigned, or signed integers always returning negative numbers.
2. Fixed an issue with Bool initialization

Add shuffle functions

Add documentation to Random API

Fix a few typos within the documentation

Fixes more typos

Also states that the range for floating points is from 0 to 1 inclusive

Update API to reflect mailing list discussions

Remove unnecessary import

Make sure not to return upperBound on Range

Use SecRandomCopyBytes on older macOS

Update API to match mailing list discussion, add tests

Added pick(_:) to collection
Added random(in:using:) to Randomizable
Added tests

Fix typo in Randomizable documentation

Rename pick to sampling

Move sampling below random

Update docs

Use new Libc naming

Fix Random.swift with new Libc naming

Remove sampling

gybify signed integer creation

Make FloatingPoint.random exclusive

Refactor {Closed}Range.random

Fix FloatingPoint initialization

Precondition getting a random number from range

Fix some doc typos

Make .random a function

Update API to reflect discussion

Make .random a function
Remove .random() in favor of .random(in:) for all numeric types

Fix compile errors

Clean up _stdlib_random

Cleanup around API

Remove `.random()` requirement from `Collection`

Use generators

Optimize shuffle()

Thread safety for /dev/urandom

Remove {Closed}Range<BinaryFloatingPoint>.random()

Add Collection random requirement

Refactor _stdlib_random

Remove whitespace changes

Clean linux shim

Add shuffle and more tests

Provide finishing tests and suggestions

Remove refs to Countable ranges

Revert to checking if T is > UInt64
* Remove refs to Countable ranges

* Add `_stdlib_random` for more platforms

* Use `getrandom` (if available) for Android, Cygwin

* Reorder the `_stdlib_random` functions

* Also include <features.h> on Linux

* Add `#error TODO` in `_stdlib_random` for Windows

* Colon after Fatal Error

Performance improvement for Random

gybify ranges

Fix typo in 'basic random numbers'
Add _stdlib_random as a testable method

Switch to generic constraints

Hopefully link against bcrypt

Fix some implementation details

1. Uniform distribution is now uniform
2. Apply Jens' method for uniform floats

Fix a lineable attribute
* [stdlib] Revise documentation for new random APIs

* [stdlib] Fix constraints on random integer generation

* [test] Isolate failing Random test

* [benchmark] Add benchmarks for new random APIs

Fix Float80 test

Value type generators

random -> randomElement

Fix some docs

One more doc fix

Doc fixes & bool fix

Use computed over explicit
@Azoy
Copy link
Member Author

Azoy commented May 5, 2018

cc: @airspeedswift

@natecook1000
Copy link
Member

@swift-ci Please smoke test

@natecook1000
Copy link
Member

@swift-ci Please smoke benchmark

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

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

I just have this one Q, then LGTM pending tests. I have some more documentation edits ready to go, but let's get this merged first!

// This can be found at: stdlib/public/core/Random.swift

#if defined(_WIN32) && !defined(__CYGWIN__)
#error TODO: Test _stdlib_random on Windows
Copy link
Member

Choose a reason for hiding this comment

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

Is this going to break the build for Win32 platforms?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes and no, this does break builds if they're compiling the stdlib. I can probably substitute this in with a warning directive instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

@swift-ci
Copy link
Collaborator

swift-ci commented May 5, 2018

Build comment file:

Optimized (O)

Regression (17)
TEST OLD NEW DELTA SPEEDUP
CharIndexing_utf16_unicodeScalars 22834 26926 +17.9% 0.85x
ObjectiveCBridgeFromNSSetAnyObjectForced 4967 5529 +11.3% 0.90x
StringInterpolation 9953 10878 +9.3% 0.91x
SuffixCountableRange 11 12 +9.1% 0.92x
NSDictionaryCastToSwift 7163 7763 +8.4% 0.92x (?)
PopFrontUnsafePointer 8812 9548 +8.4% 0.92x (?)
StringUTF16Builder 2611 2828 +8.3% 0.92x
FrequenciesUsingReduce 5002 5405 +8.1% 0.93x
ObjectiveCBridgeFromNSSetAnyObject 49189 53118 +8.0% 0.93x
ArrayAppendLatin1Substring 283801 305331 +7.6% 0.93x
IterateData 1836 1973 +7.5% 0.93x
StringEdits 171313 183615 +7.2% 0.93x (?)
ObjectiveCBridgeFromNSSetAnyObjectToString 67315 71747 +6.6% 0.94x (?)
ArrayAppendUTF16Substring 284967 302891 +6.3% 0.94x
AngryPhonebook 3748 3980 +6.2% 0.94x (?)
LazilyFilteredArrayContains 35726 37861 +6.0% 0.94x
DataAppendDataMediumToMedium 7824 8284 +5.9% 0.94x (?)
Improvement (18)
TEST OLD NEW DELTA SPEEDUP
ObjectiveCBridgeStubFromNSDate 7138 6080 -14.8% 1.17x
CharIteration_tweet_unicodeScalars 45876 40118 -12.6% 1.14x
CharIteration_japanese_unicodeScalars 27813 24656 -11.4% 1.13x
CharIteration_russian_unicodeScalars 19347 17151 -11.4% 1.13x
CharIteration_ascii_unicodeScalars 23250 20619 -11.3% 1.13x
CharIteration_chinese_unicodeScalars 17560 15580 -11.3% 1.13x
CharIteration_korean_unicodeScalars 22527 19993 -11.2% 1.13x
CharIndexing_utf16_unicodeScalars_Backwards 26134 23360 -10.6% 1.12x
CharIteration_punctuated_unicodeScalars 5186 4637 -10.6% 1.12x
CharIteration_punctuatedJapanese_unicodeScalars 4128 3704 -10.3% 1.11x
DataReplaceMedium 13122 11852 -9.7% 1.11x (?)
SequenceAlgosUnfoldSequence 1203 1102 -8.4% 1.09x
CharIndexing_korean_unicodeScalars 17341 16083 -7.3% 1.08x (?)
DataReplaceMediumBuffer 16052 14909 -7.1% 1.08x (?)
PopFrontArrayGeneric 1969 1837 -6.7% 1.07x (?)
ObjectiveCBridgeStubToNSDate 16172 15167 -6.2% 1.07x (?)
DropWhileSequence 2364 2225 -5.9% 1.06x
DataReplaceSmallBuffer 12405 11728 -5.5% 1.06x
No Changes (392)
TEST OLD NEW DELTA SPEEDUP
AnyHashableWithAClass 84628 84527 -0.1% 1.00x (?)
Array2D 2855 2854 -0.0% 1.00x (?)
ArrayAppend 1070 1073 +0.3% 1.00x (?)
ArrayAppendArrayOfInt 798 799 +0.1% 1.00x (?)
ArrayAppendAscii 3923 3960 +0.9% 0.99x (?)
ArrayAppendAsciiSubstring 153929 158002 +2.6% 0.97x
ArrayAppendFromGeneric 799 798 -0.1% 1.00x (?)
ArrayAppendGenericStructs 1426 1429 +0.2% 1.00x
ArrayAppendLatin1 39955 40139 +0.5% 1.00x
ArrayAppendLazyMap 1343 1344 +0.1% 1.00x (?)
ArrayAppendOptionals 1428 1433 +0.4% 1.00x (?)
ArrayAppendRepeatCol 1340 1343 +0.2% 1.00x
ArrayAppendReserved 801 805 +0.5% 1.00x
ArrayAppendSequence 1120 1123 +0.3% 1.00x
ArrayAppendStrings 6225 6349 +2.0% 0.98x
ArrayAppendToFromGeneric 797 795 -0.3% 1.00x (?)
ArrayAppendToGeneric 810 790 -2.5% 1.03x (?)
ArrayAppendUTF16 39764 39373 -1.0% 1.01x
ArrayInClass 85 85 +0.0% 1.00x
ArrayLiteral 0 0 +0.0% 1.00x
ArrayOfGenericPOD2 151 151 +0.0% 1.00x
ArrayOfGenericRef 4403 4397 -0.1% 1.00x (?)
ArrayOfPOD 184 184 +0.0% 1.00x
ArrayOfRef 4371 4385 +0.3% 1.00x (?)
ArrayPlusEqualArrayOfInt 797 798 +0.1% 1.00x (?)
ArrayPlusEqualFiveElementCollection 5433 5453 +0.4% 1.00x (?)
ArrayPlusEqualSingleElementCollection 1065 1074 +0.8% 0.99x
ArrayPlusEqualThreeElements 1676 1658 -1.1% 1.01x
ArraySubscript 1523 1534 +0.7% 0.99x
ArrayValueProp 8 8 +0.0% 1.00x
ArrayValueProp2 8 8 +0.0% 1.00x
ArrayValueProp3 8 8 +0.0% 1.00x
ArrayValueProp4 8 8 +0.0% 1.00x
BinaryFloatingPointPropertiesBinade 31 31 +0.0% 1.00x
BinaryFloatingPointPropertiesNextUp 28 28 +0.0% 1.00x
BinaryFloatingPointPropertiesUlp 37 37 +0.0% 1.00x
BitCount 211 211 +0.0% 1.00x
ByteSwap 106 103 -2.8% 1.03x
COWTree 5329 5461 +2.5% 0.98x (?)
CSVParsing 770523 770559 +0.0% 1.00x (?)
CSVParsingAlt 794507 788604 -0.7% 1.01x (?)
CSVParsingAltIndices 344555 345175 +0.2% 1.00x (?)
CStringLongAscii 4641 4711 +1.5% 0.99x (?)
CStringLongNonAscii 2172 2171 -0.0% 1.00x (?)
CStringShortAscii 3166 3176 +0.3% 1.00x (?)
Calculator 1127 1175 +4.3% 0.96x
CaptureProp 4101 4123 +0.5% 0.99x
ChainedFilterMap 1408 1420 +0.9% 0.99x
CharIndexing_ascii_unicodeScalars 16220 16282 +0.4% 1.00x (?)
CharIndexing_ascii_unicodeScalars_Backwards 16498 17143 +3.9% 0.96x (?)
CharIndexing_chinese_unicodeScalars 12196 12341 +1.2% 0.99x
CharIndexing_chinese_unicodeScalars_Backwards 12380 12974 +4.8% 0.95x (?)
CharIndexing_japanese_unicodeScalars 19249 19479 +1.2% 0.99x
CharIndexing_japanese_unicodeScalars_Backwards 19621 19816 +1.0% 0.99x (?)
CharIndexing_korean_unicodeScalars_Backwards 15900 16208 +1.9% 0.98x
CharIndexing_punctuatedJapanese_unicodeScalars 2922 2960 +1.3% 0.99x
CharIndexing_punctuatedJapanese_unicodeScalars_Backwards 2961 2995 +1.1% 0.99x
CharIndexing_punctuated_unicodeScalars 3657 3689 +0.9% 0.99x
CharIndexing_punctuated_unicodeScalars_Backwards 3707 3747 +1.1% 0.99x (?)
CharIndexing_russian_unicodeScalars 13399 13577 +1.3% 0.99x
CharIndexing_russian_unicodeScalars_Backwards 13736 13829 +0.7% 0.99x (?)
CharIndexing_tweet_unicodeScalars 31715 32032 +1.0% 0.99x (?)
CharIndexing_tweet_unicodeScalars_Backwards 32419 32269 -0.5% 1.00x (?)
CharIteration_ascii_unicodeScalars_Backwards 15154 15401 +1.6% 0.98x
CharIteration_chinese_unicodeScalars_Backwards 11480 11639 +1.4% 0.99x
CharIteration_japanese_unicodeScalars_Backwards 18128 18386 +1.4% 0.99x
CharIteration_korean_unicodeScalars_Backwards 14694 14895 +1.4% 0.99x
CharIteration_punctuatedJapanese_unicodeScalars_Backwards 2748 2792 +1.6% 0.98x
CharIteration_punctuated_unicodeScalars_Backwards 3438 3488 +1.5% 0.99x
CharIteration_russian_unicodeScalars_Backwards 12618 12795 +1.4% 0.99x
CharIteration_tweet_unicodeScalars_Backwards 29976 30435 +1.5% 0.98x
CharIteration_utf16_unicodeScalars 28403 27648 -2.7% 1.03x
CharIteration_utf16_unicodeScalars_Backwards 18854 18735 -0.6% 1.01x
CharacterLiteralsLarge 5805 5884 +1.4% 0.99x
CharacterLiteralsSmall 220 220 +0.0% 1.00x
CharacterPropertiesFetch 4537 4527 -0.2% 1.00x (?)
CharacterPropertiesPrecomputed 1124 1118 -0.5% 1.01x (?)
CharacterPropertiesStashed 1481 1493 +0.8% 0.99x (?)
CharacterPropertiesStashedMemo 1576 1596 +1.3% 0.99x
Chars 1216 1216 +0.0% 1.00x
ClassArrayGetter 15 15 +0.0% 1.00x
Combos 498 499 +0.2% 1.00x (?)
DataAccessBytes 1240 1232 -0.6% 1.01x (?)
DataAppendArray 6221 5994 -3.6% 1.04x
DataAppendBytes 5964 5962 -0.0% 1.00x (?)
DataAppendDataLargeToLarge 70033 69617 -0.6% 1.01x (?)
DataAppendDataLargeToMedium 36807 37080 +0.7% 0.99x (?)
DataAppendDataLargeToSmall 35872 35937 +0.2% 1.00x (?)
DataAppendDataMediumToLarge 39249 39218 -0.1% 1.00x (?)
DataAppendDataMediumToSmall 6919 7047 +1.8% 0.98x (?)
DataAppendDataSmallToLarge 38553 38695 +0.4% 1.00x (?)
DataAppendDataSmallToMedium 7752 7667 -1.1% 1.01x (?)
DataAppendDataSmallToSmall 6971 6859 -1.6% 1.02x (?)
DataAppendSequence 21978 21037 -4.3% 1.04x
DataCopyBytes 2531 2549 +0.7% 0.99x (?)
DataCount 37 37 +0.0% 1.00x
DataMutateBytes 4416 4405 -0.2% 1.00x (?)
DataReplaceLarge 44108 42864 -2.8% 1.03x
DataReplaceLargeBuffer 61097 60244 -1.4% 1.01x (?)
DataReplaceSmall 9703 9265 -4.5% 1.05x (?)
DataReset 3237 3303 +2.0% 0.98x (?)
DataSetCount 929 908 -2.3% 1.02x
DataSubscript 240 239 -0.4% 1.00x
DictOfArraysToArrayOfDicts 828 807 -2.5% 1.03x (?)
Dictionary 695 692 -0.4% 1.00x (?)
Dictionary2 816 820 +0.5% 1.00x
Dictionary2OfObjects 2238 2226 -0.5% 1.01x
Dictionary3 252 258 +2.4% 0.98x
Dictionary3OfObjects 769 771 +0.3% 1.00x (?)
Dictionary4 343 340 -0.9% 1.01x
Dictionary4Legacy 723 728 +0.7% 0.99x
Dictionary4OfObjects 456 456 +0.0% 1.00x
Dictionary4OfObjectsLegacy 934 941 +0.7% 0.99x
DictionaryBridge 1220 1272 +4.3% 0.96x (?)
DictionaryCopy 107304 107720 +0.4% 1.00x (?)
DictionaryFilter 105987 107109 +1.1% 0.99x
DictionaryGroup 219 218 -0.5% 1.00x (?)
DictionaryGroupOfObjects 2125 2129 +0.2% 1.00x (?)
DictionaryLiteral 1931 1942 +0.6% 0.99x (?)
DictionaryOfObjects 2516 2517 +0.0% 1.00x (?)
DictionaryRemove 4306 4177 -3.0% 1.03x
DictionaryRemoveOfObjects 27062 25922 -4.2% 1.04x
DictionarySubscriptDefaultMutation 267 268 +0.4% 1.00x (?)
DictionarySubscriptDefaultMutationArray 625 623 -0.3% 1.00x
DictionarySubscriptDefaultMutationArrayOfObjects 4034 4045 +0.3% 1.00x (?)
DictionarySubscriptDefaultMutationOfObjects 1716 1718 +0.1% 1.00x (?)
DictionarySwap 1039 1031 -0.8% 1.01x
DictionarySwapAt 6697 6771 +1.1% 0.99x (?)
DictionarySwapAtOfObjects 52855 52380 -0.9% 1.01x
DictionarySwapOfObjects 8827 8807 -0.2% 1.00x (?)
DoubleWidthDivision 0 0 +0.0% 1.00x
DropFirstAnyCollection 84 84 +0.0% 1.00x
DropFirstAnyCollectionLazy 62853 62475 -0.6% 1.01x (?)
DropFirstAnySeqCRangeIter 21485 21193 -1.4% 1.01x
DropFirstAnySeqCRangeIterLazy 21486 21190 -1.4% 1.01x
DropFirstAnySeqCntRange 41 41 +0.0% 1.00x
DropFirstAnySeqCntRangeLazy 41 41 +0.0% 1.00x
DropFirstAnySequence 4960 4991 +0.6% 0.99x
DropFirstAnySequenceLazy 4960 4992 +0.6% 0.99x
DropFirstArray 35 35 +0.0% 1.00x
DropFirstArrayLazy 35 35 +0.0% 1.00x
DropFirstCountableRange 35 35 +0.0% 1.00x
DropFirstCountableRangeLazy 35 35 +0.0% 1.00x
DropFirstSequence 2744 2682 -2.3% 1.02x
DropFirstSequenceLazy 2844 2775 -2.4% 1.02x
DropLastAnyCollection 31 31 +0.0% 1.00x
DropLastAnyCollectionLazy 20841 20916 +0.4% 1.00x (?)
DropLastAnySeqCRangeIter 3632 3635 +0.1% 1.00x (?)
DropLastAnySeqCRangeIterLazy 3630 3638 +0.2% 1.00x (?)
DropLastAnySeqCntRange 13 13 +0.0% 1.00x
DropLastAnySeqCntRangeLazy 13 13 +0.0% 1.00x
DropLastAnySequence 5025 5057 +0.6% 0.99x (?)
DropLastAnySequenceLazy 5147 5150 +0.1% 1.00x (?)
DropLastCountableRange 12 12 +0.0% 1.00x
DropLastCountableRangeLazy 12 12 +0.0% 1.00x
DropLastSequence 632 628 -0.6% 1.01x
DropLastSequenceLazy 633 628 -0.8% 1.01x
DropWhileAnyCollection 107 107 +0.0% 1.00x
DropWhileAnyCollectionLazy 125 125 +0.0% 1.00x
DropWhileAnySeqCRangeIter 16912 16704 -1.2% 1.01x
DropWhileAnySeqCRangeIterLazy 125 125 +0.0% 1.00x
DropWhileAnySeqCntRange 50 50 +0.0% 1.00x
DropWhileAnySeqCntRangeLazy 125 125 +0.0% 1.00x
DropWhileAnySequence 4899 4861 -0.8% 1.01x
DropWhileAnySequenceLazy 1856 1856 +0.0% 1.00x
DropWhileArrayLazy 88 88 +0.0% 1.00x
DropWhileCountableRange 36 36 +0.0% 1.00x
DropWhileCountableRangeLazy 105 105 +0.0% 1.00x
DropWhileSequenceLazy 88 88 +0.0% 1.00x
EqualStringSubstring 54 56 +3.7% 0.96x
EqualSubstringString 64 65 +1.6% 0.98x
EqualSubstringSubstring 48 49 +2.1% 0.98x
EqualSubstringSubstringGenericEquatable 48 49 +2.1% 0.98x
ErrorHandling 1504 1537 +2.2% 0.98x
ExclusivityGlobal 5 5 +0.0% 1.00x
ExclusivityIndependent 2 2 +0.0% 1.00x
FatCompactMap 203794 206324 +1.2% 0.99x (?)
FilterEvenUsingReduce 1321 1305 -1.2% 1.01x (?)
FilterEvenUsingReduceInto 147 147 +0.0% 1.00x
FloatingPointPrinting_Double_description_small 23793 23669 -0.5% 1.01x (?)
FloatingPointPrinting_Double_description_uniform 23242 23041 -0.9% 1.01x
FloatingPointPrinting_Double_interpolated 66668 67802 +1.7% 0.98x (?)
FloatingPointPrinting_Float80_description_small 30760 30761 +0.0% 1.00x (?)
FloatingPointPrinting_Float80_description_uniform 29704 29716 +0.0% 1.00x (?)
FloatingPointPrinting_Float80_interpolated 70627 70545 -0.1% 1.00x (?)
FloatingPointPrinting_Float_description_small 5181 5261 +1.5% 0.98x
FloatingPointPrinting_Float_description_uniform 4954 5093 +2.8% 0.97x
FloatingPointPrinting_Float_interpolated 42066 42344 +0.7% 0.99x (?)
FrequenciesUsingReduceInto 1554 1581 +1.7% 0.98x (?)
Hanoi 2173 2221 +2.2% 0.98x
HashTest 1047 1053 +0.6% 0.99x
Histogram 707 703 -0.6% 1.01x
Integrate 347 335 -3.5% 1.04x
Join 180 181 +0.6% 0.99x
LazilyFilteredArrays 65689 66950 +1.9% 0.98x (?)
LazilyFilteredRange 3881 3843 -1.0% 1.01x
LessSubstringSubstring 48 49 +2.1% 0.98x
LessSubstringSubstringGenericComparable 48 49 +2.1% 0.98x
LinkedList 7594 7562 -0.4% 1.00x (?)
LuhnAlgoEager 323 326 +0.9% 0.99x (?)
LuhnAlgoLazy 318 323 +1.6% 0.98x
MapReduce 400 398 -0.5% 1.01x
MapReduceAnyCollection 432 429 -0.7% 1.01x (?)
MapReduceAnyCollectionShort 2254 2269 +0.7% 0.99x
MapReduceClass 3024 3013 -0.4% 1.00x
MapReduceClassShort 4570 4553 -0.4% 1.00x (?)
MapReduceLazyCollection 13 13 +0.0% 1.00x
MapReduceLazyCollectionShort 37 38 +2.7% 0.97x (?)
MapReduceLazySequence 86 86 +0.0% 1.00x
MapReduceSequence 454 453 -0.2% 1.00x (?)
MapReduceShort 2001 1998 -0.1% 1.00x (?)
MapReduceShortString 30 31 +3.3% 0.97x
MapReduceString 79 80 +1.3% 0.99x
Memset 217 214 -1.4% 1.01x (?)
MonteCarloE 10246 10212 -0.3% 1.00x
MonteCarloPi 42663 42700 +0.1% 1.00x (?)
NSError 172 173 +0.6% 0.99x (?)
NSStringConversion 726 743 +2.3% 0.98x
NibbleSort 3671 3670 -0.0% 1.00x
NopDeinit 32369 32180 -0.6% 1.01x
ObjectAllocation 133 132 -0.8% 1.01x
ObjectiveCBridgeFromNSArrayAnyObject 25821 25261 -2.2% 1.02x (?)
ObjectiveCBridgeFromNSArrayAnyObjectForced 5238 5141 -1.9% 1.02x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToString 45793 47031 +2.7% 0.97x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 44462 44295 -0.4% 1.00x (?)
ObjectiveCBridgeFromNSDictionaryAnyObject 116604 117382 +0.7% 0.99x (?)
ObjectiveCBridgeFromNSString 1219 1198 -1.7% 1.02x
ObjectiveCBridgeFromNSStringForced 2685 2648 -1.4% 1.01x
ObjectiveCBridgeStubDataAppend 11468 11679 +1.8% 0.98x
ObjectiveCBridgeStubDateMutation 400 401 +0.2% 1.00x
ObjectiveCBridgeStubFromArrayOfNSString 33332 32106 -3.7% 1.04x (?)
ObjectiveCBridgeStubFromNSString 1048 1037 -1.0% 1.01x (?)
ObjectiveCBridgeStubFromNSStringRef 164 165 +0.6% 0.99x
ObjectiveCBridgeStubNSDataAppend 2667 2658 -0.3% 1.00x (?)
ObjectiveCBridgeStubNSDateMutationRef 13768 13786 +0.1% 1.00x (?)
ObjectiveCBridgeStubToArrayOfNSString 39335 39866 +1.3% 0.99x (?)
ObjectiveCBridgeStubToNSDateRef 3439 3441 +0.1% 1.00x (?)
ObjectiveCBridgeStubToNSString 2393 2376 -0.7% 1.01x
ObjectiveCBridgeStubToNSStringRef 122 122 +0.0% 1.00x
ObjectiveCBridgeStubURLAppendPath 290013 281339 -3.0% 1.03x (?)
ObjectiveCBridgeStubURLAppendPathRef 299315 289198 -3.4% 1.03x
ObjectiveCBridgeToNSArray 15326 15833 +3.3% 0.97x (?)
ObjectiveCBridgeToNSDictionary 27148 26355 -2.9% 1.03x (?)
ObjectiveCBridgeToNSSet 17487 17601 +0.7% 0.99x (?)
ObjectiveCBridgeToNSString 490 493 +0.6% 0.99x
ObserverClosure 2152 2166 +0.7% 0.99x
ObserverForwarderStruct 1257 1251 -0.5% 1.00x (?)
ObserverPartiallyAppliedMethod 3752 3742 -0.3% 1.00x (?)
ObserverUnappliedMethod 2600 2641 +1.6% 0.98x
OpenClose 273 286 +4.8% 0.95x
PartialApplyDynamicType 0 0 +0.0% 1.00x
Phonebook 4755 4851 +2.0% 0.98x
PointerArithmetics 34384 34358 -0.1% 1.00x
PolymorphicCalls 25 25 +0.0% 1.00x
PopFrontArray 1968 1986 +0.9% 0.99x (?)
PrefixAnyCollection 84 84 +0.0% 1.00x
PrefixAnyCollectionLazy 62897 62542 -0.6% 1.01x (?)
PrefixAnySeqCRangeIter 16632 16571 -0.4% 1.00x
PrefixAnySeqCRangeIterLazy 16618 16573 -0.3% 1.00x (?)
PrefixAnySeqCntRange 28 28 +0.0% 1.00x
PrefixAnySeqCntRangeLazy 28 28 +0.0% 1.00x
PrefixAnySequence 4398 4361 -0.8% 1.01x
PrefixAnySequenceLazy 4390 4364 -0.6% 1.01x
PrefixArray 35 35 +0.0% 1.00x
PrefixArrayLazy 35 35 +0.0% 1.00x
PrefixCountableRange 35 35 +0.0% 1.00x
PrefixCountableRangeLazy 35 35 +0.0% 1.00x
PrefixSequence 2234 2223 -0.5% 1.00x
PrefixSequenceLazy 2312 2275 -1.6% 1.02x
PrefixWhileAnyCollection 154 154 +0.0% 1.00x
PrefixWhileAnyCollectionLazy 90 90 +0.0% 1.00x
PrefixWhileAnySeqCRangeIter 8996 8992 -0.0% 1.00x (?)
PrefixWhileAnySeqCRangeIterLazy 72 73 +1.4% 0.99x
PrefixWhileAnySeqCntRange 59 59 +0.0% 1.00x
PrefixWhileAnySeqCntRangeLazy 90 90 +0.0% 1.00x
PrefixWhileAnySequence 10177 10240 +0.6% 0.99x
PrefixWhileAnySequenceLazy 1393 1394 +0.1% 1.00x
PrefixWhileArray 88 88 +0.0% 1.00x
PrefixWhileArrayLazy 70 70 +0.0% 1.00x
PrefixWhileCountableRange 36 36 +0.0% 1.00x
PrefixWhileCountableRangeLazy 35 35 +0.0% 1.00x
PrefixWhileSequence 361 361 +0.0% 1.00x
PrefixWhileSequenceLazy 52 52 +0.0% 1.00x
Prims 915 911 -0.4% 1.00x
PrimsSplit 915 913 -0.2% 1.00x (?)
QueueConcrete 1152 1148 -0.3% 1.00x (?)
QueueGeneric 1152 1148 -0.3% 1.00x
RC4 149 149 +0.0% 1.00x
RGBHistogram 3193 3210 +0.5% 0.99x (?)
RGBHistogramOfObjects 23858 23737 -0.5% 1.01x (?)
RangeAssignment 343 339 -1.2% 1.01x
RangeIterationSigned 171 171 +0.0% 1.00x
RangeReplaceableCollectionPlusDefault 1011 1018 +0.7% 0.99x (?)
RecursiveOwnedParameter 115 115 +0.0% 1.00x
RemoveWhereFilterInts 47 47 +0.0% 1.00x
RemoveWhereFilterString 213 210 -1.4% 1.01x
RemoveWhereFilterStrings 437 438 +0.2% 1.00x (?)
RemoveWhereMoveInts 15 15 +0.0% 1.00x
RemoveWhereMoveStrings 708 709 +0.1% 1.00x (?)
RemoveWhereQuadraticInts 1292 1288 -0.3% 1.00x (?)
RemoveWhereQuadraticString 376 381 +1.3% 0.99x
RemoveWhereQuadraticStrings 2756 2758 +0.1% 1.00x
RemoveWhereSwapInts 19 19 +0.0% 1.00x
RemoveWhereSwapStrings 864 860 -0.5% 1.00x (?)
ReversedArray 58 57 -1.7% 1.02x
ReversedBidirectional 16557 16512 -0.3% 1.00x (?)
ReversedDictionary 267 269 +0.7% 0.99x (?)
RomanNumbers 91228 91364 +0.1% 1.00x (?)
SequenceAlgosAnySequence 12000 11728 -2.3% 1.02x
SequenceAlgosArray 1579 1579 +0.0% 1.00x
SequenceAlgosContiguousArray 1587 1579 -0.5% 1.01x
SequenceAlgosList 1350 1356 +0.4% 1.00x
SequenceAlgosRange 2576 2577 +0.0% 1.00x (?)
SetExclusiveOr 5149 5257 +2.1% 0.98x
SetExclusiveOr_OfObjects 11821 11783 -0.3% 1.00x (?)
SetIntersect 697 700 +0.4% 1.00x
SetIntersect_OfObjects 1635 1647 +0.7% 0.99x (?)
SetIsSubsetOf 354 354 +0.0% 1.00x
SetIsSubsetOf_OfObjects 451 451 +0.0% 1.00x
SetUnion 4520 4532 +0.3% 1.00x (?)
SetUnion_OfObjects 10289 10210 -0.8% 1.01x (?)
SevenBoom 885 888 +0.3% 1.00x (?)
Sim2DArray 417 417 +0.0% 1.00x
SortLargeExistentials 6175 6273 +1.6% 0.98x
SortLettersInPlace 1048 1046 -0.2% 1.00x (?)
SortSortedStrings 1003 1027 +2.4% 0.98x
SortStrings 1981 2024 +2.2% 0.98x
SortStringsUnicode 2454 2543 +3.6% 0.97x
StackPromo 25295 25218 -0.3% 1.00x
StaticArray 10 10 +0.0% 1.00x
StrComplexWalk 1784 1785 +0.1% 1.00x (?)
StrToInt 3182 3212 +0.9% 0.99x
StringAdder 713 736 +3.2% 0.97x
StringBuilder 664 654 -1.5% 1.02x
StringBuilderLong 2798 2781 -0.6% 1.01x
StringBuilderWithLongSubstring 1485 1506 +1.4% 0.99x (?)
StringComparison_abnormal 789 803 +1.8% 0.98x
StringComparison_ascii 1283 1317 +2.7% 0.97x
StringComparison_emoji 810 803 -0.9% 1.01x
StringComparison_fastPrenormal 797 823 +3.3% 0.97x
StringComparison_latin1 629 651 +3.5% 0.97x
StringComparison_longSharedPrefix 929 929 +0.0% 1.00x
StringComparison_nonBMPSlowestPrenormal 1580 1585 +0.3% 1.00x
StringComparison_slowerPrenormal 1724 1665 -3.4% 1.04x
StringComparison_zalgo 125181 125000 -0.1% 1.00x (?)
StringEnumRawValueInitialization 928 932 +0.4% 1.00x
StringEqualPointerComparison 305 304 -0.3% 1.00x
StringFromLongWholeSubstring 21 21 +0.0% 1.00x
StringFromLongWholeSubstringGeneric 21 21 +0.0% 1.00x
StringHasPrefixAscii 2207 2291 +3.8% 0.96x
StringHasPrefixUnicode 104773 104468 -0.3% 1.00x (?)
StringHasSuffixAscii 2319 2434 +5.0% 0.95x
StringHasSuffixUnicode 101933 103621 +1.7% 0.98x (?)
StringInterpolationManySmallSegments 20310 20671 +1.8% 0.98x
StringInterpolationSmall 6838 6968 +1.9% 0.98x
StringMatch 12995 12907 -0.7% 1.01x
StringRemoveDupes 525 528 +0.6% 0.99x
StringUTF16SubstringBuilder 5838 5852 +0.2% 1.00x (?)
StringWalk 1478 1434 -3.0% 1.03x
StringWithCString 40820 40831 +0.0% 1.00x (?)
StringWordBuilder 2325 2363 +1.6% 0.98x
StringWordBuilderReservingCapacity 1915 1958 +2.2% 0.98x
SubstringComparable 26 26 +0.0% 1.00x
SubstringEqualString 790 783 -0.9% 1.01x
SubstringEquatable 1390 1392 +0.1% 1.00x (?)
SubstringFromLongString 10 10 +0.0% 1.00x
SubstringFromLongStringGeneric 75 75 +0.0% 1.00x
SuffixAnyCollection 31 31 +0.0% 1.00x
SuffixAnyCollectionLazy 21021 20914 -0.5% 1.01x (?)
SuffixAnySeqCRangeIter 3858 3854 -0.1% 1.00x
SuffixAnySeqCRangeIterLazy 3865 3841 -0.6% 1.01x
SuffixAnySeqCntRange 20 20 +0.0% 1.00x
SuffixAnySeqCntRangeLazy 20 20 +0.0% 1.00x
SuffixAnySequence 5018 5058 +0.8% 0.99x
SuffixAnySequenceLazy 5153 5183 +0.6% 0.99x
SuffixCountableRangeLazy 11 11 +0.0% 1.00x
SuffixSequence 3750 3731 -0.5% 1.01x
SuffixSequenceLazy 3735 3731 -0.1% 1.00x (?)
SumUsingReduce 97 97 +0.0% 1.00x
SumUsingReduceInto 102 102 +0.0% 1.00x
SuperChars 14783 14913 +0.9% 0.99x
TwoSum 1477 1491 +0.9% 0.99x
TypeFlood 0 0 +0.0% 1.00x
UTF8Decode 304 303 -0.3% 1.00x
Walsh 433 423 -2.3% 1.02x
WordCountHistogramASCII 7678 7828 +2.0% 0.98x
WordCountHistogramUTF16 14212 14430 +1.5% 0.98x (?)
WordCountUniqueASCII 2134 2178 +2.1% 0.98x (?)
WordCountUniqueUTF16 7657 7891 +3.1% 0.97x (?)
WordSplitASCII 7199 7139 -0.8% 1.01x (?)
WordSplitUTF16 9096 8930 -1.8% 1.02x (?)
XorLoop 395 402 +1.8% 0.98x
Added (6)
TEST MIN MAX MEAN MAX_RSS
RandomDoubleDef 27679 27726 27704 7696384
RandomDoubleLCG 2270 2275 2272 7677269
RandomIntegersDef 25635 25715 25684 7696384
RandomIntegersLCG 173 173 173 7666347
RandomShuffleDef 832305 848710 840482 31708501
RandomShuffleLCG 58258 60760 59398 31688021

Unoptimized (Onone)

Regression (23)
TEST OLD NEW DELTA SPEEDUP
ObjectiveCBridgeStubFromArrayOfNSString 32564 38492 +18.2% 0.85x
FrequenciesUsingReduceInto 3217 3795 +18.0% 0.85x
CharIteration_ascii_unicodeScalars_Backwards 250371 289351 +15.6% 0.87x
AngryPhonebook 5315 5958 +12.1% 0.89x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 49762 55320 +11.2% 0.90x
StringMatch 42061 46560 +10.7% 0.90x
CharIndexing_japanese_unicodeScalars 379397 409199 +7.9% 0.93x
DataReplaceMedium 9564 10315 +7.9% 0.93x
StringComparison_fastPrenormal 4983 5370 +7.8% 0.93x
LuhnAlgoEager 5334 5733 +7.5% 0.93x (?)
ObjectiveCBridgeToNSSet 17838 19171 +7.5% 0.93x
FloatingPointPrinting_Float_interpolated 77767 83490 +7.4% 0.93x (?)
FrequenciesUsingReduce 10786 11575 +7.3% 0.93x
RomanNumbers 1320691 1410582 +6.8% 0.94x (?)
FloatingPointPrinting_Float80_description_uniform 58731 62406 +6.3% 0.94x
StringWalk 12202 12936 +6.0% 0.94x
DropLastAnySequenceLazy 31154 32965 +5.8% 0.95x
ObjectiveCBridgeToNSDictionary 27092 28626 +5.7% 0.95x
StrToInt 77189 81489 +5.6% 0.95x (?)
ArrayOfGenericPOD2 1072 1131 +5.5% 0.95x
CharIteration_utf16_unicodeScalars_Backwards 219615 231700 +5.5% 0.95x (?)
CharIndexing_chinese_unicodeScalars 240548 253505 +5.4% 0.95x
CharIndexing_korean_unicodeScalars_Backwards 348247 366592 +5.3% 0.95x (?)
Improvement (27)
TEST OLD NEW DELTA SPEEDUP
TypeFlood 223 186 -16.6% 1.20x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToString 55859 47139 -15.6% 1.18x (?)
CharIteration_tweet_unicodeScalars_Backwards 575233 498297 -13.4% 1.15x (?)
DataCount 256 223 -12.9% 1.15x
DataReplaceMediumBuffer 17859 15786 -11.6% 1.13x (?)
PointerArithmetics 129327 116050 -10.3% 1.11x
SuffixAnySeqCRangeIter 40128 36212 -9.8% 1.11x
ArrayPlusEqualFiveElementCollection 268781 243777 -9.3% 1.10x
Dictionary4Legacy 1625 1488 -8.4% 1.09x
Dictionary4 1322 1214 -8.2% 1.09x
ObjectiveCBridgeFromNSArrayAnyObjectForced 10274 9482 -7.7% 1.08x (?)
StringUTF16SubstringBuilder 23064 21346 -7.4% 1.08x
StringUTF16Builder 8748 8098 -7.4% 1.08x (?)
CStringShortAscii 6789 6294 -7.3% 1.08x (?)
SuffixAnySeqCRangeIterLazy 40264 37409 -7.1% 1.08x
ObjectiveCBridgeFromNSArrayAnyObject 30365 28409 -6.4% 1.07x (?)
DropLastAnySeqCRangeIterLazy 44109 41320 -6.3% 1.07x (?)
DataSubscript 472 443 -6.1% 1.07x
Dictionary4OfObjects 1885 1772 -6.0% 1.06x
DataReplaceLargeBuffer 62901 59319 -5.7% 1.06x
StringComparison_abnormal 1427 1348 -5.5% 1.06x
StringInterpolationSmall 9592 9073 -5.4% 1.06x (?)
ErrorHandling 6825 6466 -5.3% 1.06x
ObjectAllocation 1342 1272 -5.2% 1.06x (?)
DataSetCount 601 570 -5.2% 1.05x (?)
DropLastAnySeqCRangeIter 42627 40465 -5.1% 1.05x
StackPromo 102957 97850 -5.0% 1.05x (?)
No Changes (377)
TEST OLD NEW DELTA SPEEDUP
AnyHashableWithAClass 101917 102872 +0.9% 0.99x
Array2D 644081 636767 -1.1% 1.01x
ArrayAppend 4440 4446 +0.1% 1.00x (?)
ArrayAppendArrayOfInt 866 865 -0.1% 1.00x (?)
ArrayAppendAscii 28886 28477 -1.4% 1.01x
ArrayAppendAsciiSubstring 184713 183012 -0.9% 1.01x
ArrayAppendFromGeneric 865 872 +0.8% 0.99x (?)
ArrayAppendGenericStructs 1501 1505 +0.3% 1.00x
ArrayAppendLatin1 66416 66204 -0.3% 1.00x (?)
ArrayAppendLatin1Substring 323268 318995 -1.3% 1.01x
ArrayAppendLazyMap 171361 170685 -0.4% 1.00x (?)
ArrayAppendOptionals 1510 1510 +0.0% 1.00x
ArrayAppendRepeatCol 184018 183354 -0.4% 1.00x
ArrayAppendReserved 4278 4284 +0.1% 1.00x
ArrayAppendSequence 102940 104380 +1.4% 0.99x
ArrayAppendStrings 6358 6446 +1.4% 0.99x
ArrayAppendToFromGeneric 871 868 -0.3% 1.00x (?)
ArrayAppendToGeneric 876 875 -0.1% 1.00x (?)
ArrayAppendUTF16 66134 65784 -0.5% 1.01x
ArrayAppendUTF16Substring 326375 322070 -1.3% 1.01x
ArrayInClass 6542 6248 -4.5% 1.05x (?)
ArrayLiteral 1804 1801 -0.2% 1.00x (?)
ArrayOfGenericRef 10935 10822 -1.0% 1.01x
ArrayOfPOD 760 760 +0.0% 1.00x
ArrayOfRef 9954 10270 +3.2% 0.97x
ArrayPlusEqualArrayOfInt 870 867 -0.3% 1.00x (?)
ArrayPlusEqualSingleElementCollection 239063 238863 -0.1% 1.00x (?)
ArrayPlusEqualThreeElements 9387 9393 +0.1% 1.00x (?)
ArraySubscript 107880 107562 -0.3% 1.00x
ArrayValueProp 3674 3687 +0.4% 1.00x (?)
ArrayValueProp2 15548 15432 -0.7% 1.01x
ArrayValueProp3 4241 4377 +3.2% 0.97x
ArrayValueProp4 4167 4205 +0.9% 0.99x
BinaryFloatingPointPropertiesBinade 85 88 +3.5% 0.97x
BinaryFloatingPointPropertiesNextUp 128 126 -1.6% 1.02x
BinaryFloatingPointPropertiesUlp 131 131 +0.0% 1.00x
BitCount 8562 8567 +0.1% 1.00x (?)
ByteSwap 9482 9493 +0.1% 1.00x (?)
COWTree 12093 12516 +3.5% 0.97x
CSVParsing 2993800 3047070 +1.8% 0.98x (?)
CSVParsingAlt 1419845 1479609 +4.2% 0.96x (?)
CSVParsingAltIndices 2388573 2435287 +2.0% 0.98x (?)
CStringLongAscii 5361 5376 +0.3% 1.00x (?)
CStringLongNonAscii 2487 2461 -1.0% 1.01x
Calculator 2109 2150 +1.9% 0.98x
CaptureProp 278682 278693 +0.0% 1.00x (?)
ChainedFilterMap 233249 234889 +0.7% 0.99x (?)
CharIndexing_ascii_unicodeScalars 317922 317892 -0.0% 1.00x (?)
CharIndexing_ascii_unicodeScalars_Backwards 358022 374728 +4.7% 0.96x (?)
CharIndexing_chinese_unicodeScalars_Backwards 270714 273738 +1.1% 0.99x (?)
CharIndexing_japanese_unicodeScalars_Backwards 428253 439697 +2.7% 0.97x (?)
CharIndexing_korean_unicodeScalars 307859 309263 +0.5% 1.00x (?)
CharIndexing_punctuatedJapanese_unicodeScalars 56067 56418 +0.6% 0.99x (?)
CharIndexing_punctuatedJapanese_unicodeScalars_Backwards 62487 65494 +4.8% 0.95x
CharIndexing_punctuated_unicodeScalars 70702 72101 +2.0% 0.98x
CharIndexing_punctuated_unicodeScalars_Backwards 79013 81794 +3.5% 0.97x (?)
CharIndexing_russian_unicodeScalars 264928 263846 -0.4% 1.00x (?)
CharIndexing_russian_unicodeScalars_Backwards 298644 304257 +1.9% 0.98x (?)
CharIndexing_tweet_unicodeScalars 648990 636857 -1.9% 1.02x (?)
CharIndexing_tweet_unicodeScalars_Backwards 709212 739809 +4.3% 0.96x (?)
CharIndexing_utf16_unicodeScalars 276997 278207 +0.4% 1.00x (?)
CharIndexing_utf16_unicodeScalars_Backwards 309868 316534 +2.2% 0.98x (?)
CharIteration_ascii_unicodeScalars 150671 150525 -0.1% 1.00x (?)
CharIteration_chinese_unicodeScalars 113605 113381 -0.2% 1.00x (?)
CharIteration_chinese_unicodeScalars_Backwards 189727 189851 +0.1% 1.00x (?)
CharIteration_japanese_unicodeScalars 180032 179529 -0.3% 1.00x (?)
CharIteration_japanese_unicodeScalars_Backwards 300658 302433 +0.6% 0.99x (?)
CharIteration_korean_unicodeScalars 145655 146254 +0.4% 1.00x
CharIteration_korean_unicodeScalars_Backwards 243801 244863 +0.4% 1.00x (?)
CharIteration_punctuatedJapanese_unicodeScalars 26812 26712 -0.4% 1.00x (?)
CharIteration_punctuatedJapanese_unicodeScalars_Backwards 43689 43952 +0.6% 0.99x (?)
CharIteration_punctuated_unicodeScalars 33596 33611 +0.0% 1.00x (?)
CharIteration_punctuated_unicodeScalars_Backwards 55350 55465 +0.2% 1.00x (?)
CharIteration_russian_unicodeScalars 124973 124878 -0.1% 1.00x (?)
CharIteration_russian_unicodeScalars_Backwards 209408 209641 +0.1% 1.00x (?)
CharIteration_tweet_unicodeScalars 296728 296331 -0.1% 1.00x (?)
CharIteration_utf16_unicodeScalars 127432 127663 +0.2% 1.00x (?)
CharacterLiteralsLarge 5859 5820 -0.7% 1.01x
CharacterLiteralsSmall 705 677 -4.0% 1.04x
CharacterPropertiesFetch 5523 5552 +0.5% 0.99x (?)
CharacterPropertiesPrecomputed 3653 3542 -3.0% 1.03x (?)
CharacterPropertiesStashed 2323 2323 +0.0% 1.00x
CharacterPropertiesStashedMemo 4532 4563 +0.7% 0.99x (?)
Chars 36310 36187 -0.3% 1.00x
ClassArrayGetter 996 996 +0.0% 1.00x
Combos 2478 2368 -4.4% 1.05x (?)
DataAccessBytes 2401 2437 +1.5% 0.99x
DataAppendArray 5443 5369 -1.4% 1.01x (?)
DataAppendBytes 5158 5088 -1.4% 1.01x (?)
DataAppendDataLargeToLarge 68440 67997 -0.6% 1.01x (?)
DataAppendDataLargeToMedium 35444 35843 +1.1% 0.99x (?)
DataAppendDataLargeToSmall 34442 34276 -0.5% 1.00x (?)
DataAppendDataMediumToLarge 38164 38569 +1.1% 0.99x (?)
DataAppendDataMediumToMedium 6925 6806 -1.7% 1.02x (?)
DataAppendDataMediumToSmall 6008 5961 -0.8% 1.01x (?)
DataAppendDataSmallToLarge 37296 37379 +0.2% 1.00x (?)
DataAppendDataSmallToMedium 6497 6400 -1.5% 1.02x (?)
DataAppendDataSmallToSmall 6517 6220 -4.6% 1.05x
DataAppendSequence 1929049 1929000 -0.0% 1.00x (?)
DataCopyBytes 2506 2555 +2.0% 0.98x (?)
DataMutateBytes 5286 5352 +1.2% 0.99x (?)
DataReplaceLarge 39369 38352 -2.6% 1.03x (?)
DataReplaceSmall 6807 7038 +3.4% 0.97x (?)
DataReplaceSmallBuffer 12947 12447 -3.9% 1.04x (?)
DataReset 2942 2857 -2.9% 1.03x (?)
DictOfArraysToArrayOfDicts 3455 3447 -0.2% 1.00x (?)
Dictionary 2431 2418 -0.5% 1.01x
Dictionary2 1476 1490 +0.9% 0.99x (?)
Dictionary2OfObjects 4329 4470 +3.3% 0.97x (?)
Dictionary3 869 872 +0.3% 1.00x (?)
Dictionary3OfObjects 2170 2140 -1.4% 1.01x (?)
Dictionary4OfObjectsLegacy 2210 2108 -4.6% 1.05x (?)
DictionaryBridge 1345 1382 +2.8% 0.97x
DictionaryCopy 315400 314500 -0.3% 1.00x (?)
DictionaryFilter 333981 326592 -2.2% 1.02x
DictionaryGroup 4564 4522 -0.9% 1.01x (?)
DictionaryGroupOfObjects 7098 6930 -2.4% 1.02x (?)
DictionaryLiteral 8881 8817 -0.7% 1.01x (?)
DictionaryOfObjects 6145 6003 -2.3% 1.02x (?)
DictionaryRemove 17584 17470 -0.6% 1.01x (?)
DictionaryRemoveOfObjects 52706 52922 +0.4% 1.00x
DictionarySubscriptDefaultMutation 1985 1979 -0.3% 1.00x (?)
DictionarySubscriptDefaultMutationArray 2269 2248 -0.9% 1.01x (?)
DictionarySubscriptDefaultMutationArrayOfObjects 9308 9497 +2.0% 0.98x (?)
DictionarySubscriptDefaultMutationOfObjects 5343 5210 -2.5% 1.03x (?)
DictionarySwap 5039 4920 -2.4% 1.02x
DictionarySwapAt 35532 35373 -0.4% 1.00x (?)
DictionarySwapAtOfObjects 113727 114602 +0.8% 0.99x (?)
DictionarySwapOfObjects 18771 19232 +2.5% 0.98x (?)
DoubleWidthDivision 0 0 +0.0% 1.00x
DropFirstAnyCollection 15458 15264 -1.3% 1.01x
DropFirstAnyCollectionLazy 103487 101045 -2.4% 1.02x (?)
DropFirstAnySeqCRangeIter 23668 23717 +0.2% 1.00x (?)
DropFirstAnySeqCRangeIterLazy 23654 23602 -0.2% 1.00x
DropFirstAnySeqCntRange 15569 15226 -2.2% 1.02x
DropFirstAnySeqCntRangeLazy 15438 15196 -1.6% 1.02x
DropFirstAnySequence 12934 12843 -0.7% 1.01x
DropFirstAnySequenceLazy 12886 12833 -0.4% 1.00x
DropFirstArray 3445 3441 -0.1% 1.00x (?)
DropFirstArrayLazy 29478 29719 +0.8% 0.99x (?)
DropFirstCountableRange 312 310 -0.6% 1.01x
DropFirstCountableRangeLazy 33848 33877 +0.1% 1.00x
DropFirstSequence 12647 12383 -2.1% 1.02x
DropFirstSequenceLazy 12493 12367 -1.0% 1.01x
DropLastAnyCollection 5168 5119 -0.9% 1.01x
DropLastAnyCollectionLazy 35569 33998 -4.4% 1.05x
DropLastAnySeqCntRange 5193 5070 -2.4% 1.02x
DropLastAnySeqCntRangeLazy 5155 5090 -1.3% 1.01x
DropLastAnySequence 31042 30471 -1.8% 1.02x
DropLastCountableRange 107 107 +0.0% 1.00x
DropLastCountableRangeLazy 11301 11293 -0.1% 1.00x (?)
DropLastSequence 31235 30416 -2.6% 1.03x
DropLastSequenceLazy 30907 30474 -1.4% 1.01x
DropWhileAnyCollection 19989 19754 -1.2% 1.01x
DropWhileAnyCollectionLazy 22544 22330 -0.9% 1.01x (?)
DropWhileAnySeqCRangeIter 24744 24407 -1.4% 1.01x
DropWhileAnySeqCRangeIterLazy 22506 22338 -0.7% 1.01x
DropWhileAnySeqCntRange 19922 19645 -1.4% 1.01x
DropWhileAnySeqCntRangeLazy 22542 22296 -1.1% 1.01x (?)
DropWhileAnySequence 13833 13616 -1.6% 1.02x
DropWhileAnySequenceLazy 12558 12354 -1.6% 1.02x (?)
DropWhileArrayLazy 14081 14429 +2.5% 0.98x
DropWhileCountableRange 4869 4812 -1.2% 1.01x
DropWhileCountableRangeLazy 22207 21915 -1.3% 1.01x
DropWhileSequence 13190 13313 +0.9% 0.99x
DropWhileSequenceLazy 12028 12012 -0.1% 1.00x (?)
EqualStringSubstring 71 72 +1.4% 0.99x
EqualSubstringString 71 73 +2.8% 0.97x
EqualSubstringSubstring 72 73 +1.4% 0.99x
EqualSubstringSubstringGenericEquatable 57 60 +5.3% 0.95x
ExclusivityGlobal 183 191 +4.4% 0.96x
ExclusivityIndependent 75 77 +2.7% 0.97x
FatCompactMap 295368 296002 +0.2% 1.00x (?)
FilterEvenUsingReduce 3679 3634 -1.2% 1.01x (?)
FilterEvenUsingReduceInto 1928 1892 -1.9% 1.02x
FloatingPointPrinting_Double_description_small 24219 24535 +1.3% 0.99x
FloatingPointPrinting_Double_description_uniform 36059 36045 -0.0% 1.00x (?)
FloatingPointPrinting_Double_interpolated 105011 101997 -2.9% 1.03x (?)
FloatingPointPrinting_Float80_description_small 31479 31693 +0.7% 0.99x (?)
FloatingPointPrinting_Float80_interpolated 118050 124104 +5.1% 0.95x (?)
FloatingPointPrinting_Float_description_small 6794 6946 +2.2% 0.98x
FloatingPointPrinting_Float_description_uniform 17215 17357 +0.8% 0.99x
Hanoi 20673 20425 -1.2% 1.01x
HashTest 20923 21244 +1.5% 0.98x (?)
Histogram 6310 6363 +0.8% 0.99x (?)
Integrate 460 460 +0.0% 1.00x
IterateData 5456 5397 -1.1% 1.01x (?)
Join 788 784 -0.5% 1.01x
LazilyFilteredArrayContains 754205 753179 -0.1% 1.00x (?)
LazilyFilteredArrays 1472254 1433212 -2.7% 1.03x (?)
LazilyFilteredRange 534452 529928 -0.8% 1.01x
LessSubstringSubstring 73 73 +0.0% 1.00x
LessSubstringSubstringGenericComparable 60 60 +0.0% 1.00x
LinkedList 32310 32374 +0.2% 1.00x
LuhnAlgoLazy 5871 6009 +2.4% 0.98x (?)
MapReduce 25793 25539 -1.0% 1.01x (?)
MapReduceAnyCollection 25995 25658 -1.3% 1.01x
MapReduceAnyCollectionShort 38113 36875 -3.2% 1.03x
MapReduceClass 29659 29604 -0.2% 1.00x (?)
MapReduceClassShort 41266 40973 -0.7% 1.01x (?)
MapReduceLazyCollection 22705 22801 +0.4% 1.00x
MapReduceLazyCollectionShort 34065 33797 -0.8% 1.01x (?)
MapReduceLazySequence 20282 20269 -0.1% 1.00x (?)
MapReduceSequence 30716 30566 -0.5% 1.00x
MapReduceShort 37793 36500 -3.4% 1.04x (?)
MapReduceShortString 237 237 +0.0% 1.00x
MapReduceString 1753 1747 -0.3% 1.00x
Memset 44798 44769 -0.1% 1.00x (?)
MonteCarloE 1147813 1137010 -0.9% 1.01x (?)
MonteCarloPi 5199147 5189537 -0.2% 1.00x (?)
NSDictionaryCastToSwift 8244 8618 +4.5% 0.96x (?)
NSError 606 618 +2.0% 0.98x (?)
NSStringConversion 781 784 +0.4% 1.00x (?)
NibbleSort 503175 499341 -0.8% 1.01x (?)
NopDeinit 194256 198485 +2.2% 0.98x
ObjectiveCBridgeFromNSDictionaryAnyObject 122286 124181 +1.5% 0.98x (?)
ObjectiveCBridgeFromNSSetAnyObject 56246 55363 -1.6% 1.02x (?)
ObjectiveCBridgeFromNSSetAnyObjectForced 5819 5717 -1.8% 1.02x (?)
ObjectiveCBridgeFromNSSetAnyObjectToString 71950 71762 -0.3% 1.00x (?)
ObjectiveCBridgeFromNSString 2881 2867 -0.5% 1.00x (?)
ObjectiveCBridgeFromNSStringForced 2795 2783 -0.4% 1.00x (?)
ObjectiveCBridgeStubDataAppend 6381 6483 +1.6% 0.98x
ObjectiveCBridgeStubDateMutation 715 716 +0.1% 1.00x (?)
ObjectiveCBridgeStubFromNSDate 7025 6901 -1.8% 1.02x (?)
ObjectiveCBridgeStubFromNSString 1085 1093 +0.7% 0.99x (?)
ObjectiveCBridgeStubFromNSStringRef 197 199 +1.0% 0.99x
ObjectiveCBridgeStubNSDataAppend 3119 2999 -3.8% 1.04x
ObjectiveCBridgeStubNSDateMutationRef 15361 16059 +4.5% 0.96x (?)
ObjectiveCBridgeStubToArrayOfNSString 39608 40371 +1.9% 0.98x
ObjectiveCBridgeStubToNSDate 15634 16371 +4.7% 0.95x (?)
ObjectiveCBridgeStubToNSDateRef 3483 3494 +0.3% 1.00x (?)
ObjectiveCBridgeStubToNSString 2435 2421 -0.6% 1.01x (?)
ObjectiveCBridgeStubToNSStringRef 151 150 -0.7% 1.01x (?)
ObjectiveCBridgeStubURLAppendPath 306328 297173 -3.0% 1.03x (?)
ObjectiveCBridgeStubURLAppendPathRef 294911 298217 +1.1% 0.99x (?)
ObjectiveCBridgeToNSArray 15756 15515 -1.5% 1.02x (?)
ObjectiveCBridgeToNSString 528 547 +3.6% 0.97x (?)
ObserverClosure 6587 6689 +1.5% 0.98x
ObserverForwarderStruct 4608 4512 -2.1% 1.02x
ObserverPartiallyAppliedMethod 8152 8255 +1.3% 0.99x
ObserverUnappliedMethod 8271 8270 -0.0% 1.00x (?)
OpenClose 886 877 -1.0% 1.01x
PartialApplyDynamicType 40120 39623 -1.2% 1.01x
Phonebook 19206 19144 -0.3% 1.00x
PolymorphicCalls 2342 2400 +2.5% 0.98x
PopFrontArray 4771 4796 +0.5% 0.99x
PopFrontArrayGeneric 5522 5552 +0.5% 0.99x
PopFrontUnsafePointer 11160 11173 +0.1% 1.00x (?)
PrefixAnyCollection 15493 15289 -1.3% 1.01x
PrefixAnyCollectionLazy 102654 101511 -1.1% 1.01x (?)
PrefixAnySeqCRangeIter 18906 18986 +0.4% 1.00x
PrefixAnySeqCRangeIterLazy 18960 18960 +0.0% 1.00x
PrefixAnySeqCntRange 15518 15248 -1.7% 1.02x
PrefixAnySeqCntRangeLazy 15427 15298 -0.8% 1.01x
PrefixAnySequence 10694 10455 -2.2% 1.02x
PrefixAnySequenceLazy 10592 10408 -1.7% 1.02x
PrefixArray 3436 3390 -1.3% 1.01x (?)
PrefixArrayLazy 29439 29678 +0.8% 0.99x (?)
PrefixCountableRange 310 310 +0.0% 1.00x
PrefixCountableRangeLazy 33838 33862 +0.1% 1.00x (?)
PrefixSequence 10197 10077 -1.2% 1.01x (?)
PrefixSequenceLazy 10105 10146 +0.4% 1.00x (?)
PrefixWhileAnyCollection 28993 28507 -1.7% 1.02x
PrefixWhileAnyCollectionLazy 18628 18473 -0.8% 1.01x (?)
PrefixWhileAnySeqCRangeIter 35060 34226 -2.4% 1.02x (?)
PrefixWhileAnySeqCRangeIterLazy 18488 18263 -1.2% 1.01x (?)
PrefixWhileAnySeqCntRange 28948 28554 -1.4% 1.01x
PrefixWhileAnySeqCntRangeLazy 18458 18337 -0.7% 1.01x (?)
PrefixWhileAnySequence 27046 26638 -1.5% 1.02x
PrefixWhileAnySequenceLazy 11122 10991 -1.2% 1.01x
PrefixWhileArray 10579 10492 -0.8% 1.01x
PrefixWhileArrayLazy 12373 12371 -0.0% 1.00x (?)
PrefixWhileCountableRange 13874 13665 -1.5% 1.02x
PrefixWhileCountableRangeLazy 18224 18122 -0.6% 1.01x
PrefixWhileSequence 26861 26386 -1.8% 1.02x (?)
PrefixWhileSequenceLazy 10799 10691 -1.0% 1.01x
Prims 9822 9552 -2.7% 1.03x
PrimsSplit 9627 9658 +0.3% 1.00x (?)
QueueConcrete 14454 14335 -0.8% 1.01x
QueueGeneric 19060 18737 -1.7% 1.02x
RC4 16051 15987 -0.4% 1.00x
RGBHistogram 24661 24414 -1.0% 1.01x
RGBHistogramOfObjects 78617 77966 -0.8% 1.01x (?)
RangeAssignment 2636 2647 +0.4% 1.00x (?)
RangeIterationSigned 14729 14918 +1.3% 0.99x
RangeReplaceableCollectionPlusDefault 11362 11389 +0.2% 1.00x (?)
RecursiveOwnedParameter 5872 5771 -1.7% 1.02x (?)
RemoveWhereFilterInts 1950 1950 +0.0% 1.00x
RemoveWhereFilterString 1327 1316 -0.8% 1.01x (?)
RemoveWhereFilterStrings 2478 2468 -0.4% 1.00x
RemoveWhereMoveInts 3411 3399 -0.4% 1.00x
RemoveWhereMoveStrings 3928 3930 +0.1% 1.00x (?)
RemoveWhereQuadraticInts 8090 8052 -0.5% 1.00x
RemoveWhereQuadraticString 2283 2275 -0.4% 1.00x (?)
RemoveWhereQuadraticStrings 9734 9693 -0.4% 1.00x
RemoveWhereSwapInts 6160 6131 -0.5% 1.00x
RemoveWhereSwapStrings 6892 6853 -0.6% 1.01x
ReversedArray 13226 13159 -0.5% 1.01x (?)
ReversedBidirectional 43150 44301 +2.7% 0.97x
ReversedDictionary 23176 23590 +1.8% 0.98x
SequenceAlgosAnySequence 12991 12860 -1.0% 1.01x
SequenceAlgosArray 758525 754016 -0.6% 1.01x
SequenceAlgosContiguousArray 285684 283956 -0.6% 1.01x
SequenceAlgosList 8690 8761 +0.8% 0.99x
SequenceAlgosRange 1278936 1262401 -1.3% 1.01x
SequenceAlgosUnfoldSequence 6563 6462 -1.5% 1.02x
SetExclusiveOr 16329 16565 +1.4% 0.99x
SetExclusiveOr_OfObjects 41287 42144 +2.1% 0.98x (?)
SetIntersect 6550 6580 +0.5% 1.00x
SetIntersect_OfObjects 10238 10239 +0.0% 1.00x (?)
SetIsSubsetOf 1180 1164 -1.4% 1.01x
SetIsSubsetOf_OfObjects 2238 2234 -0.2% 1.00x (?)
SetUnion 11800 11851 +0.4% 1.00x
SetUnion_OfObjects 29560 29718 +0.5% 0.99x (?)
SevenBoom 1077 1089 +1.1% 0.99x
Sim2DArray 46244 44563 -3.6% 1.04x
SortLargeExistentials 11715 11730 +0.1% 1.00x (?)
SortLettersInPlace 1979 1969 -0.5% 1.01x
SortSortedStrings 1143 1165 +1.9% 0.98x
SortStrings 2239 2278 +1.7% 0.98x
SortStringsUnicode 2736 2745 +0.3% 1.00x (?)
StaticArray 2528 2534 +0.2% 1.00x (?)
StrComplexWalk 7264 7270 +0.1% 1.00x (?)
StringAdder 1123 1150 +2.4% 0.98x
StringBuilder 5577 5736 +2.9% 0.97x (?)
StringBuilderLong 2956 2969 +0.4% 1.00x (?)
StringBuilderWithLongSubstring 4762 4852 +1.9% 0.98x (?)
StringComparison_ascii 9475 9486 +0.1% 1.00x (?)
StringComparison_emoji 1988 1985 -0.2% 1.00x (?)
StringComparison_latin1 3857 3867 +0.3% 1.00x
StringComparison_longSharedPrefix 2370 2374 +0.2% 1.00x (?)
StringComparison_nonBMPSlowestPrenormal 3682 3680 -0.1% 1.00x (?)
StringComparison_slowerPrenormal 4166 4156 -0.2% 1.00x (?)
StringComparison_zalgo 127869 127360 -0.4% 1.00x (?)
StringEdits 380088 373034 -1.9% 1.02x (?)
StringEnumRawValueInitialization 33031 33808 +2.4% 0.98x
StringEqualPointerComparison 1573 1597 +1.5% 0.98x
StringFromLongWholeSubstring 12 12 +0.0% 1.00x
StringFromLongWholeSubstringGeneric 201 200 -0.5% 1.00x (?)
StringHasPrefixAscii 3035 3094 +1.9% 0.98x
StringHasPrefixUnicode 105705 105491 -0.2% 1.00x
StringHasSuffixAscii 3132 3264 +4.2% 0.96x
StringHasSuffixUnicode 102769 103417 +0.6% 0.99x
StringInterpolation 13620 13480 -1.0% 1.01x (?)
StringInterpolationManySmallSegments 22151 22282 +0.6% 0.99x (?)
StringRemoveDupes 738 732 -0.8% 1.01x
StringWithCString 43489 41480 -4.6% 1.05x
StringWordBuilder 2500 2496 -0.2% 1.00x (?)
StringWordBuilderReservingCapacity 2021 2047 +1.3% 0.99x
SubstringComparable 1643 1638 -0.3% 1.00x
SubstringEqualString 1730 1718 -0.7% 1.01x (?)
SubstringEquatable 5453 5459 +0.1% 1.00x (?)
SubstringFromLongString 18 18 +0.0% 1.00x
SubstringFromLongStringGeneric 105 105 +0.0% 1.00x
SuffixAnyCollection 5163 5119 -0.9% 1.01x
SuffixAnyCollectionLazy 35560 34573 -2.8% 1.03x (?)
SuffixAnySeqCntRange 5189 5106 -1.6% 1.02x
SuffixAnySeqCntRangeLazy 5150 5077 -1.4% 1.01x
SuffixAnySequence 26643 26272 -1.4% 1.01x
SuffixAnySequenceLazy 26715 26356 -1.3% 1.01x (?)
SuffixCountableRange 108 108 +0.0% 1.00x
SuffixCountableRangeLazy 11293 11299 +0.1% 1.00x (?)
SuffixSequence 26539 26280 -1.0% 1.01x
SuffixSequenceLazy 26474 26236 -0.9% 1.01x
SumUsingReduce 163124 160649 -1.5% 1.02x
SumUsingReduceInto 153732 153036 -0.5% 1.00x (?)
SuperChars 86343 86127 -0.3% 1.00x (?)
TwoSum 3513 3531 +0.5% 0.99x (?)
UTF8Decode 29842 29745 -0.3% 1.00x
Walsh 12086 12068 -0.1% 1.00x (?)
WordCountHistogramASCII 39479 38783 -1.8% 1.02x
WordCountHistogramUTF16 46843 46225 -1.3% 1.01x
WordCountUniqueASCII 7228 7219 -0.1% 1.00x (?)
WordCountUniqueUTF16 13172 12959 -1.6% 1.02x
WordSplitASCII 10544 10163 -3.6% 1.04x (?)
WordSplitUTF16 12278 12598 +2.6% 0.97x (?)
XorLoop 23496 23370 -0.5% 1.01x
Added (6)
TEST MIN MAX MEAN MAX_RSS
RandomDoubleDef 89340 91242 90201 8187904
RandomDoubleLCG 58071 58247 58145 8183808
RandomIntegersDef 61777 63465 62504 8146944
RandomIntegersLCG 38167 39178 38826 8134656
RandomShuffleDef 2240132 2241215 2240701 32186368
RandomShuffleLCG 1497376 1499551 1498195 32194560
Hardware Overview
  Model Name: Mac Pro
  Model Identifier: MacPro6,1
  Processor Name: 12-Core Intel Xeon E5
  Processor Speed: 2.7 GHz
  Number of Processors: 1
  Total Number of Cores: 12
  L2 Cache (per Core): 256 KB
  L3 Cache: 30 MB
  Memory: 64 GB

Copy link
Contributor

@milseman milseman left a comment

Choose a reason for hiding this comment

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

Overall LGTM, just some minor comments.

I'll let @moiseev review the floating point and integer code.

if T.bitWidth <= UInt64.bitWidth {
return T(truncatingIfNeeded: self.next())
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it would make sense to split off the rest of this function into a non-@inlinable @inline(never) internal method, and _fastPath the branch above. This could make it more likely that the 99.99% use case and fast-path is more reliably inlined and/or specialized. CC @eeckstein for thoughts.

Also, how is the rest of this code tested?

Copy link
Member Author

Choose a reason for hiding this comment

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

As for testing the rest, we currently do not test it, which is a concern @benrimmington brought up. Are there any testing mechanisms for larger integers (such as UInt72), or do we need to write up one?

Copy link
Member

Choose a reason for hiding this comment

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

We have the DoubleWidth type here, we could test a 128-bit integer type with that: https://github.com/apple/swift/blob/master/test/Prototypes/DoubleWidth.swift.gyb

If we want to test anything that isn't a power of two wide, that'll be an additional thing to develop.

Copy link
Member

Choose a reason for hiding this comment

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

Does FixedWidthInteger actually require that the representable range be 0 ..< 2^N for some N? It probably should, but I can't remember that it's actually spelled out anywhere, and this implementation assumes it.

Copy link
Member

Choose a reason for hiding this comment

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

Luckily, the static FixedWidthInteger.bitWidth property has the following note:

An unsigned, fixed-width integer type can represent values from 0 through (2 ** bitWidth) - 1, where ** is exponentiation.

} while random < range

return random % upperBound
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a comment explaining the implementation strategy and the reason you chose it?

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, in arc4random_uniform, we choose the smallest N such that 2^N is greater than or equal to upperBound, and then pull N bits at a time from the random source until we get a number smaller than upperBound. This avoids needing to compute two % operations, which is pretty significant.

// This can be found at: stdlib/public/core/Random.swift

#if defined(_WIN32) && !defined(__CYGWIN__)
#error TODO: Test _stdlib_random on Windows
Copy link
Contributor

Choose a reason for hiding this comment

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

actual_nbytes = nbytes;
#endif
if (actual_nbytes == -1) {
static const int fd =
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if this code should apply to arc4random on Darwin platforms, which claims it never returns an error code.

Copy link
Member Author

Choose a reason for hiding this comment

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

This does not apply to arc4random on Darwin platforms and won't be executed during runtime. I can separate Darwin's solution outside of this one if that clears any confusion.

@@ -11,34 +11,44 @@
//===----------------------------------------------------------------------===//

#if defined(__APPLE__)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Please re-outdent the conditional preprocessor directives.

static const bool getrandom_available =
!(getrandom(nullptr, 0, 0) == -1 && errno == ENOSYS);
if (getrandom_available) {
actual_nbytes = WHILE_EINTR(getrandom(buf, nbytes, 0));
Copy link
Member

Choose a reason for hiding this comment

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

Is a blocking read from the OS's entropy source the right behavior here? For applications like server side Swift we can pretty well expect a fast response from the OS because it'll have initialized its entropy sources by the time a Swift process is up. But for embedded platforms this call might take as long as minutes if the OS deems there's insufficient entropy.

There's pros and cons either way, I would just like to see a rationale for this somewhere for reference.

Copy link
Member Author

@Azoy Azoy May 6, 2018

Choose a reason for hiding this comment

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

The version of getrandom we're using here only blocks on OS startup where /dev/urandom may not have been initialized yet. After /dev/urandom is initialized, getrandom will always call into it, which makes this call non-blocking 99.99% of the time. The proposal explains this and shares that Python's implementation uses getrandom() as well, but falls back on /dev/urandom if getrandom() deems it needed to block on OS startup. We could do something similar.

By default, getrandom() draws entropy from the urandom source (i.e.,
the same source as the /dev/urandom device). This behavior can be
changed via the flags argument.

If the urandom source has not yet been initialized, then getrandom()
will block, unless GRND_NONBLOCK is specified in flags.

Copy link
Member

Choose a reason for hiding this comment

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

The proposal explains this and shares that Python's implementation uses getrandom() as well, but falls back on /dev/urandom if getrandom() deems it needed to block on OS startup. We could do something similar.

We could, but doesn't Python 3.6 do what you've got here now?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah you're right, 3.6 does what we have here and 3.5 fell back on reading /dev/urandom.

) -> Element? {
guard !isEmpty else {
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this all just a very verbose spelling of:

let delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
% if 'Closed' in Range:
if delta == .max {
  return Bound(truncatingIfNeeded: generator.next() as Bound.Magnitude)
}
delta += 1
% end
return lowerBound &+ Bound(truncatingIfNeeded: generator.next(upperBound: delta))

?

You're asking a lot of the optimizer here. Or am I missing something?

} while random < range

return random % upperBound
}
Copy link
Member

Choose a reason for hiding this comment

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

FWIW, in arc4random_uniform, we choose the smallest N such that 2^N is greater than or equal to upperBound, and then pull N bits at a time from the random source until we get a number smaller than upperBound. This avoids needing to compute two % operations, which is pretty significant.

if T.bitWidth <= UInt64.bitWidth {
return T(truncatingIfNeeded: self.next())
}

Copy link
Member

Choose a reason for hiding this comment

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

Does FixedWidthInteger actually require that the representable range be 0 ..< 2^N for some N? It probably should, but I can't remember that it's actually spelled out anywhere, and this implementation assumes it.

return T(truncatingIfNeeded: self.next())
}

let (quotient, remainder) = T.bitWidth.quotientAndRemainder(
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to be able to just iterate over .words here and slam in bits from the source. Words is under-constrained though, which makes this a pain, I think.

Copy link
Member

Choose a reason for hiding this comment

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

Adding initializer requirements like BinaryInteger.init<S: Sequence>(words: S) where S.Element == UInt or FixedWidthInteger.init<S>(truncatingIfNeeded words: S) would help, even if we can't fix Words. That's a separate proposal, though.

(What if we added a new protocol specifically for Words? If it wasn't related to Collection, it would sidestep the compiler performance issue.)

public static func random<T: RandomNumberGenerator>(
in range: ${Range}<Self>,
using generator: inout T
) -> Self {
Copy link
Member

Choose a reason for hiding this comment

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

This implementation is not quite right; I believe that it has a slight bias to numbers with even significands, will not generate some values when the range spans the origin, and will barf when upperBound - lowerBound overflows. I should be able to provide a fixed implementation sometime later this week.

}
#elif defined(__Fuchsia__)
__swift_size_t getentropy_nbytes = std::min(nbytes, __swift_size_t{256});
if (0 == getentropy(buf, getentropy_nbytes)) {
Copy link
Member

Choose a reason for hiding this comment

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

getentropy is usually used for seeding. zx_cprng_draw seems like the function we oughta call here but I'm no Googler so @zbowling?

@zbowling
Copy link
Contributor

zbowling commented May 7, 2018 via email

@airspeedswift
Copy link
Member

Unless there are any last-minute concerns, I'm going to merge this as it stands, and items from this PR can be resolved by follow-up commits.

@natecook1000
Copy link
Member

:shipit:

@airspeedswift
Copy link
Member

@swift-ci please test and merge

@natecook1000
Copy link
Member

@swift-ci Please test and merge

@airspeedswift
Copy link
Member

@swift-ci please test macOS platform

@swift-ci
Copy link
Collaborator

swift-ci commented May 8, 2018

Build failed
Swift Test OS X Platform
Git Sha - 48886c9ebbdb6543401a9a543316af2406283fc7

@airspeedswift
Copy link
Member

Hmm. Seems to be failing reproducibly on the simulator, but only specifically on the Double testing.

@Azoy
Copy link
Member Author

Azoy commented May 8, 2018

I can look into it when I get home, although that won’t be for another 8 hours 😕

Copy link
Member

@lorentey lorentey left a comment

Choose a reason for hiding this comment

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

Most of my comments aren't important enough to block this PR, except for the issue with the generic implementation of Random.next(). I'm requesting changes for that one issue only; although I'm also fine with landing this now and fixing that in a followup -- but it should be fixed soon.

return T(truncatingIfNeeded: self.next())
}

let (quotient, remainder) = T.bitWidth.quotientAndRemainder(
Copy link
Member

Choose a reason for hiding this comment

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

Adding initializer requirements like BinaryInteger.init<S: Sequence>(words: S) where S.Element == UInt or FixedWidthInteger.init<S>(truncatingIfNeeded words: S) would help, even if we can't fix Words. That's a separate proposal, though.

(What if we added a new protocol specifically for Words? If it wasn't related to Collection, it would sidestep the compiler performance issue.)


if remainder != 0 {
let random = next()
let mask = UInt64.max &>> (UInt64.bitWidth - remainder)
Copy link
Member

Choose a reason for hiding this comment

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

Masking is unnecessary here, and the entire remainder case can be rolled into the loop. (The &<< will shift off high bits that aren't representable.)

if T.bitWidth <= UInt64.bitWidth {
return T(truncatingIfNeeded: self.next())
}

Copy link
Member

Choose a reason for hiding this comment

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

Luckily, the static FixedWidthInteger.bitWidth property has the following note:

An unsigned, fixed-width integer type can represent values from 0 through (2 ** bitWidth) - 1, where ** is exponentiation.

}
}

public // @testable
Copy link
Member

Choose a reason for hiding this comment

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

This should be internal @usableFromInline // @testable. The symbol will then become accessible in tests as long as they are done with %target-run-stdlib-swift instead of %target-run-simple-swift.

let randomGreeting = greetings.randomElement()
expectNotNil(randomGreeting)
expectTrue(greetings.contains(randomGreeting!))
}
Copy link
Member

Choose a reason for hiding this comment

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

We could do the same coverage test we do for Int8, by inserting the selected elements into a set.

We should also test how randomElement behaves on an empty collection.

/// Returns a value from a uniform, independent distribution of binary data.
///
/// - Returns: An unsigned 64-bit random value.
public mutating func next() -> UInt64 {
Copy link
Member

Choose a reason for hiding this comment

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

This method seems like a good candidate for an @effects(releasenone) attribute.

/// ===================================
///
/// - Apple platforms use `arc4random_buf(3)` for newer versions of their OS,
/// and for older versions they will read from `/dev/urandom`.
Copy link
Member

Choose a reason for hiding this comment

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

Is this right? The shim calls arc4random whenever __APPLE__ is defined.

Copy link
Member

Choose a reason for hiding this comment

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

Ah good spot – the decision for the Apple implementation is to use one consistent implementation regardless of platform version. The caveats of OS version determining the method of generation exist today for arc4random and should extend to this implementation.

/// `/dev/urandom`.
/// - `Fuchsia` calls `getentropy(3)`.
/// - `Windows` calls `BCryptGenRandom`.
public struct Random : RandomNumberGenerator {
Copy link
Member

Choose a reason for hiding this comment

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

I wonder how much resilience costs us for Random; Random.default.next() involves an indirectly-sized temporary and three resilient function calls, when we only really need a single call.

Do we expect that Random may become non-empty in the future? If not, we should make it @_fixed_layout, and we should make the initializer and .default's getter and setter inlinable.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is there a way to mark a private initializer as @inlinable or something similar? I can't use a private initializer in an @inlinable getter/setter for a var, but I can if I make the initializer internal with @usableFromInline. I wonder if we have to make this change in order to achieve @inlinable for the static var.

Copy link
Member

Choose a reason for hiding this comment

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

If we're okay with making it inlinable, I think @inlinable internal is the way to do it.

/// every value of `T` is equally likely to be returned.
public mutating func next<T: FixedWidthInteger & UnsignedInteger>() -> T {
var random: T = 0
_stdlib_random(&random, MemoryLayout<T>.size)
Copy link
Member

@lorentey lorentey May 8, 2018

Choose a reason for hiding this comment

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

Alas, this isn't right; FixedWidthInteger types aren't necessarily bitwise initializable like this.

It may very well be that we can't easily do better than to provide four additional concrete overloads for UInt8, UInt16, UInt32 and UInt, and leave the generic case to the default implementation. 😞

A more complicated way to resolve this would be to implement these next() overloads using a new (defaulted) _random(using:) requirement on FixedWidthInteger, which the standard fixed width integers could implement using _stdlib_random. To make this work, we should expose a customizable _fillBuffer operation on RandomNumberGenerator.

protocol RandomNumberGenerator {
  mutating func next() -> UInt64
  // FIXME: De-underscore after swift-evolution amendment
  mutating func _fillBuffer(_ buffer: UnsafeMutableRawBufferPointer)
} 
extension RandomNumberGenerator {
  public mutating func _fillBuffer(_ buffer: UnsafeMutableRawBufferPointer) {
    // Implementation in terms of next()
  }
  // FIXME: Remove after swift-evolution amendment
  @inlinable
  public mutating next<T: FixedWidthInteger & UnsignedInteger>() -> T {
    return T._random(using: &self)
  }
}
extension Random {
   @effects(releasenone)
   public mutating func _fillBuffer(_ buffer: UnsafeMutableRawBufferPointer) {
    _stdlib_random(buffer)
  }
}

protocol FixedWidthInteger: ... {
  ...
  // Underscored to prevent misuse
  static func _random<R: RandomNumberGenerator>(using generator: inout R) -> Self
}
extension FixedWidthInteger {
  @inlinable
  public static func _random<R: RandomNumberGenerator>(using generator: inout R) -> Self {
    // Generic implementation with &<< and | (or +)
  }
}

extension UInt8 {
  @inlinable
  public static func _random<R: RandomNumberGenerator>(using generator: inout R) -> UInt8 {
    var result: UInt8 = 0
    withUnsafeMutableBytes(of: &result) { generator._fillBuffer($0) }
    return result
  }
}
// etc. for the other standard fixed width integer types

}

public // @testable
func _stdlib_random(_ bytes: UnsafeMutableRawBufferPointer) {
Copy link
Member

Choose a reason for hiding this comment

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

If filling a buffer with random bytes is the primitive operation around which we're building the default RNG, it should probably be exposed as a customizable public operation on RandomNumberGenerator. (I.e., I think it should be a requirement, with a default implementation in terms of the 64-bit next.)

(Update: I see you've already made the case for this on swift-evolution. 👍)

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I see that as a good future enhancement.

* Use the `__has_include` and `GRND_RANDOM` macros

* Use `getentropy` instead of `getrandom`

* Use `std::min` from the <algorithm> header

* Move `#if` out of the `_stdlib_random` function

* Use `getrandom` with "/dev/urandom" fallback

* Use `#pragma comment` to import "Bcrypt.lib"

* <https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp>
* <https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions>

* Use "/dev/urandom" instead of `SecRandomCopyBytes`

* Use `swift::StaticMutex` for shared "/dev/urandom"

* Add `getrandom_available`; use `O_CLOEXEC` flag

Add platform impl docs

Update copyrights

Fix docs

Add _stdlib_random test

Update _stdlib_random test

Add missing &

Notice about _stdlib_random

Fix docs

Guard on upperBound = 0

Test full range of 8 bit integers

Remove some gyb

Clean up integerRangeTest

Remove FixedWidthInteger constraint

Use arc4random universally

Fix randomElement

Constrain shuffle to RandomAccessCollection

warning instead of error

Move Apple's implementation

Fix failing test on 32 bit systems
…eir raw memory

Custom FixedWidthInteger types may not support this.

Introduce a new (non-public) FixedWidthInteger requirement for generating random values; implement it using &<</+ in the generic case, and specialize it using RandomNumberGenerator._fill(bytes) for the builtin types.
var tmp: Self = 0
for i in 0 ..< quotient + remainder.signum() {
let next: UInt64 = generator.next()
tmp += Self(truncatingIfNeeded: next) &<< (UInt64.bitWidth * i)
Copy link
Member

Choose a reason for hiding this comment

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

It might be worth opening jira / radar to track making this less spectacularly inefficient for bignums at some future point?

Copy link
Member

Choose a reason for hiding this comment

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

I think adding required BinaryInteger initializers to initialize integers from a given word or sequence of words would resolve this. I filed https://bugs.swift.org/browse/SR-7648; we should write up a swift-evolution pitch/proposal at some point. (cc @moiseev)

(The code above is defined on FixedWidthInteger, which uses a similar shifting loop for its own generic integer conversions. Frustratingly, FixedWidthInteger is currently impossible to implement using only public API: it requires an underscored version of the single-word initializer, without providing a default implementation.)

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for writing that up!

@lorentey
Copy link
Member

lorentey commented May 9, 2018

@Azoy By a (happy?) accident, I pushed two commits directly on your branch instead of my own fork; they fix the FixedWidthInteger issue I noticed.

Provided the bots are in a cooperating mood, I want to re-do the tests to try reproducing the failure on the 32-bit Simulator -- I can't reproduce it myself with the latest changes.

@Azoy
Copy link
Member Author

Azoy commented May 9, 2018

@lorentey I actually fixed those in my commit last night!

@lorentey
Copy link
Member

lorentey commented May 9, 2018

@Azoy Nice!

Unless anyone spots an issue with the last round of changes, LGTM! We just need to wait for the bots to come back.

@stephentyrone
Copy link
Member

@lorentey Agree. Assuming tests pass, let's land this so people can start using it. We'll find the problems faster that way anyway =)

@airspeedswift
Copy link
Member

@swift-ci please test

@airspeedswift
Copy link
Member

(needs full test to get the simulators)

Copy link
Collaborator

@xwu xwu left a comment

Choose a reason for hiding this comment

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

Sorry to be late here. Some initial comments.

public static func random<T: RandomNumberGenerator>(
using generator: inout T
) -> Bool {
return (generator.next() >> 17) & 1 == 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

Question: why >> 17?

Copy link
Member

Choose a reason for hiding this comment

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

This isn't totally insane, because for (some) very weak RNGs middle bits have better randomness properties than low bits, but really no one should be using those ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Nate sent this in the initial pr:

For some random generators the low bits have higher levels of repetition than the higher bits do. Could we change this to (generator.next() >> 17) & 1 == 0?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Got it; seemed strange because 17 is pretty arbitrary. If we want to use high bits, Int(bitPattern: generator.next()) < 0 would be less mystifying, IMO.

Copy link
Member

Choose a reason for hiding this comment

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

@xwu you don't want the high bits either, those can also be weak. You really want some "middle" bits. This is worth a comment, though.

Copy link
Member

Choose a reason for hiding this comment

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

Go ahead, try to name a number more random than 17.

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, according to some cursory testing, the GKRandomSource types use 31 for the offset in nextBool() (i.e., the high bit, like @xwu suggested).

) {
let count = self.count
guard count > 1 else { return }
var amount = count
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: we don't need both let count and var amount in this method, it seems.

random = next()
} while random < range

return random % upperBound
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm concerned about this implementation here. If % upperBound is necessary, then we have modulo bias; if not, then we should not have this operation here.

Copy link
Member

Choose a reason for hiding this comment

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

This does not introduce modulo bias; it has already been accounted for discarding draws smaller than range. This is a standard technique of eliminating modulo bias while minimizing the expected number of bits that you need to draw from your source. It does require two non-constant modulus operations, so for most random sources it's preferable to use the other technique that I sketched out for performance reasons, but it is bias-free.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah yes, I didn't study the preceding lines in great detail. Agree that there's room for performance improvement.

/// The default instance of the `Random` random number generator.
public static var `default`: Random {
get { return Random() }
set { /* Discard */ }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does Random have to be a struct? If it's a final class, then we don't have to make this a static var and the setter can be deleted. As it is, I worry that this is a code smell; should we at least fatalError if the user attempts to use the setter?

Copy link
Member

Choose a reason for hiding this comment

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

The interface for using generators takes them inout to allow for value typed generators. This means you can't fatalError on the set because it will be called (if you put code in it... not if you don't hopefully :).

@lorentey
Copy link
Member

lorentey commented May 9, 2018

@swift-ci please test and merge

@natecook1000
Copy link
Member

@swift-ci Please test and merge

@Azoy
Copy link
Member Author

Azoy commented May 10, 2018

@natecook1000 the failure looks unrelated, could you test again?

@airspeedswift
Copy link
Member

@swift-ci please test macOS platform

@lorentey
Copy link
Member

This looks ready to merge 🎉

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