@@ -8,6 +8,7 @@ package kotlinx.io.benchmarks
88import kotlinx.benchmark.*
99import kotlinx.io.*
1010import kotlinx.io.bytestring.ByteString
11+ import kotlin.random.Random
1112
1213@State(Scope .Benchmark )
1314abstract 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