Skip to content

Commit 130ce14

Browse files
authored
Merge pull request #15221 from parkera/parkera/data_benchmarks
Updated Data benchmarks
2 parents c79fa5b + bfa0be9 commit 130ce14

File tree

5 files changed

+389
-2
lines changed

5 files changed

+389
-2
lines changed

benchmark/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ set(SWIFT_BENCH_MODULES
5555
single-source/Chars
5656
single-source/ClassArrayGetter
5757
single-source/Combos
58+
single-source/DataBenchmarks
5859
single-source/DeadArray
5960
single-source/DictOfArraysToArrayOfDicts
6061
single-source/DictTest
Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
//===--- DataBenchmarks.swift ---------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 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+
import Foundation
15+
16+
public let DataBenchmarks = [
17+
BenchmarkInfo(name: "DataSubscript", runFunction: run_Subscript, tags: [.validation, .api, .Data]),
18+
BenchmarkInfo(name: "DataCount", runFunction: run_Count, tags: [.validation, .api, .Data]),
19+
BenchmarkInfo(name: "DataSetCount", runFunction: run_SetCount, tags: [.validation, .api, .Data]),
20+
BenchmarkInfo(name: "DataAccessBytes", runFunction: run_AccessBytes, tags: [.validation, .api, .Data]),
21+
BenchmarkInfo(name: "DataMutateBytes", runFunction: run_MutateBytes, tags: [.validation, .api, .Data]),
22+
BenchmarkInfo(name: "DataCopyBytes", runFunction: run_CopyBytes, tags: [.validation, .api, .Data]),
23+
BenchmarkInfo(name: "DataAppendBytes", runFunction: run_AppendBytes, tags: [.validation, .api, .Data]),
24+
BenchmarkInfo(name: "DataAppendArray", runFunction: run_AppendArray, tags: [.validation, .api, .Data]),
25+
BenchmarkInfo(name: "DataReset", runFunction: run_Reset, tags: [.validation, .api, .Data]),
26+
BenchmarkInfo(name: "DataReplaceSmall", runFunction: run_ReplaceSmall, tags: [.validation, .api, .Data]),
27+
BenchmarkInfo(name: "DataReplaceMedium", runFunction: run_ReplaceMedium, tags: [.validation, .api, .Data]),
28+
BenchmarkInfo(name: "DataReplaceLarge", runFunction: run_ReplaceLarge, tags: [.validation, .api, .Data]),
29+
BenchmarkInfo(name: "DataReplaceSmallBuffer", runFunction: run_ReplaceSmallBuffer, tags: [.validation, .api, .Data]),
30+
BenchmarkInfo(name: "DataReplaceMediumBuffer", runFunction: run_ReplaceMediumBuffer, tags: [.validation, .api, .Data]),
31+
BenchmarkInfo(name: "DataReplaceLargeBuffer", runFunction: run_ReplaceLargeBuffer, tags: [.validation, .api, .Data]),
32+
BenchmarkInfo(name: "DataAppendSequence", runFunction: run_AppendSequence, tags: [.validation, .api, .Data]),
33+
BenchmarkInfo(name: "DataAppendDataSmallToSmall", runFunction: run_AppendDataSmallToSmall, tags: [.validation, .api, .Data]),
34+
BenchmarkInfo(name: "DataAppendDataSmallToMedium", runFunction: run_AppendDataSmallToMedium, tags: [.validation, .api, .Data]),
35+
BenchmarkInfo(name: "DataAppendDataSmallToLarge", runFunction: run_AppendDataSmallToLarge, tags: [.validation, .api, .Data]),
36+
BenchmarkInfo(name: "DataAppendDataMediumToSmall", runFunction: run_AppendDataMediumToSmall, tags: [.validation, .api, .Data]),
37+
BenchmarkInfo(name: "DataAppendDataMediumToMedium", runFunction: run_AppendDataMediumToMedium, tags: [.validation, .api, .Data]),
38+
BenchmarkInfo(name: "DataAppendDataMediumToLarge", runFunction: run_AppendDataMediumToLarge, tags: [.validation, .api, .Data]),
39+
BenchmarkInfo(name: "DataAppendDataLargeToSmall", runFunction: run_AppendDataLargeToSmall, tags: [.validation, .api, .Data]),
40+
BenchmarkInfo(name: "DataAppendDataLargeToMedium", runFunction: run_AppendDataLargeToMedium, tags: [.validation, .api, .Data]),
41+
BenchmarkInfo(name: "DataAppendDataLargeToLarge", runFunction: run_AppendDataLargeToLarge, tags: [.validation, .api, .Data]),
42+
]
43+
44+
enum SampleKind {
45+
case small
46+
case medium
47+
case large
48+
case veryLarge
49+
case string
50+
case immutableBacking
51+
}
52+
53+
func sampleData(size: Int) -> Data {
54+
var data = Data(count: size)
55+
data.withUnsafeMutableBytes { arc4random_buf($0, size) }
56+
return data
57+
}
58+
59+
func sampleString() -> Data {
60+
let bytes: [UInt8] = [
61+
0x4c,0x6f,0x72,0x65, 0x6d,0x20,0x69,0x70, 0x73,0x75,0x6d,0x20, 0x64,0x6f,0x6c,0x6f,
62+
0x72,0x20,0x73,0x69, 0x74,0x20,0x61,0x6d, 0x65,0x74,0x2c,0x20, 0x63,0x6f,0x6e,0x73,
63+
0x65,0x63,0x74,0x65, 0x74,0x75,0x72,0x20, 0x61,0x64,0x69,0x70, 0x69,0x73,0x69,0x63,
64+
0x69,0x6e,0x67,0x20, 0x65,0x6c,0x69,0x74, 0x2c,0x20,0x73,0x65, 0x64,0x20,0x64,0x6f,
65+
0x20,0x65,0x69,0x75, 0x73,0x6d,0x6f,0x64, 0x0a,0x74,0x65,0x6d, 0x70,0x6f,0x72,0x20,
66+
0x69,0x6e,0x63,0x69, 0x64,0x69,0x64,0x75, 0x6e,0x74,0x20,0x75, 0x74,0x20,0x6c,0x61,
67+
0x62,0x6f,0x72,0x65, 0x20,0x65,0x74,0x20, 0x64,0x6f,0x6c,0x6f, 0x72,0x65,0x20,0x6d,
68+
0x61,0x67,0x6e,0x61, 0x20,0x61,0x6c,0x69, 0x71,0x75,0x61,0x2e, 0x20,0x55,0x74,0x20,
69+
0x65,0x6e,0x69,0x6d, 0x20,0x61,0x64,0x20, 0x6d,0x69,0x6e,0x69, 0x6d,0x20,0x76,0x65,
70+
0x6e,0x69,0x61,0x6d, 0x2c,0x0a,0x71,0x75, 0x69,0x73,0x20,0x6e, 0x6f,0x73,0x74,0x72,
71+
0x75,0x64,0x20,0x65, 0x78,0x65,0x72,0x63, 0x69,0x74,0x61,0x74, 0x69,0x6f,0x6e,0x20,
72+
0x75,0x6c,0x6c,0x61, 0x6d,0x63,0x6f,0x20, 0x6c,0x61,0x62,0x6f, 0x72,0x69,0x73,0x20,
73+
0x6e,0x69,0x73,0x69, 0x20,0x75,0x74,0x20, 0x61,0x6c,0x69,0x71, 0x75,0x69,0x70,0x20,
74+
0x65,0x78,0x20,0x65, 0x61,0x20,0x63,0x6f, 0x6d,0x6d,0x6f,0x64, 0x6f,0x0a,0x63,0x6f,
75+
0x6e,0x73,0x65,0x71, 0x75,0x61,0x74,0x2e, 0x20,0x44,0x75,0x69, 0x73,0x20,0x61,0x75,
76+
0x74,0x65,0x20,0x69, 0x72,0x75,0x72,0x65, 0x20,0x64,0x6f,0x6c, 0x6f,0x72,0x20,0x69,
77+
0x6e,0x20,0x72,0x65, 0x70,0x72,0x65,0x68, 0x65,0x6e,0x64,0x65, 0x72,0x69,0x74,0x20,
78+
0x69,0x6e,0x20,0x76, 0x6f,0x6c,0x75,0x70, 0x74,0x61,0x74,0x65, 0x20,0x76,0x65,0x6c,
79+
0x69,0x74,0x20,0x65, 0x73,0x73,0x65,0x0a, 0x63,0x69,0x6c,0x6c, 0x75,0x6d,0x20,0x64,
80+
0x6f,0x6c,0x6f,0x72, 0x65,0x20,0x65,0x75, 0x20,0x66,0x75,0x67, 0x69,0x61,0x74,0x20,
81+
0x6e,0x75,0x6c,0x6c, 0x61,0x20,0x70,0x61, 0x72,0x69,0x61,0x74, 0x75,0x72,0x2e,0x20,
82+
0x45,0x78,0x63,0x65, 0x70,0x74,0x65,0x75, 0x72,0x20,0x73,0x69, 0x6e,0x74,0x20,0x6f,
83+
0x63,0x63,0x61,0x65, 0x63,0x61,0x74,0x20, 0x63,0x75,0x70,0x69, 0x64,0x61,0x74,0x61,
84+
0x74,0x20,0x6e,0x6f, 0x6e,0x0a,0x70,0x72, 0x6f,0x69,0x64,0x65, 0x6e,0x74,0x2c,0x20,
85+
0x73,0x75,0x6e,0x74, 0x20,0x69,0x6e,0x20, 0x63,0x75,0x6c,0x70, 0x61,0x20,0x71,0x75,
86+
0x69,0x20,0x6f,0x66, 0x66,0x69,0x63,0x69, 0x61,0x20,0x64,0x65, 0x73,0x65,0x72,0x75,
87+
0x6e,0x74,0x20,0x6d, 0x6f,0x6c,0x6c,0x69, 0x74,0x20,0x61,0x6e, 0x69,0x6d,0x20,0x69,
88+
0x64,0x20,0x65,0x73, 0x74,0x20,0x6c,0x61, 0x62,0x6f,0x72,0x75, 0x6d,0x2e,0x0a,0x00]
89+
return Data(bytes: bytes)
90+
}
91+
92+
func sampleBridgedNSData() -> Data {
93+
let count = 1033
94+
var bytes = [UInt8](repeating: 0, count: count)
95+
bytes.withUnsafeMutableBufferPointer {
96+
arc4random_buf($0.baseAddress, $0.count)
97+
}
98+
let data = NSData(bytes: bytes, length: count)
99+
return Data(referencing: data)
100+
}
101+
102+
func sampleData(_ type: SampleKind) -> Data {
103+
switch type {
104+
case .small: return sampleData(size: 11)
105+
case .medium: return sampleData(size: 1033)
106+
case .large: return sampleData(size: 40980)
107+
case .veryLarge: return sampleData(size: 1024 * 1024 * 1024 + 128)
108+
case .string: return sampleString()
109+
case .immutableBacking: return sampleBridgedNSData()
110+
}
111+
112+
}
113+
114+
func benchmark_AccessBytes(_ N: Int, _ data: Data) {
115+
for _ in 1...10000*N {
116+
data.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
117+
// Ensure that the compiler does not optimize away this call
118+
blackHole(ptr.pointee)
119+
}
120+
}
121+
}
122+
123+
func benchmark_MutateBytes(_ N: Int, _ data_: Data) {
124+
for _ in 1...10000*N {
125+
var data = data_
126+
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
127+
// Mutate a byte
128+
ptr.pointee = 42
129+
}
130+
}
131+
}
132+
133+
func benchmark_CopyBytes(_ N: Int, _ data: Data) {
134+
let amount = data.count
135+
var buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: amount)
136+
defer { buffer.deallocate() }
137+
for _ in 1...10000*N {
138+
data.copyBytes(to: buffer, count: amount)
139+
}
140+
}
141+
142+
func benchmark_AppendBytes(_ N: Int, _ count: Int, _ data_: Data) {
143+
let bytes = malloc(count).assumingMemoryBound(to: UInt8.self)
144+
defer { free(bytes) }
145+
for _ in 1...10000*N {
146+
var data = data_
147+
data.append(bytes, count: count)
148+
}
149+
}
150+
151+
func benchmark_AppendArray(_ N: Int, _ count: Int, _ data_: Data) {
152+
var bytes = [UInt8](repeating: 0, count: count)
153+
bytes.withUnsafeMutableBufferPointer {
154+
arc4random_buf($0.baseAddress, $0.count)
155+
}
156+
for _ in 1...10000*N {
157+
var data = data_
158+
data.append(contentsOf: bytes)
159+
}
160+
}
161+
162+
func benchmark_AppendSequence(_ N: Int, _ count: Int, _ data_: Data) {
163+
let bytes = repeatElement(UInt8(0xA0), count: count)
164+
for _ in 1...10000*N {
165+
var data = data_
166+
data.append(contentsOf: bytes)
167+
}
168+
}
169+
170+
func benchmark_Reset(_ N: Int, _ range: Range<Data.Index>, _ data_: Data) {
171+
for _ in 1...10000*N {
172+
var data = data_
173+
data.resetBytes(in: range)
174+
}
175+
}
176+
177+
func benchmark_Replace(_ N: Int, _ range: Range<Data.Index>, _ data_: Data, _ replacement: Data) {
178+
for _ in 1...10000*N {
179+
var data = data_
180+
data.replaceSubrange(range, with: replacement)
181+
}
182+
}
183+
184+
func benchmark_ReplaceBuffer(_ N: Int, _ range: Range<Data.Index>, _ data_: Data, _ replacement: UnsafeBufferPointer<UInt8>) {
185+
for _ in 1...10000*N {
186+
var data = data_
187+
data.replaceSubrange(range, with: replacement)
188+
}
189+
}
190+
191+
func benchmark_AppendData(_ N: Int, _ lhs: Data, _ rhs: Data) {
192+
var data = lhs
193+
for _ in 1...10000*N {
194+
data = lhs
195+
data.append(rhs)
196+
}
197+
}
198+
199+
@inline(never)
200+
public func run_Subscript(_ N: Int) {
201+
let data = sampleData(.medium)
202+
let index = 521
203+
for _ in 1...10000*N {
204+
// Ensure that the compiler does not optimize away this call
205+
blackHole(data[index])
206+
}
207+
}
208+
209+
@inline(never)
210+
public func run_Count(_ N: Int) {
211+
let data = sampleData(.medium)
212+
for _ in 1...10000*N {
213+
// Ensure that the compiler does not optimize away this call
214+
blackHole(data.count)
215+
}
216+
}
217+
218+
@inline(never)
219+
public func run_SetCount(_ N: Int) {
220+
let data = sampleData(.medium)
221+
let count = data.count + 100
222+
var otherData = data
223+
let orig = data.count
224+
for _ in 1...10000*N {
225+
otherData.count = count
226+
otherData.count = orig
227+
}
228+
}
229+
230+
@inline(never)
231+
public func run_AccessBytes(_ N: Int) {
232+
let data = sampleData(.medium)
233+
benchmark_AccessBytes(N, data)
234+
}
235+
236+
@inline(never)
237+
public func run_MutateBytes(_ N: Int) {
238+
let data = sampleData(.medium)
239+
benchmark_MutateBytes(N, data)
240+
}
241+
242+
@inline(never)
243+
public func run_CopyBytes(_ N: Int) {
244+
let data = sampleData(.medium)
245+
benchmark_CopyBytes(N, data)
246+
}
247+
248+
@inline(never)
249+
public func run_AppendBytes(_ N: Int) {
250+
let data = sampleData(.medium)
251+
benchmark_AppendBytes(N, 809, data)
252+
}
253+
254+
@inline(never)
255+
public func run_AppendArray(_ N: Int) {
256+
let data = sampleData(.medium)
257+
benchmark_AppendArray(N, 809, data)
258+
}
259+
260+
@inline(never)
261+
public func run_Reset(_ N: Int) {
262+
let data = sampleData(.medium)
263+
benchmark_Reset(N, 431..<809, data)
264+
}
265+
266+
@inline(never)
267+
public func run_ReplaceSmall(_ N: Int) {
268+
let data = sampleData(.medium)
269+
let replacement = sampleData(.small)
270+
benchmark_Replace(N, 431..<809, data, replacement)
271+
}
272+
273+
@inline(never)
274+
public func run_ReplaceMedium(_ N: Int) {
275+
let data = sampleData(.medium)
276+
let replacement = sampleData(.medium)
277+
benchmark_Replace(N, 431..<809, data, replacement)
278+
}
279+
280+
@inline(never)
281+
public func run_ReplaceLarge(_ N: Int) {
282+
let data = sampleData(.medium)
283+
let replacement = sampleData(.large)
284+
benchmark_Replace(N, 431..<809, data, replacement)
285+
}
286+
287+
@inline(never)
288+
public func run_ReplaceSmallBuffer(_ N: Int) {
289+
let data = sampleData(.medium)
290+
let replacement = sampleData(.small)
291+
let sz = replacement.count
292+
replacement.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
293+
benchmark_ReplaceBuffer(N, 431..<809, data, UnsafeBufferPointer(start: ptr, count: sz))
294+
}
295+
}
296+
297+
@inline(never)
298+
public func run_ReplaceMediumBuffer(_ N: Int) {
299+
let data = sampleData(.medium)
300+
let replacement = sampleData(.medium)
301+
let sz = replacement.count
302+
replacement.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
303+
benchmark_ReplaceBuffer(N, 431..<809, data, UnsafeBufferPointer(start: ptr, count: sz))
304+
}
305+
}
306+
307+
@inline(never)
308+
public func run_ReplaceLargeBuffer(_ N: Int) {
309+
let data = sampleData(.medium)
310+
let replacement = sampleData(.large)
311+
let sz = replacement.count
312+
replacement.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
313+
benchmark_ReplaceBuffer(N, 431..<809, data, UnsafeBufferPointer(start: ptr, count: sz))
314+
}
315+
}
316+
317+
@inline(never)
318+
public func run_AppendSequence(_ N: Int) {
319+
let data = sampleData(.medium)
320+
benchmark_AppendSequence(N, 809, data)
321+
}
322+
323+
@inline(never)
324+
public func run_AppendDataSmallToSmall(_ N: Int) {
325+
let data = sampleData(.small)
326+
let other = sampleData(.small)
327+
benchmark_AppendData(N, data, other)
328+
}
329+
330+
@inline(never)
331+
public func run_AppendDataSmallToMedium(_ N: Int) {
332+
let data = sampleData(.medium)
333+
let other = sampleData(.small)
334+
benchmark_AppendData(N, data, other)
335+
}
336+
337+
@inline(never)
338+
public func run_AppendDataSmallToLarge(_ N: Int) {
339+
let data = sampleData(.large)
340+
let other = sampleData(.small)
341+
benchmark_AppendData(N, data, other)
342+
}
343+
344+
@inline(never)
345+
public func run_AppendDataMediumToSmall(_ N: Int) {
346+
let data = sampleData(.small)
347+
let other = sampleData(.medium)
348+
benchmark_AppendData(N, data, other)
349+
}
350+
351+
@inline(never)
352+
public func run_AppendDataMediumToMedium(_ N: Int) {
353+
let data = sampleData(.medium)
354+
let other = sampleData(.medium)
355+
benchmark_AppendData(N, data, other)
356+
}
357+
358+
@inline(never)
359+
public func run_AppendDataMediumToLarge(_ N: Int) {
360+
let data = sampleData(.large)
361+
let other = sampleData(.medium)
362+
benchmark_AppendData(N, data, other)
363+
}
364+
365+
@inline(never)
366+
public func run_AppendDataLargeToSmall(_ N: Int) {
367+
let data = sampleData(.small)
368+
let other = sampleData(.large)
369+
benchmark_AppendData(N, data, other)
370+
}
371+
372+
@inline(never)
373+
public func run_AppendDataLargeToMedium(_ N: Int) {
374+
let data = sampleData(.medium)
375+
let other = sampleData(.large)
376+
benchmark_AppendData(N, data, other)
377+
}
378+
379+
@inline(never)
380+
public func run_AppendDataLargeToLarge(_ N: Int) {
381+
let data = sampleData(.large)
382+
let other = sampleData(.large)
383+
benchmark_AppendData(N, data, other)
384+
}

0 commit comments

Comments
 (0)