Skip to content

Commit 62cf42d

Browse files
committed
Add a first benchmark
1 parent bc23a6e commit 62cf42d

File tree

3 files changed

+111
-1
lines changed

3 files changed

+111
-1
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the swift-valkey open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the swift-valkey project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of swift-valkey project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Benchmark
16+
import Logging
17+
import NIOCore
18+
import NIOPosix
19+
import Valkey
20+
21+
let benchmarks : @Sendable () -> Void = {
22+
let defaultMetrics: [BenchmarkMetric] = [
23+
.wallClock,
24+
.cpuTotal,
25+
.mallocCountTotal,
26+
.throughput,
27+
.instructions,
28+
]
29+
30+
var server: Channel?
31+
Benchmark("GET benchmark", configuration: .init(metrics: defaultMetrics, scalingFactor: .kilo)) { benchmark in
32+
let port = server!.localAddress!.port!
33+
let logger = Logger(label: "test")
34+
let client = ValkeyClient(.hostname("127.0.0.1", port: port), logger: logger)
35+
36+
try await client.withConnection(logger: logger) { connection in
37+
benchmark.startMeasurement()
38+
39+
for _ in benchmark.scaledIterations {
40+
let foo = try await connection.get(key: "foo")
41+
precondition(foo == "Bar")
42+
}
43+
44+
benchmark.stopMeasurement()
45+
}
46+
} setup: {
47+
server = try await ServerBootstrap(group: NIOSingletons.posixEventLoopGroup)
48+
.childChannelInitializer { channel in
49+
do {
50+
try channel.pipeline.syncOperations.addHandler(ValkeyServerChannelHandler())
51+
return channel.eventLoop.makeSucceededVoidFuture()
52+
} catch {
53+
return channel.eventLoop.makeFailedFuture(error)
54+
}
55+
}
56+
.bind(host: "127.0.0.1", port: 0)
57+
.get()
58+
} teardown: {
59+
try await server?.close().get()
60+
}
61+
}
62+
63+
final class ValkeyServerChannelHandler: ChannelInboundHandler {
64+
typealias InboundIn = ByteBuffer
65+
typealias OutboundOut = ByteBuffer
66+
67+
private var decoder = NIOSingleStepByteToMessageProcessor(RESPTokenDecoder())
68+
private let response = ByteBuffer(string: "$3\r\nBar\r\n")
69+
70+
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
71+
try! self.decoder.process(buffer: self.unwrapInboundIn(data)) { token in
72+
self.handleToken(context: context, token: token)
73+
}
74+
}
75+
76+
func handleToken(context: ChannelHandlerContext, token: RESPToken) {
77+
guard case .array(let array) = token.value else {
78+
fatalError()
79+
}
80+
81+
var iterator = array.makeIterator()
82+
switch iterator.next()?.value {
83+
case .bulkString(ByteBuffer(string: "HELLO")):
84+
let map = "%1\r\n+server\r\n+fake\r\n"
85+
context.writeAndFlush(self.wrapOutboundOut(ByteBuffer(string: map)), promise: nil)
86+
87+
case .bulkString(ByteBuffer(string: "GET")):
88+
context.writeAndFlush(self.wrapOutboundOut(self.response), promise: nil)
89+
90+
default:
91+
fatalError()
92+
}
93+
}
94+
}

Package.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ let package = Package(
1515
.package(url: "https://github.com/apple/swift-nio.git", from: "2.79.0"),
1616
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.29.0"),
1717
.package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.23.0"),
18+
19+
.package(url: "https://github.com/ordo-one/package-benchmark", from: "1.29.2"),
1820
],
1921
targets: [
2022
.target(
@@ -32,6 +34,20 @@ let package = Package(
3234
name: "ValkeyCommandsBuilder",
3335
resources: [.process("Resources")]
3436
),
37+
.executableTarget(
38+
name: "ValkeyBenchmarks",
39+
dependencies: [
40+
"Valkey",
41+
.product(name: "Benchmark", package: "package-benchmark"),
42+
.product(name: "Logging", package: "swift-log"),
43+
.product(name: "NIOCore", package: "swift-nio"),
44+
.product(name: "NIOPosix", package: "swift-nio"),
45+
],
46+
path: "Benchmarks/ValkeyBenchmarks",
47+
plugins: [
48+
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
49+
]
50+
),
3551
.testTarget(
3652
name: "ValkeyTests",
3753
dependencies: ["Valkey"]

Sources/Valkey/ValkeyClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ extension ValkeyClient {
6262
/// - operation: Closure handling Valkey connection
6363
public func withConnection<Value: Sendable>(
6464
logger: Logger,
65-
operation: @escaping @Sendable (ValkeyConnection) async throws -> Value
65+
operation: (ValkeyConnection) async throws -> Value
6666
) async throws -> Value {
6767
let valkeyConnection = try await ValkeyConnection.connect(
6868
address: self.serverAddress,

0 commit comments

Comments
 (0)