Skip to content

Commit 1b8a489

Browse files
authoredApr 27, 2018
Merge pull request #16157 from lorentey/modernize-hashing-in-benchmarks
[benchmark] Replace hashValue implementations with hash(into:)
2 parents 95a3a43 + ec91f6b commit 1b8a489

18 files changed

+205
-38
lines changed
 

‎benchmark/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ set(SWIFT_BENCH_MODULES
6363
single-source/DictTest2
6464
single-source/DictTest3
6565
single-source/DictTest4
66+
single-source/DictTest4Legacy
6667
single-source/DictionaryBridge
6768
single-source/DictionaryCopy
6869
single-source/DictionaryGroup

‎benchmark/multi-source/PrimsSplit/Prims.swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,9 @@ func ==(lhs: Edge, rhs: Edge) -> Bool {
176176
}
177177

178178
extension Edge : Hashable {
179-
var hashValue: Int {
180-
get {
181-
return start.hashValue ^ end.hashValue
182-
}
179+
func hash(into hasher: inout Hasher) {
180+
hasher.combine(start)
181+
hasher.combine(end)
183182
}
184183
}
185184

‎benchmark/single-source/AnyHashableWithAClass.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ class TestHashableBase : Hashable {
3333
init(_ value: Int) {
3434
self.value = value
3535
}
36-
var hashValue: Int {
37-
return value
36+
37+
func hash(into hasher: inout Hasher) {
38+
hasher.combine(value)
3839
}
40+
3941
static func == (
4042
lhs: TestHashableBase,
4143
rhs: TestHashableBase

‎benchmark/single-source/BinaryFloatingPointConversionFromBinaryInteger.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ extension MockBinaryInteger : Comparable {
5959
}
6060

6161
extension MockBinaryInteger : Hashable {
62-
var hashValue: Int {
63-
return _value.hashValue
62+
func hash(into hasher: inout Hasher) {
63+
hasher.combine(_value)
6464
}
6565
}
6666

‎benchmark/single-source/DictTest.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ class Box<T : Hashable> : Hashable {
157157
value = v
158158
}
159159

160-
var hashValue: Int {
161-
return value.hashValue
160+
func hash(into hasher: inout Hasher) {
161+
hasher.combine(value)
162162
}
163163

164164
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/DictTest2.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ class Box<T : Hashable> : Hashable {
4949
value = v
5050
}
5151

52-
var hashValue: Int {
53-
return value.hashValue
52+
func hash(into hasher: inout Hasher) {
53+
hasher.combine(value)
5454
}
5555

5656
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/DictTest3.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ class Box<T : Hashable> : Hashable {
5656
value = v
5757
}
5858

59-
var hashValue: Int {
60-
return value.hashValue
59+
func hash(into hasher: inout Hasher) {
60+
hasher.combine(value)
6161
}
62-
62+
6363
static func ==(lhs: Box, rhs: Box) -> Bool {
6464
return lhs.value == rhs.value
6565
}

‎benchmark/single-source/DictTest4.swift

+11-5
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ import TestsUtils
1616
// exercising the default hash compression function.
1717

1818
public let Dictionary4 = [
19-
BenchmarkInfo(name: "Dictionary4", runFunction: run_Dictionary4, tags: [.validation, .api, .Dictionary]),
20-
BenchmarkInfo(name: "Dictionary4OfObjects", runFunction: run_Dictionary4OfObjects, tags: [.validation, .api, .Dictionary]),
19+
BenchmarkInfo(
20+
name: "Dictionary4",
21+
runFunction: run_Dictionary4,
22+
tags: [.validation, .api, .Dictionary]),
23+
BenchmarkInfo(
24+
name: "Dictionary4OfObjects",
25+
runFunction: run_Dictionary4OfObjects,
26+
tags: [.validation, .api, .Dictionary]),
2127
]
2228

2329
struct LargeKey: Hashable {
@@ -85,10 +91,10 @@ class Box<T : Hashable> : Hashable {
8591
value = v
8692
}
8793

88-
var hashValue: Int {
89-
return value.hashValue
94+
func hash(into hasher: inout Hasher) {
95+
hasher.combine(value)
9096
}
91-
97+
9298
static func ==(lhs: Box, rhs: Box) -> Bool {
9399
return lhs.value == rhs.value
94100
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//===--- DictTest4.swift --------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import TestsUtils
14+
15+
// This benchmark mostly measures lookups in dictionaries with complex keys,
16+
// using the legacy hashValue API.
17+
18+
public let Dictionary4Legacy = [
19+
BenchmarkInfo(
20+
name: "Dictionary4Legacy",
21+
runFunction: run_Dictionary4Legacy,
22+
tags: [.validation, .api, .Dictionary]),
23+
BenchmarkInfo(
24+
name: "Dictionary4OfObjectsLegacy",
25+
runFunction: run_Dictionary4OfObjectsLegacy,
26+
tags: [.validation, .api, .Dictionary]),
27+
]
28+
29+
extension Int {
30+
mutating func combine(_ value: Int) {
31+
self = 16777619 &* self ^ value
32+
}
33+
}
34+
35+
struct LargeKey: Hashable {
36+
let i: Int
37+
let j: Int
38+
let k: Double
39+
let l: UInt32
40+
let m: Bool
41+
let n: Bool
42+
let o: Bool
43+
let p: Bool
44+
let q: Bool
45+
46+
var hashValue: Int {
47+
var hash = i.hashValue
48+
hash.combine(j.hashValue)
49+
hash.combine(k.hashValue)
50+
hash.combine(l.hashValue)
51+
hash.combine(m.hashValue)
52+
hash.combine(n.hashValue)
53+
hash.combine(o.hashValue)
54+
hash.combine(p.hashValue)
55+
hash.combine(q.hashValue)
56+
return hash
57+
}
58+
59+
init(_ value: Int) {
60+
self.i = value
61+
self.j = 2 * value
62+
self.k = Double(value) / 7
63+
self.l = UInt32(truncatingIfNeeded: value)
64+
self.m = value & 1 == 0
65+
self.n = value & 2 == 0
66+
self.o = value & 4 == 0
67+
self.p = value & 8 == 0
68+
self.q = value & 16 == 0
69+
}
70+
}
71+
72+
@inline(never)
73+
public func run_Dictionary4Legacy(_ N: Int) {
74+
let size1 = 100
75+
let reps = 20
76+
let ref_result = "1 99 \(reps) \(reps * 99)"
77+
var hash1 = [LargeKey: Int]()
78+
var hash2 = [LargeKey: Int]()
79+
var res = ""
80+
81+
for _ in 1...N {
82+
// Test insertions
83+
hash1 = [:]
84+
for i in 0..<size1 {
85+
hash1[LargeKey(i)] = i
86+
}
87+
88+
hash2 = hash1
89+
90+
// Test lookups & value replacement
91+
for _ in 1..<reps {
92+
for (k, v) in hash1 {
93+
hash2[k] = hash2[k]! + v
94+
}
95+
}
96+
97+
res = "\(hash1[LargeKey(1)]!) \(hash1[LargeKey(99)]!)" +
98+
" \(hash2[LargeKey(1)]!) \(hash2[LargeKey(99)]!)"
99+
if res != ref_result {
100+
break
101+
}
102+
}
103+
CheckResults(res == ref_result)
104+
}
105+
106+
class Box<T : Hashable> : Hashable {
107+
var value: T
108+
109+
init(_ v: T) {
110+
value = v
111+
}
112+
113+
func hash(into hasher: inout Hasher) {
114+
hasher.combine(value)
115+
}
116+
117+
var hashValue: Int {
118+
return value.hashValue
119+
}
120+
121+
static func ==(lhs: Box, rhs: Box) -> Bool {
122+
return lhs.value == rhs.value
123+
}
124+
}
125+
126+
@inline(never)
127+
public func run_Dictionary4OfObjectsLegacy(_ N: Int) {
128+
let size1 = 100
129+
let reps = 20
130+
let ref_result = "1 99 \(reps) \(reps * 99)"
131+
var hash1 = [Box<LargeKey>: Int]()
132+
var hash2 = [Box<LargeKey>: Int]()
133+
var res = ""
134+
135+
for _ in 1...N {
136+
// Test insertions
137+
hash1 = [:]
138+
for i in 0..<size1 {
139+
hash1[Box(LargeKey(i))] = i
140+
}
141+
142+
hash2 = hash1
143+
144+
// Test lookups & value replacement
145+
for _ in 1..<reps {
146+
for (k, v) in hash1 {
147+
hash2[k] = hash2[k]! + v
148+
}
149+
}
150+
151+
res = "\(hash1[Box(LargeKey(1))]!) \(hash1[Box(LargeKey(99))]!)" +
152+
" \(hash2[Box(LargeKey(1))]!) \(hash2[Box(LargeKey(99))]!)"
153+
if res != ref_result {
154+
break
155+
}
156+
}
157+
CheckResults(res == ref_result)
158+
}

‎benchmark/single-source/DictionaryGroup.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ class Box<T : Hashable> : Hashable {
3636
value = v
3737
}
3838

39-
var hashValue: Int {
40-
return value.hashValue
39+
func hash(into hasher: inout Hasher) {
40+
hasher.combine(value)
4141
}
4242

4343
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/DictionaryRemove.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ class Box<T : Hashable> : Hashable {
5252
value = v
5353
}
5454

55-
var hashValue: Int {
56-
return value.hashValue
55+
func hash(into hasher: inout Hasher) {
56+
hasher.combine(value)
5757
}
5858

5959
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/DictionarySubscriptDefault.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ class Box<T : Hashable> : Hashable, P {
8484
value = v
8585
}
8686

87-
var hashValue: Int {
88-
return value.hashValue
87+
func hash(into hasher: inout Hasher) {
88+
hasher.combine(value)
8989
}
9090

9191
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/DictionarySwap.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ class Box<T : Hashable> : Hashable {
8383
value = v
8484
}
8585

86-
var hashValue: Int {
87-
return value.hashValue
86+
func hash(into hasher: inout Hasher) {
87+
hasher.combine(value)
8888
}
8989

9090
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/Prims.swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,9 @@ func ==(lhs: Edge, rhs: Edge) -> Bool {
181181
}
182182

183183
extension Edge : Hashable {
184-
var hashValue: Int {
185-
get {
186-
return start.hashValue ^ end.hashValue
187-
}
184+
func hash(into hasher: inout Hasher) {
185+
hasher.combine(start)
186+
hasher.combine(end)
188187
}
189188
}
190189

‎benchmark/single-source/RGBHistogram.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ class Box<T : Hashable> : Hashable {
124124
value = v
125125
}
126126

127-
var hashValue: Int {
128-
return value.hashValue
127+
func hash(into hasher: inout Hasher) {
128+
hasher.combine(value)
129129
}
130130

131131
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/single-source/SetTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ class Box<T : Hashable> : Hashable {
122122
value = v
123123
}
124124

125-
var hashValue: Int {
126-
return value.hashValue
125+
func hash(into hasher: inout Hasher) {
126+
hasher.combine(value)
127127
}
128128

129129
static func ==(lhs: Box, rhs: Box) -> Bool {

‎benchmark/utils/TestsUtils.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ extension BenchmarkInfo : Comparable {
111111
}
112112

113113
extension BenchmarkInfo : Hashable {
114-
public var hashValue: Int {
115-
return name.hashValue
114+
public func hash(into hasher: inout Hasher) {
115+
hasher.combine(name)
116116
}
117117
}
118118

‎benchmark/utils/main.swift

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import DictTest
5050
import DictTest2
5151
import DictTest3
5252
import DictTest4
53+
import DictTest4Legacy
5354
import DictionaryBridge
5455
import DictionaryCopy
5556
import DictionaryGroup
@@ -203,6 +204,7 @@ registerBenchmark(Dictionary)
203204
registerBenchmark(Dictionary2)
204205
registerBenchmark(Dictionary3)
205206
registerBenchmark(Dictionary4)
207+
registerBenchmark(Dictionary4Legacy)
206208
registerBenchmark(DictionaryBridge)
207209
registerBenchmark(DictionaryCopy)
208210
registerBenchmark(DictionaryGroup)

0 commit comments

Comments
 (0)
Please sign in to comment.