diff --git a/benchmark/single-source/ArrayAppend.swift b/benchmark/single-source/ArrayAppend.swift index 633d81eee297c..4e674271be023 100644 --- a/benchmark/single-source/ArrayAppend.swift +++ b/benchmark/single-source/ArrayAppend.swift @@ -14,31 +14,53 @@ import TestsUtils +let t: [BenchmarkCategory] = [.validation, .api, .Array] public let ArrayAppend = [ - BenchmarkInfo(name: "ArrayAppend", runFunction: run_ArrayAppend, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendArrayOfInt", runFunction: run_ArrayAppendArrayOfInt, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendAscii", runFunction: run_ArrayAppendAscii, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendAsciiSubstring", runFunction: run_ArrayAppendAsciiSubstring, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendFromGeneric", runFunction: run_ArrayAppendFromGeneric, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendGenericStructs", runFunction: run_ArrayAppendGenericStructs, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendLatin1", runFunction: run_ArrayAppendLatin1, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendLatin1Substring", runFunction: run_ArrayAppendLatin1Substring, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendLazyMap", runFunction: run_ArrayAppendLazyMap, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendOptionals", runFunction: run_ArrayAppendOptionals, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendRepeatCol", runFunction: run_ArrayAppendRepeatCol, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendReserved", runFunction: run_ArrayAppendReserved, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendSequence", runFunction: run_ArrayAppendSequence, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendStrings", runFunction: run_ArrayAppendStrings, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendToFromGeneric", runFunction: run_ArrayAppendToFromGeneric, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendToGeneric", runFunction: run_ArrayAppendToGeneric, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendUTF16", runFunction: run_ArrayAppendUTF16, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayAppendUTF16Substring", runFunction: run_ArrayAppendUTF16Substring, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayPlusEqualArrayOfInt", runFunction: run_ArrayPlusEqualArrayOfInt, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayPlusEqualFiveElementCollection", runFunction: run_ArrayPlusEqualFiveElementCollection, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayPlusEqualSingleElementCollection", runFunction: run_ArrayPlusEqualSingleElementCollection, tags: [.validation, .api, .Array]), - BenchmarkInfo(name: "ArrayPlusEqualThreeElements", runFunction: run_ArrayPlusEqualThreeElements, tags: [.validation, .api, .Array]), + BenchmarkInfo(name: "ArrayAppend", runFunction: run_ArrayAppend, tags: t), + BenchmarkInfo(name: "ArrayAppendArrayOfInt", runFunction: run_ArrayAppendArrayOfInt, tags: t, + setUpFunction: ones, tearDownFunction: releaseOnes), + BenchmarkInfo(name: "ArrayAppendAscii", runFunction: run_ArrayAppendAscii, tags: t), + BenchmarkInfo(name: "ArrayAppendAsciiSubstring", runFunction: run_ArrayAppendAsciiSubstring, tags: t), + BenchmarkInfo(name: "ArrayAppendFromGeneric", runFunction: run_ArrayAppendFromGeneric, tags: t, + setUpFunction: ones, tearDownFunction: releaseOnes), + BenchmarkInfo(name: "ArrayAppendGenericStructs", runFunction: run_ArrayAppendGenericStructs, tags: t, + setUpFunction: { otherStructs = Array(repeating: S(x: 3, y: 4.2), count: 10_000) }, + tearDownFunction: { otherStructs = nil } ), + BenchmarkInfo(name: "ArrayAppendLatin1", runFunction: run_ArrayAppendLatin1, tags: t), + BenchmarkInfo(name: "ArrayAppendLatin1Substring", runFunction: run_ArrayAppendLatin1Substring, tags: t), + BenchmarkInfo(name: "ArrayAppendLazyMap", runFunction: run_ArrayAppendLazyMap, tags: t, + setUpFunction: { blackHole(array) }), + BenchmarkInfo(name: "ArrayAppendOptionals", runFunction: run_ArrayAppendOptionals, tags: t, + setUpFunction: { otherOptionalOnes = Array(repeating: 1, count: 10_000) }, + tearDownFunction: { otherOptionalOnes = nil } ), + BenchmarkInfo(name: "ArrayAppendRepeatCol", runFunction: run_ArrayAppendRepeatCol, tags: t), + BenchmarkInfo(name: "ArrayAppendReserved", runFunction: run_ArrayAppendReserved, tags: t), + BenchmarkInfo(name: "ArrayAppendSequence", runFunction: run_ArrayAppendSequence, tags: t), + BenchmarkInfo(name: "ArrayAppendStrings", runFunction: run_ArrayAppendStrings, tags: t, + setUpFunction: { otherStrings = stride(from: 0, to: 10_000, by: 1).map { "\($0)" } }, + tearDownFunction: { otherStrings = nil } ), + BenchmarkInfo(name: "ArrayAppendToFromGeneric", runFunction: run_ArrayAppendToFromGeneric, tags: t, + setUpFunction: ones, tearDownFunction: releaseOnes), + BenchmarkInfo(name: "ArrayAppendToGeneric", runFunction: run_ArrayAppendToGeneric, tags: t, + setUpFunction: ones, tearDownFunction: releaseOnes), + BenchmarkInfo(name: "ArrayAppendUTF16", runFunction: run_ArrayAppendUTF16, tags: t), + BenchmarkInfo(name: "ArrayAppendUTF16Substring", runFunction: run_ArrayAppendUTF16Substring, tags: t), + BenchmarkInfo(name: "ArrayPlusEqualArrayOfInt", runFunction: run_ArrayPlusEqualArrayOfInt, tags: t, + setUpFunction: ones, tearDownFunction: releaseOnes), + BenchmarkInfo(name: "ArrayPlusEqualFiveElementCollection", runFunction: run_ArrayPlusEqualFiveElementCollection, tags: t), + BenchmarkInfo(name: "ArrayPlusEqualSingleElementCollection", runFunction: run_ArrayPlusEqualSingleElementCollection, tags: t), + BenchmarkInfo(name: "ArrayPlusEqualThreeElements", runFunction: run_ArrayPlusEqualThreeElements, tags: t), ] +var otherOnes: [Int]! +var otherOptionalOnes: [Int?]! +var otherStrings: [String]! +var otherStructs: [S]! +let array = Array(0..<10_000) + +func ones() { otherOnes = Array(repeating: 1, count: 10_000) } +func releaseOnes() { otherOnes = nil } + // Append single element @inline(never) public func run_ArrayAppend(_ N: Int) { @@ -67,10 +89,11 @@ public func run_ArrayAppendReserved(_ N: Int) { } // Append a sequence. Length of sequence unknown so -// can't pre-reserve capacity. +// can't pre-reserve capacity. @inline(never) public func run_ArrayAppendSequence(_ N: Int) { let seq = stride(from: 0, to: 10_000, by: 1) + for _ in 0.. { // can pre-reserve capacity. @inline(never) public func run_ArrayAppendGenericStructs(_ N: Int) { - let other = Array(repeating: S(x: 3, y: 4.2), count: 10_000) + let other: [S] = otherStructs + for _ in 0..]() + var nums = [S]() for _ in 0..<8 { nums += other } @@ -151,7 +178,7 @@ public func run_ArrayAppendGenericStructs(_ N: Int) { // can pre-reserve capacity. @inline(never) public func run_ArrayAppendOptionals(_ N: Int) { - let other: [Int?] = Array(repeating: 1, count: 10_000) + let other: [Int?] = otherOptionalOnes for _ in 0..(collection: inout R, sequence: S) +>(collection: inout R, sequence: S) where R.Element == S.Element { collection.append(contentsOf: sequence) } @inline(never) public func run_ArrayAppendToFromGeneric(_ N: Int) { - let other = Array(repeating: 1, count: 10_000) + let other: [Int] = otherOnes for _ in 0.. ArrayContainer { - return ArrayContainer() -} - @inline(never) public func run_ArrayInClass(_ N: Int) { - let a = getArrayContainer() + let a = ac! a.runLoop(N) } diff --git a/benchmark/single-source/DataBenchmarks.swift b/benchmark/single-source/DataBenchmarks.swift index 46b90ffc22e21..02c79fd52a7fd 100644 --- a/benchmark/single-source/DataBenchmarks.swift +++ b/benchmark/single-source/DataBenchmarks.swift @@ -41,6 +41,9 @@ public let DataBenchmarks = [ BenchmarkInfo(name: "DataAppendDataLargeToLarge", runFunction: run_AppendDataLargeToLarge, tags: [.validation, .api, .Data]), ] +let small = sampleData(.small) +let medium = sampleData(.medium) + enum SampleKind { case small case medium @@ -138,7 +141,6 @@ func sampleData(_ type: SampleKind) -> Data { case .string: return sampleString() case .immutableBacking: return sampleBridgedNSData() } - } func benchmark_AccessBytes(_ N: Int, _ data: Data) { @@ -228,7 +230,7 @@ func benchmark_AppendData(_ N: Int, _ lhs: Data, _ rhs: Data) { @inline(never) public func run_Subscript(_ N: Int) { - let data = sampleData(.medium) + let data = medium let index = 521 for _ in 1...10000*N { // Ensure that the compiler does not optimize away this call @@ -238,7 +240,7 @@ public func run_Subscript(_ N: Int) { @inline(never) public func run_Count(_ N: Int) { - let data = sampleData(.medium) + let data = medium for _ in 1...10000*N { // Ensure that the compiler does not optimize away this call blackHole(data.count) @@ -247,7 +249,7 @@ public func run_Count(_ N: Int) { @inline(never) public func run_SetCount(_ N: Int) { - let data = sampleData(.medium) + let data = medium let count = data.count + 100 var otherData = data let orig = data.count @@ -259,65 +261,65 @@ public func run_SetCount(_ N: Int) { @inline(never) public func run_AccessBytes(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_AccessBytes(N, data) } @inline(never) public func run_MutateBytes(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_MutateBytes(N, data) } @inline(never) public func run_CopyBytes(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_CopyBytes(N, data) } @inline(never) public func run_AppendBytes(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_AppendBytes(N, 809, data) } @inline(never) public func run_AppendArray(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_AppendArray(N, 809, data) } @inline(never) public func run_Reset(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_Reset(N, 431..<809, data) } @inline(never) public func run_ReplaceSmall(_ N: Int) { - let data = sampleData(.medium) - let replacement = sampleData(.small) + let data = medium + let replacement = small benchmark_Replace(N, 431..<809, data, replacement) } @inline(never) public func run_ReplaceMedium(_ N: Int) { - let data = sampleData(.medium) - let replacement = sampleData(.medium) + let data = medium + let replacement = medium benchmark_Replace(N, 431..<809, data, replacement) } @inline(never) public func run_ReplaceLarge(_ N: Int) { - let data = sampleData(.medium) + let data = medium let replacement = sampleData(.large) benchmark_Replace(N, 431..<809, data, replacement) } @inline(never) public func run_ReplaceSmallBuffer(_ N: Int) { - let data = sampleData(.medium) - let replacement = sampleData(.small) + let data = medium + let replacement = small let sz = replacement.count replacement.withUnsafeBytes { (ptr: UnsafePointer) in benchmark_ReplaceBuffer(N, 431..<809, data, UnsafeBufferPointer(start: ptr, count: sz)) @@ -326,8 +328,8 @@ public func run_ReplaceSmallBuffer(_ N: Int) { @inline(never) public func run_ReplaceMediumBuffer(_ N: Int) { - let data = sampleData(.medium) - let replacement = sampleData(.medium) + let data = medium + let replacement = medium let sz = replacement.count replacement.withUnsafeBytes { (ptr: UnsafePointer) in benchmark_ReplaceBuffer(N, 431..<809, data, UnsafeBufferPointer(start: ptr, count: sz)) @@ -336,7 +338,7 @@ public func run_ReplaceMediumBuffer(_ N: Int) { @inline(never) public func run_ReplaceLargeBuffer(_ N: Int) { - let data = sampleData(.medium) + let data = medium let replacement = sampleData(.large) let sz = replacement.count replacement.withUnsafeBytes { (ptr: UnsafePointer) in @@ -346,62 +348,62 @@ public func run_ReplaceLargeBuffer(_ N: Int) { @inline(never) public func run_AppendSequence(_ N: Int) { - let data = sampleData(.medium) + let data = medium benchmark_AppendSequence(N, 809, data) } @inline(never) public func run_AppendDataSmallToSmall(_ N: Int) { - let data = sampleData(.small) - let other = sampleData(.small) + let data = small + let other = small benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataSmallToMedium(_ N: Int) { - let data = sampleData(.medium) - let other = sampleData(.small) + let data = medium + let other = small benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataSmallToLarge(_ N: Int) { let data = sampleData(.large) - let other = sampleData(.small) + let other = small benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataMediumToSmall(_ N: Int) { - let data = sampleData(.small) - let other = sampleData(.medium) + let data = small + let other = medium benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataMediumToMedium(_ N: Int) { - let data = sampleData(.medium) - let other = sampleData(.medium) + let data = medium + let other = medium benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataMediumToLarge(_ N: Int) { let data = sampleData(.large) - let other = sampleData(.medium) + let other = medium benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataLargeToSmall(_ N: Int) { - let data = sampleData(.small) + let data = small let other = sampleData(.large) benchmark_AppendData(N, data, other) } @inline(never) public func run_AppendDataLargeToMedium(_ N: Int) { - let data = sampleData(.medium) + let data = medium let other = sampleData(.large) benchmark_AppendData(N, data, other) } diff --git a/benchmark/single-source/DictTest.swift b/benchmark/single-source/DictTest.swift index bf4f10e60fab3..e730bdad8234e 100644 --- a/benchmark/single-source/DictTest.swift +++ b/benchmark/single-source/DictTest.swift @@ -14,13 +14,16 @@ import TestsUtils public let Dictionary = [ - BenchmarkInfo(name: "Dictionary", runFunction: run_Dictionary, tags: [.validation, .api, .Dictionary]), - BenchmarkInfo(name: "DictionaryOfObjects", runFunction: run_DictionaryOfObjects, tags: [.validation, .api, .Dictionary]), + BenchmarkInfo(name: "Dictionary", runFunction: run_Dictionary, + tags: [.validation, .api, .Dictionary], + setUpFunction: { blackHole(half) }), + BenchmarkInfo(name: "DictionaryOfObjects", + runFunction: run_DictionaryOfObjects, + tags: [.validation, .api, .Dictionary], + setUpFunction: { blackHole(halfObjects) }), ] -@inline(never) -public func run_Dictionary(scale: Int) { - let Input = [ +let text = [ // Text from http://en.wikipedia.org/wiki/Hash_table "hash", "table", "in", "computing", "a", "hash", "table", "also", "hash", "map", "is", @@ -118,31 +121,37 @@ public func run_Dictionary(scale: Int) { "entries", "for", "some", "sets", "of", "keys" ] - var Dict: Dictionary = [:] +// Fill the dictionary with words from the first half of the text +let half: Dictionary = { + var dict: Dictionary = [:] + for i in 0 ..< text.count/2 { + let word = text[i] + dict[word] = true + } + return dict +}() + +@inline(never) +public func run_Dictionary(scale: Int) { + var dict: Dictionary = [:] let N = 5*scale // Check performance of filling the dictionary: for _ in 1...N { - Dict = [:] - for word in Input { - Dict[word] = true + dict = [:] + for word in text { + dict[word] = true } } - CheckResults(Dict.count == 270) + CheckResults(dict.count == 270) // Check performance of searching in the dictionary: - // Fill the dictionary with words from the first half of the text - Dict = [:] - for i in 0 ..< Input.count/2 { - let word = Input[i] - Dict[word] = true - } - + dict = half // Count number of words from the first half in the entire text var count = 0 for _ in 1...N { - for word in Input { - if Dict[word] != nil { + for word in text { + if dict[word] != nil { count += 1 } } @@ -166,131 +175,37 @@ class Box : Hashable { } } +// Fill the dictionary with words from the first half of the text +let halfObjects: Dictionary, Box> = { + var dict: Dictionary, Box> = [:] + for i in 0 ..< text.count/2 { + let word = text[i] + dict[Box(word)] = Box(true) + } + return dict +}() + @inline(never) public func run_DictionaryOfObjects(scale: Int) { - let Input = [ - // Text from http://en.wikipedia.org/wiki/Hash_table - "hash", "table", - "in", "computing", "a", "hash", "table", "also", "hash", "map", "is", - "a", "data", "structure", "used", "to", "implement", "an", "associative", - "array", "a", "structure", "that", "can", "map", "keys", "to", "values", - "a", "hash", "table", "uses", "a", "hash", "function", "to", "compute", - "an", "index", "into", "an", "array", "of", "buckets", "or", "slots", - "from", "which", "the", "correct", "value", "can", "be", "found", - "ideally", "the", "hash", "function", "will", "assign", "each", "key", - "to", "a", "unique", "bucket", "but", "this", "situation", "is", - "rarely", "achievable", "in", "practice", "usually", "some", "keys", - "will", "hash", "to", "the", "same", "bucket", "instead", "most", "hash", - "table", "designs", "assume", "that", "hash", "collisions", "different", - "keys", "that", "are", "assigned", "by", "the", "hash", "function", "to", - "the", "same", "bucket", "will", "occur", "and", "must", "be", - "accommodated", "in", "some", "way", "in", "a", "well", "dimensioned", - "hash", "table", "the", "average", "cost", "number", "of", - "instructions", "for", "each", "lookup", "is", "independent", "of", - "the", "number", "of", "elements", "stored", "in", "the", "table", - "many", "hash", "table", "designs", "also", "allow", "arbitrary", - "insertions", "and", "deletions", "of", "key", "value", "pairs", "at", - "amortized", "constant", "average", "cost", "per", "operation", "in", - "many", "situations", "hash", "tables", "turn", "out", "to", "be", - "more", "efficient", "than", "search", "trees", "or", "any", "other", - "table", "lookup", "structure", "for", "this", "reason", "they", "are", - "widely", "used", "in", "many", "kinds", "of", "computer", "software", - "particularly", "for", "associative", "arrays", "database", "indexing", - "caches", "and", "sets", - - "hashing", - "the", "idea", "of", "hashing", "is", "to", "distribute", "the", - "entries", "key", "value", "pairs", "across", "an", "array", "of", - "buckets", "given", "a", "key", "the", "algorithm", "computes", "an", - "index", "that", "suggests", "where", "the", "entry", "can", "be", - "found", "index", "f", "key", "array", "size", "often", "this", "is", - "done", "in", "two", "steps", "hash", "hashfunc", "key", "index", "hash", - "array", "size", "in", "this", "method", "the", "hash", "is", - "independent", "of", "the", "array", "size", "and", "it", "is", "then", - "reduced", "to", "an", "index", "a", "number", "between", "and", "array", - "size", "using", "the", "modulus", "operator", "in", "the", "case", - "that", "the", "array", "size", "is", "a", "power", "of", "two", "the", - "remainder", "operation", "is", "reduced", "to", "masking", "which", - "improves", "speed", "but", "can", "increase", "problems", "with", "a", - "poor", "hash", "function", - - "choosing", "a", "good", "hash", "function", - "a", "good", "hash", "function", "and", "implementation", "algorithm", - "are", "essential", "for", "good", "hash", "table", "performance", "but", - "may", "be", "difficult", "to", "achieve", "a", "basic", "requirement", - "is", "that", "the", "function", "should", "provide", "a", "uniform", - "distribution", "of", "hash", "values", "a", "non", "uniform", - "distribution", "increases", "the", "number", "of", "collisions", "and", - "the", "cost", "of", "resolving", "them", "uniformity", "is", - "sometimes", "difficult", "to", "ensure", "by", "design", "but", "may", - "be", "evaluated", "empirically", "using", "statistical", "tests", "e", - "g", "a", "pearson", "s", "chi", "squared", "test", "for", "discrete", - "uniform", "distributions", "the", "distribution", "needs", "to", "be", - "uniform", "only", "for", "table", "sizes", "that", "occur", "in", "the", - "application", "in", "particular", "if", "one", "uses", "dynamic", - "resizing", "with", "exact", "doubling", "and", "halving", "of", "the", - "table", "size", "s", "then", "the", "hash", "function", "needs", "to", - "be", "uniform", "only", "when", "s", "is", "a", "power", "of", "two", - "on", "the", "other", "hand", "some", "hashing", "algorithms", "provide", - "uniform", "hashes", "only", "when", "s", "is", "a", "prime", "number", - "for", "open", "addressing", "schemes", "the", "hash", "function", - "should", "also", "avoid", "clustering", "the", "mapping", "of", "two", - "or", "more", "keys", "to", "consecutive", "slots", "such", "clustering", - "may", "cause", "the", "lookup", "cost", "to", "skyrocket", "even", "if", - "the", "load", "factor", "is", "low", "and", "collisions", "are", - "infrequent", "the", "popular", "multiplicative", "hash", "3", "is", - "claimed", "to", "have", "particularly", "poor", "clustering", - "behavior", "cryptographic", "hash", "functions", "are", "believed", - "to", "provide", "good", "hash", "functions", "for", "any", "table", - "size", "s", "either", "by", "modulo", "reduction", "or", "by", "bit", - "masking", "they", "may", "also", "be", "appropriate", "if", "there", - "is", "a", "risk", "of", "malicious", "users", "trying", "to", - "sabotage", "a", "network", "service", "by", "submitting", "requests", - "designed", "to", "generate", "a", "large", "number", "of", "collisions", - "in", "the", "server", "s", "hash", "tables", "however", "the", "risk", - "of", "sabotage", "can", "also", "be", "avoided", "by", "cheaper", - "methods", "such", "as", "applying", "a", "secret", "salt", "to", "the", - "data", "or", "using", "a", "universal", "hash", "function", - - "perfect", "hash", "function", - "if", "all", "keys", "are", "known", "ahead", "of", "time", "a", - "perfect", "hash", "function", "can", "be", "used", "to", "create", "a", - "perfect", "hash", "table", "that", "has", "no", "collisions", "if", - "minimal", "perfect", "hashing", "is", "used", "every", "location", "in", - "the", "hash", "table", "can", "be", "used", "as", "well", "perfect", - "hashing", "allows", "for", "constant", "time", "lookups", "in", "the", - "worst", "case", "this", "is", "in", "contrast", "to", "most", - "chaining", "and", "open", "addressing", "methods", "where", "the", - "time", "for", "lookup", "is", "low", "on", "average", "but", "may", - "be", "very", "large", "proportional", "to", "the", "number", "of", - "entries", "for", "some", "sets", "of", "keys" - ] - - var Dict: Dictionary, Box> = [:] + var dict: Dictionary, Box> = [:] let N = 5*scale // Check performance of filling the dictionary: for _ in 1...N { - Dict = [:] - for word in Input { - Dict[Box(word)] = Box(true) + dict = [:] + for word in text { + dict[Box(word)] = Box(true) } } - CheckResults(Dict.count == 270) + CheckResults(dict.count == 270) // Check performance of searching in the dictionary: - // Fill the dictionary with words from the first half of the text - Dict = [:] - for i in 0 ..< Input.count/2 { - let word = Input[i] - Dict[Box(word)] = Box(true) - } - + dict = halfObjects // Count number of words from the first half in the entire text var count = 0 for _ in 1...N { - for word in Input { - if Dict[Box(word)] != nil { + for word in text { + if dict[Box(word)] != nil { count += 1 } } diff --git a/benchmark/single-source/DropFirst.swift b/benchmark/single-source/DropFirst.swift index 9e28c427cdace..bae534c7b7909 100644 --- a/benchmark/single-source/DropFirst.swift +++ b/benchmark/single-source/DropFirst.swift @@ -22,7 +22,7 @@ let sequenceCount = 4096 let dropCount = 1024 let suffixCount = sequenceCount - dropCount let sumCount = suffixCount * (2 * sequenceCount - suffixCount - 1) / 2 - +let array: [Int] = Array(0.. Data { +let data: Data = { var data = Data(count: 16 * 1024) let n = data.count data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer) -> () in @@ -28,13 +28,11 @@ func generateData() -> Data { } } return data -} +}() @inline(never) public func run_IterateData(_ N: Int) { - let data = generateData() - - for _ in 0...10*N { + for _ in 1...10*N { _ = data.reduce(0, &+) } } diff --git a/benchmark/single-source/MapReduce.swift b/benchmark/single-source/MapReduce.swift index c8525781f2b5d..d232fc0651d5a 100644 --- a/benchmark/single-source/MapReduce.swift +++ b/benchmark/single-source/MapReduce.swift @@ -17,8 +17,14 @@ public let MapReduce = [ BenchmarkInfo(name: "MapReduce", runFunction: run_MapReduce, tags: [.validation, .algorithm]), BenchmarkInfo(name: "MapReduceAnyCollection", runFunction: run_MapReduceAnyCollection, tags: [.validation, .algorithm]), BenchmarkInfo(name: "MapReduceAnyCollectionShort", runFunction: run_MapReduceAnyCollectionShort, tags: [.validation, .algorithm]), - BenchmarkInfo(name: "MapReduceClass", runFunction: run_MapReduceClass, tags: [.validation, .algorithm]), - BenchmarkInfo(name: "MapReduceClassShort", runFunction: run_MapReduceClassShort, tags: [.validation, .algorithm]), + BenchmarkInfo(name: "MapReduceClass2", runFunction: run_MapReduceClass, tags: [.validation, .algorithm], + setUpFunction: { boxedNumbers(1000) }, tearDownFunction: releaseDecimals), + BenchmarkInfo(name: "MapReduceClassShort2", runFunction: run_MapReduceClassShort, tags: [.validation, .algorithm], + setUpFunction: { boxedNumbers(10) }, tearDownFunction: releaseDecimals), + BenchmarkInfo(name: "MapReduceNSDecimalNumber", runFunction: run_MapReduceNSDecimalNumber, tags: [.validation, .algorithm], + setUpFunction: { decimals(1000) }, tearDownFunction: releaseDecimals), + BenchmarkInfo(name: "MapReduceNSDecimalNumberShort", runFunction: run_MapReduceNSDecimalNumberShort, tags: [.validation, .algorithm], + setUpFunction: { decimals(10) }, tearDownFunction: releaseDecimals), BenchmarkInfo(name: "MapReduceLazyCollection", runFunction: run_MapReduceLazyCollection, tags: [.validation, .algorithm]), BenchmarkInfo(name: "MapReduceLazyCollectionShort", runFunction: run_MapReduceLazyCollectionShort, tags: [.validation, .algorithm]), BenchmarkInfo(name: "MapReduceLazySequence", runFunction: run_MapReduceLazySequence, tags: [.validation, .algorithm]), @@ -28,6 +34,26 @@ public let MapReduce = [ BenchmarkInfo(name: "MapReduceString", runFunction: run_MapReduceString, tags: [.validation, .algorithm, .String]), ] +#if _runtime(_ObjC) +var decimals : [NSDecimalNumber]! +func decimals(_ n: Int) { + decimals = (0.. Bool { @inline(never) public func run_Phonebook(_ N: Int) { - // The list of names in the phonebook. - var Names : [Record] = [] - for first in words { - for last in words { - Names.append(Record(first, last)) - } - } for _ in 1...N { - var t = Names + var t = names t.sort() } } diff --git a/benchmark/single-source/PolymorphicCalls.swift b/benchmark/single-source/PolymorphicCalls.swift index 64aedae9fd399..cb688ce0f1920 100644 --- a/benchmark/single-source/PolymorphicCalls.swift +++ b/benchmark/single-source/PolymorphicCalls.swift @@ -308,32 +308,22 @@ func test(_ a3_c3: A3, _ a3_d3: A3, _ a3_e3: A3, _ a3_f3: A3, _ UPTO: Int) -> In return cnt } - +let a = A(b:B(x:1)) +let a1 = A1(b:C1(x:1)) +let a2 = A2(b:C2(x:1)) +let a2_c2 = A2(b:C2(x:1)) +let a2_d2 = A2(b:D2(x:1)) +let a3_c3 = A3(b:C3(x:1)) +let a3_d3 = A3(b:D3(x:1)) +let a3_e3 = A3(b:E3(x:1)) +let a3_f3 = A3(b:F3(x:1)) @inline(never) public func run_PolymorphicCalls(_ N:Int) { - let UPTO = 10000 * N - - let a = A(b:B(x:1)) + let UPTO = 10_000 * N _ = test(a, UPTO) - - let a1 = A1(b:C1(x:1)) - _ = test(a1, UPTO) - - let a2 = A2(b:C2(x:1)) - _ = test(a2, UPTO) - - let a2_c2 = A2(b:C2(x:1)) - let a2_d2 = A2(b:D2(x:1)) - _ = test(a2_c2, a2_d2, UPTO) - - let a3_c3 = A3(b:C3(x:1)) - let a3_d3 = A3(b:D3(x:1)) - let a3_e3 = A3(b:E3(x:1)) - let a3_f3 = A3(b:F3(x:1)) - _ = test(a3_c3, a3_d3, a3_e3, a3_f3, UPTO) } diff --git a/benchmark/single-source/Prefix.swift b/benchmark/single-source/Prefix.swift index 00e6b800d7b33..b442e710a693a 100644 --- a/benchmark/single-source/Prefix.swift +++ b/benchmark/single-source/Prefix.swift @@ -21,6 +21,7 @@ import TestsUtils let sequenceCount = 4096 let prefixCount = sequenceCount - 1024 let sumCount = prefixCount * (prefixCount - 1) / 2 +let array: [Int] = Array(0.. UInt64 { state = 2862933555777941757 &* state &+ 3037000493 return state } } -var numbersDef: [Int]! = Array(0...10_000) -var numbersLCG: [Int]! = Array(0...100_000) +var numbersDef: [Int] = Array(0...10_000) +var numbersLCG: [Int] = Array(0...100_000) @inline(never) public func run_RandomShuffleDef(_ N: Int) { - var numbers: [Int] = numbersDef for _ in 0 ..< N { - numbers.shuffle() - blackHole(numbers.first!) + numbersDef.shuffle() + blackHole(numbersDef.first!) } } @inline(never) public func run_RandomShuffleLCG(_ N: Int) { - var numbers: [Int] = numbersLCG var generator = LCRNG(seed: 0) for _ in 0 ..< N { - numbers.shuffle(using: &generator) - blackHole(numbers.first!) + numbersLCG.shuffle(using: &generator) + blackHole(numbersLCG.first!) } } diff --git a/benchmark/single-source/SortStrings.swift b/benchmark/single-source/SortStrings.swift index 6c0796054d6cb..3baaed2ab00d3 100644 --- a/benchmark/single-source/SortStrings.swift +++ b/benchmark/single-source/SortStrings.swift @@ -13,12 +13,16 @@ import TestsUtils // Sort an array of strings using an explicit sort predicate. public let SortStrings = [ - BenchmarkInfo(name: "SortSortedStrings", runFunction: run_SortSortedStrings, tags: [.validation, .api, .algorithm, .String]), - BenchmarkInfo(name: "SortStrings", runFunction: run_SortStrings, tags: [.validation, .api, .algorithm, .String]), - BenchmarkInfo(name: "SortStringsUnicode", runFunction: run_SortStringsUnicode, tags: [.validation, .api, .algorithm, .String]), + BenchmarkInfo(name: "SortSortedStrings", runFunction: run_SortSortedStrings, tags: [.validation, .api, .algorithm, .String], + setUpFunction: { blackHole(sortedWords) }), + BenchmarkInfo(name: "SortStrings", runFunction: run_SortStrings, tags: [.validation, .api, .algorithm, .String], + setUpFunction: { blackHole(words) }), + BenchmarkInfo(name: "SortStringsUnicode", runFunction: run_SortStringsUnicode, tags: [.validation, .api, .algorithm, .String], + setUpFunction: { blackHole(unicodeWords) }), ] -var stringBenchmarkWords: [String] = [ +let sortedWords = words.sorted() +let words: [String] = [ "woodshed", "lakism", "gastroperiodynia", @@ -1032,18 +1036,17 @@ func benchSortStrings(_ words: [String]) { public func run_SortStrings(_ N: Int) { for _ in 1...5*N { - benchSortStrings(stringBenchmarkWords) + benchSortStrings(words) } } public func run_SortSortedStrings(_ N: Int) { - let sortedBenchmarkWords = stringBenchmarkWords.sorted() for _ in 1...5*N { - benchSortStrings(sortedBenchmarkWords) + benchSortStrings(sortedWords) } } -var stringBenchmarkWordsUnicode: [String] = [ +var unicodeWords: [String] = [ "❄️woodshed", "❄️lakism", "❄️gastroperiodynia", @@ -2048,6 +2051,6 @@ var stringBenchmarkWordsUnicode: [String] = [ public func run_SortStringsUnicode(_ N: Int) { for _ in 1...5*N { - benchSortStrings(stringBenchmarkWordsUnicode) + benchSortStrings(unicodeWords) } } diff --git a/benchmark/single-source/Substring.swift b/benchmark/single-source/Substring.swift index c529d086c5bfc..bd3aab887be8c 100644 --- a/benchmark/single-source/Substring.swift +++ b/benchmark/single-source/Substring.swift @@ -21,7 +21,8 @@ public let SubstringTest = [ BenchmarkInfo(name: "LessSubstringSubstringGenericComparable", runFunction: run_LessSubstringSubstringGenericComparable, tags: [.validation, .api, .String]), BenchmarkInfo(name: "StringFromLongWholeSubstring", runFunction: run_StringFromLongWholeSubstring, tags: [.validation, .api, .String]), BenchmarkInfo(name: "StringFromLongWholeSubstringGeneric", runFunction: run_StringFromLongWholeSubstringGeneric, tags: [.validation, .api, .String]), - BenchmarkInfo(name: "SubstringComparable", runFunction: run_SubstringComparable, tags: [.validation, .api, .String]), + BenchmarkInfo(name: "SubstringComparable", runFunction: run_SubstringComparable, tags: [.validation, .api, .String], + setUpFunction: { blackHole(_comparison) }), BenchmarkInfo(name: "SubstringEqualString", runFunction: run_SubstringEqualString, tags: [.validation, .api, .String]), BenchmarkInfo(name: "SubstringEquatable", runFunction: run_SubstringEquatable, tags: [.validation, .api, .String]), BenchmarkInfo(name: "SubstringFromLongString", runFunction: run_SubstringFromLongString, tags: [.validation, .api, .String]), @@ -79,7 +80,7 @@ private func equivalentWithDistinctBuffers() -> (String, Substring) { var s0 = longWide withUnsafeMutablePointer(to: &s0) { blackHole($0) } s0 += "!" - + // These two should be equal but with distinct buffers, both refcounted. let a = Substring(s0).dropFirst() let b = String(a) @@ -226,12 +227,13 @@ public func run_SubstringEqualString(_ N: Int) { CheckResults(count == 2*N*500) } +let _substrings = "pen,pineapple,apple,pen,✒️,🍍,🍏,✒️".split(separator: ",") +let _comparison = _substrings + ["PPAP"] + @inline(never) public func run_SubstringComparable(_ N: Int) { - var string = "pen,pineapple,apple,pen" - string += ",✒️,🍍,🍏,✒️" - let substrings = string.split(separator: ",") - let comparison = substrings + ["PPAP"] + let substrings = _substrings // without this alias, there was 25% slowdown + let comparison = _comparison // due to increased retain/release traffic 🤷‍‍ var count = 0 for _ in 1...N*500 { if substrings.lexicographicallyPrecedes(comparison) { diff --git a/benchmark/single-source/Suffix.swift b/benchmark/single-source/Suffix.swift index ace24f65a1cba..ae44759057fb9 100644 --- a/benchmark/single-source/Suffix.swift +++ b/benchmark/single-source/Suffix.swift @@ -21,12 +21,13 @@ import TestsUtils let sequenceCount = 4096 let suffixCount = 1024 let sumCount = suffixCount * (2 * sequenceCount - suffixCount - 1) / 2 +let array: [Int] = Array(0..