• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import Benchmark
18 import CoreFoundation
19 import FlatBuffers
20 
21 @usableFromInline
22 struct AA: NativeStruct {
23   public init(a: Double, b: Double) {
24     self.a = a
25     self.b = b
26   }
27   var a: Double
28   var b: Double
29 }
30 
31 let benchmarks = {
32   let ints: [Int] = Array(repeating: 42, count: 100)
33   let bytes: [UInt8] = Array(repeating: 42, count: 100)
34   let str10 = (0...9).map { _ -> String in "x" }.joined()
35   let str100 = (0...99).map { _ -> String in "x" }.joined()
36   let array: [AA] = [
37     AA(a: 2.4, b: 2.4),
38     AA(a: 2.4, b: 2.4),
39     AA(a: 2.4, b: 2.4),
40     AA(a: 2.4, b: 2.4),
41     AA(a: 2.4, b: 2.4),
42   ]
43 
44   let metrics: [BenchmarkMetric] = [
45     .cpuTotal,
46     .wallClock,
47     .mallocCountTotal,
48     .releaseCount,
49     .peakMemoryResident,
50   ]
51   let maxIterations = 1_000_000
52   let maxDuration: Duration = .seconds(3)
53   let singleConfiguration: Benchmark.Configuration = .init(
54     metrics: metrics,
55     warmupIterations: 1,
56     scalingFactor: .one,
57     maxDuration: maxDuration,
58     maxIterations: maxIterations)
59   let kiloConfiguration: Benchmark.Configuration = .init(
60     metrics: metrics,
61     warmupIterations: 1,
62     scalingFactor: .kilo,
63     maxDuration: maxDuration,
64     maxIterations: maxIterations)
65   let megaConfiguration: Benchmark.Configuration = .init(
66     metrics: metrics,
67     warmupIterations: 1,
68     scalingFactor: .mega,
69     maxDuration: maxDuration,
70     maxIterations: maxIterations)
71 
72   Benchmark.defaultConfiguration = megaConfiguration
73 
74   Benchmark("Allocating 1GB", configuration: singleConfiguration) { benchmark in
75     for _ in benchmark.scaledIterations {
76       blackHole(FlatBufferBuilder(initialSize: 1_024_000_000))
77     }
78   }
79 
80   Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
81     var fb = FlatBufferBuilder(initialSize: 1_024_000_000)
82     benchmark.startMeasurement()
83     for _ in benchmark.scaledIterations {
84       blackHole(fb.clear())
85     }
86   }
87 
88   Benchmark("Strings 10") { benchmark in
89     var fb = FlatBufferBuilder(initialSize: 1<<20)
90     benchmark.startMeasurement()
91     for _ in benchmark.scaledIterations {
92       blackHole(fb.create(string: str10))
93     }
94   }
95 
96   Benchmark("Strings 100") { benchmark in
97     var fb = FlatBufferBuilder(initialSize: 1<<20)
98     benchmark.startMeasurement()
99     for _ in benchmark.scaledIterations {
100       blackHole(fb.create(string: str100))
101     }
102   }
103 
104   Benchmark("Vector 1 Bytes") { benchmark in
105     var fb = FlatBufferBuilder(initialSize: 1<<20)
106     benchmark.startMeasurement()
107     for _ in benchmark.scaledIterations {
108       blackHole(fb.createVector(bytes: bytes))
109     }
110   }
111 
112   Benchmark("Vector 1 Ints") { benchmark in
113     var fb = FlatBufferBuilder(initialSize: 1<<20)
114     benchmark.startMeasurement()
115     for _ in benchmark.scaledIterations {
116       blackHole(fb.createVector(ints))
117     }
118   }
119 
120   Benchmark("Vector 100 Ints") { benchmark in
121     var fb = FlatBufferBuilder(initialSize: 1<<20)
122     benchmark.startMeasurement()
123     for i in benchmark.scaledIterations {
124       blackHole(fb.createVector(ints))
125     }
126   }
127 
128   Benchmark("Vector 100 Bytes") { benchmark in
129     var fb = FlatBufferBuilder(initialSize: 1<<20)
130     benchmark.startMeasurement()
131     for i in benchmark.scaledIterations {
132       blackHole(fb.createVector(bytes))
133     }
134   }
135 
136   Benchmark("Vector 100 ContiguousBytes") { benchmark in
137     var fb = FlatBufferBuilder(initialSize: 1<<20)
138     benchmark.startMeasurement()
139     for i in benchmark.scaledIterations {
140       blackHole(fb.createVector(bytes: bytes))
141     }
142   }
143 
144   Benchmark(
145     "FlatBufferBuilder Add",
146     configuration: kiloConfiguration)
147   { benchmark in
148     var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
149     benchmark.startMeasurement()
150     for _ in benchmark.scaledIterations {
151       let off = fb.create(string: "T")
152       let s = fb.startTable(with: 4)
153       fb.add(element: 3.2, def: 0, at: 2)
154       fb.add(element: 4.2, def: 0, at: 4)
155       fb.add(element: 5.2, def: 0, at: 6)
156       fb.add(offset: off, at: 8)
157       blackHole(fb.endTable(at: s))
158     }
159   }
160 
161   Benchmark("Structs") { benchmark in
162     let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024
163     var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600))
164     var offsets: [Offset] = []
165 
166     benchmark.startMeasurement()
167     for _ in benchmark.scaledIterations {
168       let vector = fb.createVector(
169         ofStructs: array)
170       let start = fb.startTable(with: 1)
171       fb.add(offset: vector, at: 4)
172       offsets.append(Offset(offset: fb.endTable(at: start)))
173     }
174 
175     let vector = fb.createVector(ofOffsets: offsets)
176     let start = fb.startTable(with: 1)
177     fb.add(offset: vector, at: 4)
178     let root = Offset(offset: fb.endTable(at: start))
179     fb.finish(offset: root)
180   }
181 
182   Benchmark("Vector of Offsets") { benchmark in
183     let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024
184     var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600))
185     benchmark.startMeasurement()
186     for _ in benchmark.scaledIterations {
187       let offsets = [
188         fb.create(string: "T"),
189         fb.create(string: "2"),
190         fb.create(string: "3"),
191       ]
192       let off = fb.createVector(ofOffsets: [
193         fb.createVector(ofOffsets: offsets),
194         fb.createVector(ofOffsets: offsets),
195       ])
196       let s = fb.startTable(with: 2)
197       fb.add(offset: off, at: 2)
198       blackHole(fb.endTable(at: s))
199     }
200   }
201 }
202