@@ -33,6 +33,7 @@ ChannelCopyBenchmark.runBlockingAndLaunch avgt 5 833,390 ± 14,96
33
33
@State(Scope .Benchmark )
34
34
@Fork(1 )
35
35
open class ChannelCopyBenchmark {
36
+ private val HelloWorld = " Hello, World!" .toByteArray()
36
37
private val ABC = " ABC" .repeat(100 ).toByteArray()
37
38
private val buffer = ByteArray (4096 )
38
39
private val ioe = IOException ()
@@ -76,6 +77,26 @@ open class ChannelCopyBenchmark {
76
77
read
77
78
}
78
79
80
+ @Benchmark
81
+ fun cioChannelCopyHW () = runBlocking {
82
+ val pIn = ByteChannel (true )
83
+ val pOut = ByteChannel (true )
84
+
85
+ pOut.writeFully(HelloWorld )
86
+ pOut.close()
87
+
88
+ pOut.copyAndClose(pIn)
89
+
90
+ var read = 0
91
+ while (read < HelloWorld .size) {
92
+ val rc = pIn.readAvailable(buffer)
93
+ if (rc == - 1 ) break
94
+ read + = rc
95
+ }
96
+
97
+ read
98
+ }
99
+
79
100
@Benchmark
80
101
fun cioJoinToClosed () = runBlocking {
81
102
val pIn = ByteChannel (true )
@@ -96,6 +117,53 @@ open class ChannelCopyBenchmark {
96
117
read
97
118
}
98
119
120
+ @Benchmark
121
+ fun cioJoinToClosedHW () = runBlocking {
122
+ val pIn = ByteChannel (true )
123
+ val pOut = ByteChannel (true )
124
+
125
+ pOut.writeFully(HelloWorld )
126
+ pOut.close()
127
+
128
+ pOut.joinTo(pIn, true )
129
+
130
+ var read = 0
131
+ while (read < HelloWorld .size) {
132
+ val rc = pIn.readAvailable(buffer)
133
+ if (rc == - 1 ) break
134
+ read + = rc
135
+ }
136
+
137
+ read
138
+ }
139
+
140
+
141
+ @Benchmark
142
+ fun cioCopyFromEmpty () = runCoroutineFast {
143
+ val from = ByteChannel (true )
144
+ val to = ByteChannel (true )
145
+
146
+ from.close()
147
+ from.copyAndClose(to)
148
+ }
149
+
150
+ @Benchmark
151
+ fun cioJoinFromEmpty () = runCoroutineFast {
152
+ val from = ByteChannel (true )
153
+ val to = ByteChannel (true )
154
+
155
+ from.close()
156
+ from.joinTo(to, true )
157
+ }
158
+
159
+ @Benchmark
160
+ fun cioJoinFromEmptyNonClosed () = runCoroutineFast(allowSuspend = true ) {
161
+ val from = ByteChannel (true )
162
+ val to = ByteChannel (true )
163
+
164
+ from.joinTo(to, true ) // should setup joining and suspend
165
+ }
166
+
99
167
@Benchmark
100
168
fun cioJoinToBeforeWrite () = runBlocking {
101
169
val pIn = ByteChannel (true )
@@ -120,6 +188,30 @@ open class ChannelCopyBenchmark {
120
188
read
121
189
}
122
190
191
+ @Benchmark
192
+ fun cioJoinToHWBeforeWrite () = runBlocking {
193
+ val pIn = ByteChannel (true )
194
+ val pOut = ByteChannel (true )
195
+
196
+ launch(coroutineContext) {
197
+ pOut.joinTo(pIn, true )
198
+ }
199
+
200
+ yield ()
201
+
202
+ pOut.writeFully(HelloWorld )
203
+ pOut.close()
204
+
205
+ var read = 0
206
+ while (read < HelloWorld .size) {
207
+ val rc = pIn.readAvailable(buffer)
208
+ if (rc == - 1 ) break
209
+ read + = rc
210
+ }
211
+
212
+ read
213
+ }
214
+
123
215
@Benchmark
124
216
fun cioCopyToInLaunch () = runBlocking {
125
217
val pIn = ByteChannel (true )
@@ -145,6 +237,31 @@ open class ChannelCopyBenchmark {
145
237
read
146
238
}
147
239
240
+ @Benchmark
241
+ fun cioCopyToHWInLaunch () = runBlocking {
242
+ val pIn = ByteChannel (true )
243
+ val pOut = ByteChannel (true )
244
+
245
+ launch(coroutineContext) {
246
+ pOut.copyTo(pIn)
247
+ pIn.close()
248
+ }
249
+
250
+ yield ()
251
+
252
+ pOut.writeFully(HelloWorld )
253
+ pOut.close()
254
+
255
+ var read = 0
256
+ while (read < HelloWorld .size) {
257
+ val rc = pIn.readAvailable(buffer)
258
+ if (rc == - 1 ) break
259
+ read + = rc
260
+ }
261
+
262
+ read
263
+ }
264
+
148
265
@Benchmark
149
266
fun cioJustWrite () = runBlocking {
150
267
val c = ByteChannel ()
@@ -153,7 +270,7 @@ open class ChannelCopyBenchmark {
153
270
}
154
271
155
272
@Benchmark
156
- fun cioJustWriteUnintercepted () = runForSureNoSuspend {
273
+ fun cioJustWriteUnintercepted () = runCoroutineFast {
157
274
val c = ByteChannel ()
158
275
c.writeFully(ABC )
159
276
c.close(ioe)
@@ -168,7 +285,7 @@ open class ChannelCopyBenchmark {
168
285
}
169
286
170
287
@Benchmark
171
- fun cioReadAndWriteUnintercepted () = runForSureNoSuspend {
288
+ fun cioReadAndWriteUnintercepted () = runCoroutineFast {
172
289
val c = ByteChannel (true )
173
290
c.writeFully(ABC )
174
291
c.readAvailable(buffer)
@@ -188,9 +305,10 @@ open class ChannelCopyBenchmark {
188
305
yield ()
189
306
}
190
307
191
- private fun runForSureNoSuspend ( block : suspend () -> Unit ) {
308
+ private fun runCoroutineFast ( allowSuspend : Boolean = false, block : suspend () -> Unit ) {
192
309
if (block.startCoroutineUninterceptedOrReturn(EmptyContinuation ) == = COROUTINE_SUSPENDED ) {
193
- throw IllegalStateException (" Unexpected suspend" )
310
+ if (! allowSuspend)
311
+ throw IllegalStateException (" Unexpected suspend" )
194
312
}
195
313
}
196
314
0 commit comments