Skip to content

Commit adcc4fc

Browse files
committed
Setup benchmarks
1 parent 4752325 commit adcc4fc

File tree

27 files changed

+1207
-368
lines changed

27 files changed

+1207
-368
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Benchmarks CI
2+
on:
3+
push:
4+
5+
jobs:
6+
benchmark:
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
os: [ ubuntu-latest, macos-latest ]
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: ./.github/actions/setup-gradle
15+
16+
- run: >
17+
./gradlew
18+
FastCsvLocalRequestChannelBenchmark
19+
FastCsvLocalRequestResponseBenchmark
20+
FastCsvLocalRequestStreamBenchmark
21+
--dry-run
22+
23+
- run: >
24+
./gradlew
25+
FastCsvLocalRequestChannelBenchmark
26+
FastCsvLocalRequestResponseBenchmark
27+
FastCsvLocalRequestStreamBenchmark
28+
--no-parallel
29+
--max-workers=1
30+
31+
- if: always() && !cancelled()
32+
uses: actions/upload-artifact@v4
33+
with:
34+
name: benchmark-reports-${{ matrix.os }}
35+
path: "benchmarks/**/build/reports/benchmarks/**/*.csv"
36+
retention-days: 1

benchmarks/build.gradle.kts

Lines changed: 0 additions & 116 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2015-2025 the original author or authors.
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 kotlinx.benchmark.gradle.*
18+
import rsocketbuild.*
19+
20+
plugins {
21+
id("rsocketbuild.multiplatform-benchmarks")
22+
}
23+
24+
kotlin {
25+
jvmTarget()
26+
27+
sourceSets {
28+
jvmMain.dependencies {
29+
implementation(projects.benchmarksShared)
30+
31+
implementation(libs.kotlinx.coroutines.reactor)
32+
implementation(libs.rsocket.java.transport.local)
33+
implementation(libs.rsocket.java.transport.netty)
34+
}
35+
}
36+
}
37+
38+
benchmark {
39+
targets {
40+
register("jvm") {
41+
this as JvmBenchmarkTarget
42+
jmhVersion = libs.versions.jmh.get()
43+
}
44+
}
45+
46+
registerBenchmarks("RSocketJava", listOf("local", "tcp", "ws"))
47+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2015-2025 the original author or authors.
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+
package io.rsocket.kotlin.benchmarks.java
18+
19+
import io.rsocket.transport.*
20+
import io.rsocket.transport.local.*
21+
22+
class LocalRSocketJavaBenchmark : RSocketJavaBenchmark() {
23+
override val serverTransport: ServerTransport<*> = LocalServerTransport.create("local")
24+
override val clientTransport: ClientTransport = LocalClientTransport.create("local")
25+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2022 the original author or authors.
2+
* Copyright 2015-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,32 +14,57 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.rsocket.kotlin.benchmarks
17+
package io.rsocket.kotlin.benchmarks.java
1818

1919
import io.rsocket.*
2020
import io.rsocket.core.*
2121
import io.rsocket.frame.decoder.*
22-
import io.rsocket.transport.local.*
22+
import io.rsocket.kotlin.benchmarks.*
23+
import io.rsocket.transport.*
2324
import io.rsocket.util.*
25+
import kotlinx.benchmark.*
26+
import kotlinx.benchmark.Mode
2427
import kotlinx.coroutines.flow.*
2528
import kotlinx.coroutines.reactive.*
2629
import org.reactivestreams.*
2730
import reactor.core.publisher.*
2831
import kotlin.random.*
2932

30-
class RSocketJavaBenchmark : RSocketBenchmark<Payload>() {
33+
@BenchmarkMode(Mode.Throughput)
34+
@Warmup(iterations = WARMUP, time = WARMUP_DURATION)
35+
@Measurement(iterations = ITERATION, time = ITERATION_DURATION)
36+
@State(Scope.Benchmark)
37+
abstract class RSocketJavaBenchmark : RSocketBenchmark<Payload, Blackhole>() {
38+
protected abstract val clientTransport: ClientTransport
39+
protected abstract val serverTransport: ServerTransport<*>
40+
41+
private lateinit var payload: Payload
42+
private lateinit var payloadMono: Mono<Payload>
43+
private lateinit var payloadsFlux: Flux<Payload>
44+
private lateinit var payloadsFlow: Flow<Payload>
45+
private lateinit var client: RSocket
46+
private lateinit var server: Closeable
3147

32-
lateinit var client: RSocket
33-
lateinit var server: Closeable
48+
override fun createPayload(size: Int): Payload = if (size == 0) EmptyPayload.INSTANCE else ByteBufPayload.create(
49+
ByteArray(size / 2).also { Random.nextBytes(it) },
50+
ByteArray(size / 2).also { Random.nextBytes(it) }
51+
)
52+
53+
override fun createPayloadCopy(): Payload = payload.retain()
54+
55+
override fun releasePayload(payload: Payload) {
56+
payload.release()
57+
}
3458

35-
lateinit var payload: Payload
36-
lateinit var payloadMono: Mono<Payload>
37-
lateinit var payloadsFlux: Flux<Payload>
38-
lateinit var payloadsFlow: Flow<Payload>
59+
override fun consumePayload(bh: Blackhole, value: Payload) = bh.consume(value)
3960

61+
override suspend fun doRequestResponse(): Payload = client.requestResponse(payload.retain()).awaitSingle()
62+
override fun doRequestStream(): Flow<Payload> = client.requestStream(payload.retain()).asFlow()
63+
override fun doRequestChannel(): Flow<Payload> = client.requestChannel(payloadsFlow.asPublisher()).asFlow()
64+
65+
@Setup
4066
override fun setup() {
4167
payload = createPayload(payloadSize)
42-
4368
payloadMono = Mono.fromSupplier(payload::retain)
4469
payloadsFlux = Flux.range(0, 5000).map { payload.retain() }
4570
payloadsFlow = flow { repeat(5000) { emit(payload.retain()) } }
@@ -61,33 +86,48 @@ class RSocketJavaBenchmark : RSocketBenchmark<Payload>() {
6186
})
6287
}
6388
.payloadDecoder(PayloadDecoder.ZERO_COPY)
64-
.bind(LocalServerTransport.create("server"))
89+
.bind(serverTransport)
6590
.block()!!
6691

6792
client = RSocketConnector.create()
6893
.payloadDecoder(PayloadDecoder.ZERO_COPY)
69-
.connect(LocalClientTransport.create("server"))
94+
.connect(clientTransport)
7095
.block()!!
7196
}
7297

98+
@TearDown
7399
override fun cleanup() {
74100
client.dispose()
75101
server.dispose()
76102
}
77103

78-
override fun createPayload(size: Int): Payload = if (size == 0) EmptyPayload.INSTANCE else ByteBufPayload.create(
79-
ByteArray(size / 2).also { Random.nextBytes(it) },
80-
ByteArray(size / 2).also { Random.nextBytes(it) }
81-
)
104+
@Param("0")
105+
override var payloadSize: Int = 0
82106

83-
override fun releasePayload(payload: Payload) {
84-
payload.release()
85-
}
107+
@Benchmark
108+
override fun requestResponseBlocking(bh: Blackhole) = super.requestResponseBlocking(bh)
86109

87-
override suspend fun doRequestResponse(): Payload = client.requestResponse(payload.retain()).awaitSingle()
110+
@Benchmark
111+
override fun requestResponseParallel(bh: Blackhole) = super.requestResponseParallel(bh)
112+
113+
@Benchmark
114+
override fun requestResponseConcurrent(bh: Blackhole) = super.requestResponseConcurrent(bh)
115+
116+
@Benchmark
117+
override fun requestStreamBlocking(bh: Blackhole) = super.requestStreamBlocking(bh)
118+
119+
@Benchmark
120+
override fun requestStreamParallel(bh: Blackhole) = super.requestStreamParallel(bh)
121+
122+
@Benchmark
123+
override fun requestStreamConcurrent(bh: Blackhole) = super.requestStreamConcurrent(bh)
88124

89-
override suspend fun doRequestStream(): Flow<Payload> = client.requestStream(payload.retain()).asFlow()
125+
@Benchmark
126+
override fun requestChannelBlocking(bh: Blackhole) = super.requestChannelBlocking(bh)
90127

91-
override suspend fun doRequestChannel(): Flow<Payload> = client.requestChannel(payloadsFlow.asPublisher()).asFlow()
128+
@Benchmark
129+
override fun requestChannelParallel(bh: Blackhole) = super.requestChannelParallel(bh)
92130

131+
@Benchmark
132+
override fun requestChannelConcurrent(bh: Blackhole) = super.requestChannelConcurrent(bh)
93133
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2015-2025 the original author or authors.
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+
package io.rsocket.kotlin.benchmarks.java
18+
19+
import io.rsocket.transport.*
20+
import io.rsocket.transport.netty.client.*
21+
import io.rsocket.transport.netty.server.*
22+
23+
class TcpRSocketJavaBenchmark : RSocketJavaBenchmark() {
24+
override val serverTransport: ServerTransport<*> = TcpServerTransport.create(9000)
25+
override val clientTransport: ClientTransport = TcpClientTransport.create(9000)
26+
}

0 commit comments

Comments
 (0)