Skip to content

Commit

Permalink
Add initial Benchmark data
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyle-Ye committed Oct 20, 2024
1 parent 89b5d26 commit 7305e00
Show file tree
Hide file tree
Showing 15 changed files with 525 additions and 3 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
.DS_Store
/.build
.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.swiftpm
.netrc
.repos
/build
/Benchmark/.benchmarkBaselines
15 changes: 15 additions & 0 deletions Benchmark/Benchmarks/BenchmarkHelper/BenchmarkHelper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Benchmark

package let defaultMetrics: [BenchmarkMetric] = [
.cpuTotal,
.mallocCountTotal,
.instructions,
.peakMemoryResident,
]

package let defaultConfiguration: Benchmark.Configuration = .init(
metrics: defaultMetrics,
scalingFactor: .kilo,
maxDuration: .seconds(20),
maxIterations: 10000
)
34 changes: 34 additions & 0 deletions Benchmark/Benchmarks/BenchmarkHelper/Message.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Foundation

package enum Command: CaseIterable {
case unknown
case add
case sub
case mul
case div
}

package struct Message {
package var command: Command
package var id: String
package var value1: Int64
package var value2: Int64

package init(command: Command, id: String, value1: Int64, value2: Int64) {
self.command = command
self.id = id
self.value1 = value1
self.value2 = value2
}
}

extension Message {
package static func random() -> Self {
.init(
command: Command.allCases.randomElement() ?? .unknown,
id: UUID().uuidString,
value1: Int64.random(in: 0...100),
value2: Int64.random(in: 0...100)
)
}
}
102 changes: 102 additions & 0 deletions Benchmark/Benchmarks/ProtobufKitBenchmarks/Benchmarks.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import Benchmark
import ProtobufKit
import BenchmarkHelper

extension Command: ProtobufEnum {
package init(protobufValue: UInt) {
switch protobufValue {
case 0: self = .unknown
case 1: self = .add
case 2: self = .sub
case 3: self = .mul
case 4: self = .div
default: self = .unknown
}
}

package var protobufValue: UInt {
switch self {
case .unknown: return 0
case .add: return 1
case .sub: return 2
case .mul: return 3
case .div: return 4
}
}
}

extension Message: ProtobufMessage {
package func encode(to encoder: inout ProtobufEncoder) throws {
encoder.enumField(1, command)
try encoder.stringField(2, id)
encoder.int64Field(3, value1)
encoder.int64Field(4, value2)
}

package init(from decoder: inout ProtobufDecoder) throws {
var command: Command = .add
var id: String = ""
var value1: Int64 = 0
var value2: Int64 = 0
while let field = try decoder.nextField() {
switch field.tag {
case 1:
if let cmd: Command = try decoder.enumField(field) {
command = cmd
}
case 2:
id = try decoder.stringField(field)
case 3:
value1 = try Int64(decoder.intField(field))
case 4:
value2 = try Int64(decoder.intField(field))
default:
try decoder.skipField(field)
}
}
self.init(command: command, id: id, value1: value1, value2: value2)
}
}

let benchmarks = {
Benchmark(
"Message.encode",
configuration: defaultConfiguration
) { benchmark in
// Elide the cost of the 'Message.init'.
var messages: [Message] = []
messages.reserveCapacity(benchmark.scaledIterations.count)
for _ in 0..<benchmark.scaledIterations.count {
messages.append(.random())
}

benchmark.startMeasurement()
defer {
benchmark.stopMeasurement()
}
for message in messages {
_ = try ProtobufEncoder.encoding(message)
}
}

Benchmark(
"Message.decode",
configuration: defaultConfiguration
) { benchmark in
var messages: [Message] = []
messages.reserveCapacity(benchmark.scaledIterations.count)
for _ in 0..<benchmark.scaledIterations.count {
messages.append(.random())
}
let datas = try messages.map { try ProtobufEncoder.encoding($0) }

benchmark.startMeasurement()
defer {
benchmark.stopMeasurement()
}
for data in datas {
var decoder = ProtobufDecoder(data)
_ = try Message(from: &decoder)
}
}
}
121 changes: 121 additions & 0 deletions Benchmark/Benchmarks/SwiftProtobufBenchmarks/Benchmarks.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import Benchmark
import SwiftProtobuf
import BenchmarkHelper
import struct BenchmarkHelper.Message

extension Command: SwiftProtobuf.Enum {
package init(rawValue: Int) {
switch rawValue {
case 0: self = .unknown
case 1: self = .add
case 2: self = .sub
case 3: self = .mul
case 4: self = .div
default: self = .unknown
}
}

package var rawValue: Int {
switch self {
case .unknown: return 0
case .add: return 1
case .sub: return 2
case .mul: return 3
case .div: return 4
}
}

package init() { self = .unknown }
}

extension Message: SwiftProtobuf.Message {
package init() {
self.init(command: .unknown, id: "", value1: 0, value2: 0)
}

package static var protoMessageName: String { "Message" }

package var unknownFields: SwiftProtobuf.UnknownStorage {
get { fatalError() }
set(newValue) { fatalError() }
}

package mutating func decodeMessage<D>(decoder: inout D) throws where D : SwiftProtobuf.Decoder {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularEnumField(value: &self.command) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.id) }()
case 3: try { try decoder.decodeSingularInt64Field(value: &self.value1) }()
case 4: try { try decoder.decodeSingularInt64Field(value: &self.value2) }()
default: break
}
}
}

package func traverse<V>(visitor: inout V) throws where V : SwiftProtobuf.Visitor {
if self.command != .unknown {
try visitor.visitSingularEnumField(value: self.command, fieldNumber: 1)
}
if !self.id.isEmpty {
try visitor.visitSingularStringField(value: self.id, fieldNumber: 2)
}
if self.value1 != 0 {
try visitor.visitSingularInt64Field(value: self.value1, fieldNumber: 3)
}
if self.value2 != 0 {
try visitor.visitSingularInt64Field(value: self.value2, fieldNumber: 4)
}
}

package func isEqualTo(message: any SwiftProtobuf.Message) -> Bool {
guard let other = message as? Message else {
return false
}
return self.id == other.id
}
}

let benchmarks = {
Benchmark(
"Message.encode",
configuration: defaultConfiguration
) { benchmark in
// Elide the cost of the 'Message.init'.
var messages: [Message] = []
messages.reserveCapacity(benchmark.scaledIterations.count)
for _ in 0..<benchmark.scaledIterations.count {
messages.append(.random())
}

benchmark.startMeasurement()
defer {
benchmark.stopMeasurement()
}
for message in messages {
_ = try message.serializedData()
}
}

Benchmark(
"Message.decode",
configuration: defaultConfiguration
) { benchmark in
var messages: [Message] = []
messages.reserveCapacity(benchmark.scaledIterations.count)
for _ in 0..<benchmark.scaledIterations.count {
messages.append(.random())
}
let datas = try messages.map { try $0.serializedData() }

benchmark.startMeasurement()
defer {
benchmark.stopMeasurement()
}
for data in datas {
_ = try Message(serializedBytes: data)
}
}
}
87 changes: 87 additions & 0 deletions Benchmark/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"originHash" : "08ed28245b15131d02f90a3b1ac24d31abd2182c7202fcfe96dacb0297e93ca8",
"pins" : [
{
"identity" : "hdrhistogram-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/HdrHistogram/hdrhistogram-swift",
"state" : {
"revision" : "a69fa24d7b70421870cafa86340ece900489e17e",
"version" : "0.1.2"
}
},
{
"identity" : "package-benchmark",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ordo-one/package-benchmark.git",
"state" : {
"revision" : "f9dcf0b540c4973ab1cef7893fb46e34a4e74099",
"version" : "1.27.2"
}
},
{
"identity" : "package-jemalloc",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ordo-one/package-jemalloc",
"state" : {
"revision" : "e8a5db026963f5bfeac842d9d3f2cc8cde323b49",
"version" : "1.0.0"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "41982a3656a71c768319979febd796c6fd111d5c",
"version" : "1.5.0"
}
},
{
"identity" : "swift-atomics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-atomics",
"state" : {
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
"version" : "1.2.0"
}
},
{
"identity" : "swift-numerics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-numerics",
"state" : {
"revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
"version" : "1.0.2"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "ebc7251dd5b37f627c93698e4374084d98409633",
"version" : "1.28.2"
}
},
{
"identity" : "swift-system",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-system",
"state" : {
"revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5",
"version" : "1.3.2"
}
},
{
"identity" : "texttable",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ordo-one/TextTable",
"state" : {
"revision" : "a27a07300cf4ae322e0079ca0a475c5583dd575f",
"version" : "0.0.2"
}
}
],
"version" : 3
}
Loading

0 comments on commit 7305e00

Please sign in to comment.