Skip to content

Commit 80cbdd8

Browse files
authored
Add a benchmark on individual Unicode codepoints reading/writing (#320)
1 parent 4019a7e commit 80cbdd8

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

benchmarks/src/commonMain/kotlin/BufferOps.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package kotlinx.io.benchmarks
88
import kotlinx.benchmark.*
99
import kotlinx.io.*
1010
import kotlinx.io.bytestring.ByteString
11+
import kotlin.random.Random
1112

1213
@State(Scope.Benchmark)
1314
abstract class BufferRWBenchmarkBase {
@@ -415,3 +416,67 @@ open class IndexOfByteString {
415416
@Benchmark
416417
fun benchmark() = buffer.indexOf(byteString)
417418
}
419+
420+
@State(Scope.Benchmark)
421+
open class Utf8CodePointsBenchmark : BufferRWBenchmarkBase() {
422+
private val codePointsCount = 128
423+
424+
// Encoding names follow naming from Utf8StringBenchmark
425+
@Param("ascii", "utf8", "sparse", "2bytes", "3bytes", "4bytes", "bad")
426+
var encoding: String = "ascii"
427+
428+
override fun padding(): ByteArray {
429+
return ByteArray(minGap) { '.'.code.toByte() }
430+
}
431+
432+
private val codePoints = IntArray(codePointsCount)
433+
private var codePointIdx = 0
434+
435+
@Setup
436+
fun fillCodePointsArray() {
437+
fun IntArray.fill(generator: () -> Int) {
438+
for (idx in this.indices) {
439+
this[idx] = generator()
440+
}
441+
}
442+
443+
when (encoding) {
444+
"ascii" -> codePoints.fill { Random.nextInt(' '.code, '~'.code) }
445+
"utf8" -> codePoints.fill {
446+
var cp: Int
447+
do {
448+
cp = Random.nextInt(0, 0x10ffff)
449+
} while (cp in 0xd800 .. 0xdfff)
450+
cp
451+
}
452+
"sparse" -> {
453+
codePoints.fill { Random.nextInt(' '.code, '~'.code) }
454+
codePoints[42] = ''.code
455+
}
456+
"2bytes" -> codePoints.fill { Random.nextInt(0x80, 0x800) }
457+
"3bytes" -> codePoints.fill {
458+
var cp: Int
459+
do {
460+
cp = Random.nextInt(0x800, 0x10000)
461+
} while (cp in 0xd800 .. 0xdfff)
462+
cp
463+
}
464+
"4bytes" -> codePoints.fill { Random.nextInt(0x10000, 0x10ffff) }
465+
"bad" -> codePoints.fill { Random.nextInt(0xd800, 0xdfff) }
466+
}
467+
}
468+
469+
470+
private fun nextCodePoint(): Int {
471+
val idx = codePointIdx
472+
val cp = codePoints[idx]
473+
codePointIdx = (idx + 1) % codePointsCount
474+
return cp
475+
}
476+
477+
@Benchmark
478+
fun benchmark(): Int {
479+
buffer.writeCodePointValue(nextCodePoint())
480+
return buffer.readCodePointValue()
481+
}
482+
}

0 commit comments

Comments
 (0)