Skip to content

Commit 6e017a8

Browse files
committed
add batching demo
1 parent 04f5c14 commit 6e017a8

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//
2+
// Copyright (c) 2025 PADL Software Pty Ltd
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 Foundation // for String(format:)
18+
@testable import IORing
19+
import struct SystemPackage.Errno
20+
import struct SystemPackage.FileDescriptor
21+
22+
let operationCount = 100
23+
24+
@main
25+
struct BatchingDemo {
26+
static func main() async {
27+
print("IORing Batching Performance Demo")
28+
print("================================")
29+
30+
await testBatchingPerformance()
31+
}
32+
33+
static func testBatchingPerformance() async {
34+
do {
35+
// Test 1: No batching (batch size 1)
36+
print("\nTest 1: No Batching (batch size 1)")
37+
let noBatchRing = try IORing(batchSize: 1, batchTimeout: .microseconds(1))
38+
let noBatchTime = await measureOperations(ring: noBatchRing, count: operationCount)
39+
print("Time: \(String(format: "%.3f", noBatchTime)) seconds")
40+
41+
// Test 2: Small batches (batch size 4)
42+
print("\nTest 2: Small Batching (batch size 4)")
43+
let smallBatchRing = try IORing(batchSize: 4, batchTimeout: .microseconds(100))
44+
let smallBatchTime = await measureOperations(ring: smallBatchRing, count: operationCount)
45+
print("Time: \(String(format: "%.3f", smallBatchTime)) seconds")
46+
47+
// Test 3: Large batches (batch size 16)
48+
print("\nTest 3: Large Batching (batch size 16)")
49+
let largeBatchRing = try IORing(batchSize: 16, batchTimeout: .microseconds(200))
50+
let largeBatchTime = await measureOperations(ring: largeBatchRing, count: operationCount)
51+
print("Time: \(String(format: "%.3f", largeBatchTime)) seconds")
52+
53+
// Analysis
54+
print("\nPerformance Analysis:")
55+
print("--------------------")
56+
let smallBatchImprovement = ((noBatchTime - smallBatchTime) / noBatchTime) * 100
57+
let largeBatchImprovement = ((noBatchTime - largeBatchTime) / noBatchTime) * 100
58+
59+
if smallBatchImprovement > 0 {
60+
print(
61+
"Small batching improved performance by \(String(format: "%.1f", smallBatchImprovement))%"
62+
)
63+
}
64+
if largeBatchImprovement > 0 {
65+
print(
66+
"Large batching improved performance by \(String(format: "%.1f", largeBatchImprovement))%"
67+
)
68+
}
69+
70+
} catch {
71+
print("Error: \(error)")
72+
}
73+
}
74+
75+
static func measureOperations(ring: IORing, count: Int) async -> Double {
76+
let startTime = ContinuousClock.now
77+
78+
await withTaskGroup(of: Void.self) { group in
79+
for i in 0..<count {
80+
group.addTask {
81+
do {
82+
let data = "Test operation \(i)\n".data(using: .utf8) ?? Data()
83+
// Write to /dev/null to avoid actual I/O overhead
84+
let devNull = try FileDescriptor.open("/dev/null", .writeOnly)
85+
defer { try? devNull.close() }
86+
_ = try await ring.write([UInt8](data), to: devNull)
87+
} catch {
88+
// Ignore errors for performance testing
89+
}
90+
}
91+
}
92+
}
93+
94+
let endTime = ContinuousClock.now
95+
let duration = endTime - startTime
96+
return Double(duration.components.seconds) + Double(duration.components.attoseconds) / 1e18
97+
}
98+
}

Package.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ let package = Package(
146146
dependencies: ["IORing", "IORingUtils"],
147147
path: "Examples/IORingDeviceSpy"
148148
),
149+
.executableTarget(
150+
name: "BatchingDemo",
151+
dependencies: ["IORing", "IORingUtils"],
152+
path: "Examples/BatchingDemo"
153+
),
149154
],
150155
cLanguageStandard: .c18,
151156
cxxLanguageStandard: .cxx20

0 commit comments

Comments
 (0)