Skip to content

Commit 4f6ae6f

Browse files
committed
Add benchmarks based on ordo-one's package-benchmark
1 parent 6ca5f57 commit 4f6ae6f

File tree

9 files changed

+151
-128
lines changed

9 files changed

+151
-128
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the RediStack open source project
4+
//
5+
// Copyright (c) 2023 RediStack 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 RediStack project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
@_spi(RESP3) import RediStack
16+
import Benchmark
17+
import NIOCore
18+
19+
let benchmarks = {
20+
let resp3ArrayValueBuffer = ByteBuffer(string: "*2\r\n$3\r\nGET\r\n$7\r\nwelcome\r\n")
21+
let resp3ArrayCount = 2
22+
23+
Benchmark("RESP3 Array Parsing") { benchmark in
24+
try runRESP3ArrayParsing(
25+
valueBuffer: resp3ArrayValueBuffer,
26+
valueCount: resp3ArrayCount
27+
)
28+
}
29+
30+
let respArrayValueBuffer = ByteBuffer(string: "*2\r\n$3\r\nGET\r\n$7\r\nwelcome\r\n")
31+
let respArrayCount = 2
32+
Benchmark("RESP Array Parsing") { benchmark in
33+
try runRESPArrayParsing(
34+
valueBuffer: respArrayValueBuffer,
35+
valueCount: respArrayCount
36+
)
37+
}
38+
39+
Benchmark("RESP3 Conversation") { benchmark in
40+
try runRESP3Protocol()
41+
}
42+
43+
Benchmark("RESP Conversation") { benchmark in
44+
try runRESPProtocol()
45+
}
46+
}

Sources/RediStackPerformanceTester/RESP3ParsingBenchmark.swift Benchmarks/Benchmarks/ProtocolBenchmark/RESP3ArrayParsingBenchmark.swift

+10-16
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,18 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import NIOCore
16-
import RESP3
16+
@_spi(RESP3) import RediStack
1717

18-
func benchmarkRESP3Parsing() throws {
19-
let valueBuffer = ByteBuffer(string: "*2\r\n$3\r\nGET\r\n$7\r\nwelcome\r\n")
20-
let values: [RESP3Token.Value] = [
21-
.blobString(ByteBuffer(string: "GET")),
22-
.blobString(ByteBuffer(string: "welcome")),
23-
]
18+
func runRESP3ArrayParsing(
19+
valueBuffer: ByteBuffer,
20+
valueCount: Int
21+
) throws {
2422
let token = RESP3Token.Unchecked(buffer: valueBuffer)
2523

26-
try benchmark {
27-
let token = token
28-
29-
guard
30-
case .array(let array) = try token.getValue(),
31-
array.count == values.count
32-
else {
33-
fatalError("\(#function) Test failed: Invalid test result")
34-
}
24+
guard
25+
case .array(let array) = try token.getValue(),
26+
array.count == valueCount
27+
else {
28+
fatalError("\(#function) Test failed: Invalid test result")
3529
}
3630
}

Sources/RediStackPerformanceTester/RESP3ProtocolBenchmark.swift Benchmarks/Benchmarks/ProtocolBenchmark/RESP3ProtocolBenchmark.swift

+22-24
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,35 @@ import Foundation
1818
import NIOCore
1919
import NIOEmbedded
2020

21-
func benchmarkRESP3Protocol() throws {
21+
func runRESP3Protocol() throws {
2222
let channel = EmbeddedChannel()
2323

2424
// Precalculate the server response
2525
try channel.connect(to: .init(unixDomainSocketPath: "/fakeserver")).wait()
2626
let serverReply = "Hello, world"
2727
let redisReplyBuffer = ByteBuffer(string: "$\(serverReply.count)\r\n\(serverReply)\r\n")
2828

29-
try benchmark {
30-
// Client sends a command
31-
// GET welcome
32-
// TODO: Replace when we get RESP3 serialization
33-
try channel.writeOutbound(ByteBuffer(string: "*2\r\n$3\r\nGET\r\n$7\r\nwelcome\r\n"))
34-
35-
// Server reads the command
36-
_ = try channel.readOutbound(as: ByteBuffer.self)
37-
// Server replies
38-
try channel.writeInbound(redisReplyBuffer)
39-
40-
// Client reads the reply
41-
guard var serverReplyBuffer = try channel.readInbound(as: ByteBuffer.self) else {
42-
fatalError("Missing reply")
43-
}
44-
45-
guard case .blobString(var blobString) = try RESP3Token(consuming: &serverReplyBuffer)?.value else {
46-
fatalError("Invalid reply")
47-
}
48-
49-
guard blobString.readString(length: blobString.readableBytes) == serverReply else {
50-
fatalError("Invalid test result")
51-
}
29+
// Client sends a command
30+
// GET welcome
31+
// TODO: Replace when we get RESP3 serialization
32+
try channel.writeOutbound(ByteBuffer(string: "*2\r\n$3\r\nGET\r\n$7\r\nwelcome\r\n"))
33+
34+
// Server reads the command
35+
_ = try channel.readOutbound(as: ByteBuffer.self)
36+
// Server replies
37+
try channel.writeInbound(redisReplyBuffer)
38+
39+
// Client reads the reply
40+
guard var serverReplyBuffer = try channel.readInbound(as: ByteBuffer.self) else {
41+
fatalError("Missing reply")
42+
}
43+
44+
guard case .blobString(var blobString) = try RESP3Token(consuming: &serverReplyBuffer)?.value else {
45+
fatalError("Invalid reply")
46+
}
47+
48+
guard blobString.readString(length: blobString.readableBytes) == serverReply else {
49+
fatalError("Invalid test result")
5250
}
5351

5452
guard case .clean = try channel.finish() else {

Sources/RediStackPerformanceTester/RESPParsingBenchmark.swift Benchmarks/Benchmarks/ProtocolBenchmark/RESPArrayParsingBenchmark.swift

+8-12
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,14 @@
1515
import NIOCore
1616
import RediStack
1717

18-
func benchmarkRESPParsing() throws {
19-
let valueBuffer = ByteBuffer(string: "*2\r\n$3\r\nGET\r\n$7\r\nwelcome\r\n")
20-
let result: [RESPValue] = [
21-
.bulkString(ByteBuffer(string: "GET")),
22-
.bulkString(ByteBuffer(string: "welcome")),
23-
]
18+
func runRESPArrayParsing(
19+
valueBuffer: ByteBuffer,
20+
valueCount: Int
21+
) throws {
2422
let translator = RESPTranslator()
25-
try benchmark {
26-
var valueBuffer = valueBuffer
27-
let value = try translator.parseBytes(from: &valueBuffer)
28-
guard case .array(result) = value else {
29-
fatalError("\(#function) Test failed: Invalid test result")
30-
}
23+
var valueBuffer = valueBuffer
24+
let value = try translator.parseBytes(from: &valueBuffer)
25+
guard case .array(let result) = value, result.count == valueCount else {
26+
fatalError("\(#function) Test failed: Invalid test result")
3127
}
3228
}

Sources/RediStackPerformanceTester/RESPProtocolBenchmark.swift Benchmarks/Benchmarks/ProtocolBenchmark/RESPProtocolBenchmark.swift

+22-26
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
import RediStack
16-
import RESP3
15+
@_spi(RESP3) import RediStack
1716
import Foundation
1817
import NIOCore
1918
import NIOEmbedded
2019

21-
func benchmarkRESPProtocol() throws {
20+
func runRESPProtocol() throws {
2221
let channel = EmbeddedChannel()
2322
try channel.pipeline.addBaseRedisHandlers().wait()
2423

@@ -28,29 +27,26 @@ func benchmarkRESPProtocol() throws {
2827
let serverValue = "Hello, world"
2928
let replyValue = RESPValue.simpleString(ByteBuffer(string: serverValue))
3029
RESPTranslator().write(replyValue, into: &redisReplyBuffer)
31-
32-
try benchmark {
33-
let promise = channel.eventLoop.makePromise(of: RESPValue.self)
34-
35-
// Client sends a command
36-
try channel.writeOutbound(RedisCommand(
37-
message: .array([
38-
.bulkString(ByteBuffer(string: "GET")),
39-
.bulkString(ByteBuffer(string: "welcome")),
40-
]),
41-
responsePromise: promise
42-
))
43-
44-
// Server reads the command
45-
_ = try channel.readOutbound(as: ByteBuffer.self)
46-
// Server replies
47-
try channel.writeInbound(redisReplyBuffer)
48-
49-
// Client reads the reply
50-
let serverReply = try promise.futureResult.wait()
51-
guard serverReply.string == serverValue else {
52-
fatalError("Invalid test result")
53-
}
30+
let promise = channel.eventLoop.makePromise(of: RESPValue.self)
31+
32+
// Client sends a command
33+
try channel.writeOutbound(RedisCommand(
34+
message: .array([
35+
.bulkString(ByteBuffer(string: "GET")),
36+
.bulkString(ByteBuffer(string: "welcome")),
37+
]),
38+
responsePromise: promise
39+
))
40+
41+
// Server reads the command
42+
_ = try channel.readOutbound(as: ByteBuffer.self)
43+
// Server replies
44+
try channel.writeInbound(redisReplyBuffer)
45+
46+
// Client reads the reply
47+
let serverReply = try promise.futureResult.wait()
48+
guard serverReply.string == serverValue else {
49+
fatalError("Invalid test result")
5450
}
5551

5652
guard case .clean = try channel.finish() else {

Benchmarks/Package.swift

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// swift-tools-version:5.9
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// This source file is part of the RediStack open source project
5+
//
6+
// Copyright (c) 2019-2023 RediStack project authors
7+
// Licensed under Apache License v2.0
8+
//
9+
// See LICENSE.txt for license information
10+
// See CONTRIBUTORS.txt for the list of RediStack project authors
11+
//
12+
// SPDX-License-Identifier: Apache-2.0
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
import PackageDescription
17+
18+
let package = Package(
19+
name: "Benchmarks",
20+
platforms: [
21+
.macOS(.v13),
22+
],
23+
dependencies: [
24+
.package(path: "../"),
25+
.package(url: "https://github.com/ordo-one/package-benchmark.git", exact: "1.11.1"),
26+
],
27+
targets: [
28+
.executableTarget(
29+
name: "ProtocolBenchmark",
30+
dependencies: [
31+
.product(name: "Benchmark", package: "package-benchmark"),
32+
.product(name: "RediStack", package: "RediStack"),
33+
],
34+
path: "Benchmarks/ProtocolBenchmark",
35+
plugins: [
36+
.plugin(name: "BenchmarkPlugin", package: "package-benchmark")
37+
]
38+
),
39+
]
40+
)

Package.swift

+2-8
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,11 @@ let package = Package(
4040
.product(name: "NIOSSL", package: "swift-nio-ssl"),
4141
.product(name: "Atomics", package: "swift-atomics"),
4242
.product(name: "Logging", package: "swift-log"),
43-
.product(name: "Metrics", package: "swift-metrics")
43+
.product(name: "Metrics", package: "swift-metrics"),
44+
.target(name: "RESP3"),
4445
]
4546
),
4647
.target(name: "RedisTypes", dependencies: ["RediStack"]),
47-
.executableTarget(
48-
name: "RediStackPerformanceTester",
49-
dependencies: [
50-
"RediStack",
51-
"RESP3",
52-
]
53-
),
5448
.target(
5549
name: "RediStackTestUtils",
5650
dependencies: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@_spi(RESP3) @_exported import RESP3

Sources/RediStackPerformanceTester/main.swift

-42
This file was deleted.

0 commit comments

Comments
 (0)