Skip to content

Commit

Permalink
Minor cleanup and simplification of readString
Browse files Browse the repository at this point in the history
* Request Long.MAX_VALUE from the source at once (note: no need for a loop as we are unable to build the string of such size anyway)
* Get rid of redundant checks in commonReadUtf8

Ticks one of the boxes in #342
  • Loading branch information
qwwdfsad committed Aug 21, 2024
1 parent 046523f commit 08040c7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 11 deletions.
11 changes: 10 additions & 1 deletion benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,13 @@ Currently, the suite includes benchmarks on:
- segment pooling performance.

The suite doesn't include benchmarks for more complex APIs inherited from Okio as these APIs are subject to change.
Such benchmarks will be added later along with corresponding changes in the library.
Such benchmarks will be added later along with corresponding changes in the library.

### Quickstart

For JVM:
```
./gradlew :kotlinx-io-benchmarks:jvmJar
java -jar benchmarks/build/benchmarks/jvm/jars/kotlinx-io-benchmarks-jvm-jmh-0.6.0-SNAPSHOT-JMH.jar ReadStringBenchmark -f 1 -wi 5 -i 5 -tu us -w 1 -r 1
```
42 changes: 42 additions & 0 deletions benchmarks/src/commonMain/kotlin/ReadStringBenchmark.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package kotlinx.io.benchmarks

import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Param
import kotlinx.benchmark.Scope
import kotlinx.benchmark.Setup
import kotlinx.benchmark.State
import kotlinx.io.Buffer
import kotlinx.io.Source
import kotlinx.io.readCodePointValue
import kotlinx.io.readString
import kotlinx.io.writeCodePointValue
import kotlinx.io.writeString
import kotlin.random.Random


@State(Scope.Benchmark)
open class ReadStringBenchmark() {

@Param("16", "64", "512")
var size: Int = 0

val buffer: Buffer = Buffer()

@Setup
fun setup() {
val string = buildString { repeat(size) { append(('a'..'z').random()) } }
buffer.writeString(string)
}


@Benchmark
fun bufferReadString(): String {
return buffer.copy().readString()
}

@Benchmark
fun sourceReadString(): String {
val source: Source = buffer.copy()
return source.readString()
}
}
13 changes: 3 additions & 10 deletions core/common/src/Utf8.kt
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,7 @@ public fun Sink.writeString(chars: CharSequence, startIndex: Int = 0, endIndex:
*/
@OptIn(InternalIoApi::class)
public fun Source.readString(): String {
var req: Long = Segment.SIZE.toLong()
while (request(req)) {
req *= 2
}
request(Long.MAX_VALUE) // Request all data
return buffer.commonReadUtf8(buffer.size)
}

Expand Down Expand Up @@ -595,16 +592,12 @@ private fun Buffer.commonWriteUtf8CodePoint(codePoint: Int) {
}

private fun Buffer.commonReadUtf8(byteCount: Long): String {
require(byteCount >= 0 && byteCount <= Int.MAX_VALUE) {
"byteCount ($byteCount) is not within the range [0..${Int.MAX_VALUE})"
}
require(byteCount)
// Invariant: byteCount was request()'ed into this buffer beforehand
if (byteCount == 0L) return ""

val s = head!!
if (s.pos + byteCount > s.limit) {
// If the string spans multiple segments, delegate to readBytes().

// If the string spans multiple segments, delegate to readBytes()
return readByteArray(byteCount.toInt()).commonToUtf8String()
}

Expand Down

0 comments on commit 08040c7

Please sign in to comment.