Skip to content

Commit 08040c7

Browse files
committed
Minor cleanup and simplification of readString
* 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
1 parent 046523f commit 08040c7

File tree

3 files changed

+55
-11
lines changed

3 files changed

+55
-11
lines changed

benchmarks/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,13 @@ Currently, the suite includes benchmarks on:
88
- segment pooling performance.
99

1010
The suite doesn't include benchmarks for more complex APIs inherited from Okio as these APIs are subject to change.
11-
Such benchmarks will be added later along with corresponding changes in the library.
11+
Such benchmarks will be added later along with corresponding changes in the library.
12+
13+
### Quickstart
14+
15+
For JVM:
16+
```
17+
./gradlew :kotlinx-io-benchmarks:jvmJar
18+
19+
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
20+
```
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package kotlinx.io.benchmarks
2+
3+
import kotlinx.benchmark.Benchmark
4+
import kotlinx.benchmark.Param
5+
import kotlinx.benchmark.Scope
6+
import kotlinx.benchmark.Setup
7+
import kotlinx.benchmark.State
8+
import kotlinx.io.Buffer
9+
import kotlinx.io.Source
10+
import kotlinx.io.readCodePointValue
11+
import kotlinx.io.readString
12+
import kotlinx.io.writeCodePointValue
13+
import kotlinx.io.writeString
14+
import kotlin.random.Random
15+
16+
17+
@State(Scope.Benchmark)
18+
open class ReadStringBenchmark() {
19+
20+
@Param("16", "64", "512")
21+
var size: Int = 0
22+
23+
val buffer: Buffer = Buffer()
24+
25+
@Setup
26+
fun setup() {
27+
val string = buildString { repeat(size) { append(('a'..'z').random()) } }
28+
buffer.writeString(string)
29+
}
30+
31+
32+
@Benchmark
33+
fun bufferReadString(): String {
34+
return buffer.copy().readString()
35+
}
36+
37+
@Benchmark
38+
fun sourceReadString(): String {
39+
val source: Source = buffer.copy()
40+
return source.readString()
41+
}
42+
}

core/common/src/Utf8.kt

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,7 @@ public fun Sink.writeString(chars: CharSequence, startIndex: Int = 0, endIndex:
203203
*/
204204
@OptIn(InternalIoApi::class)
205205
public fun Source.readString(): String {
206-
var req: Long = Segment.SIZE.toLong()
207-
while (request(req)) {
208-
req *= 2
209-
}
206+
request(Long.MAX_VALUE) // Request all data
210207
return buffer.commonReadUtf8(buffer.size)
211208
}
212209

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

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

604598
val s = head!!
605599
if (s.pos + byteCount > s.limit) {
606-
// If the string spans multiple segments, delegate to readBytes().
607-
600+
// If the string spans multiple segments, delegate to readBytes()
608601
return readByteArray(byteCount.toInt()).commonToUtf8String()
609602
}
610603

0 commit comments

Comments
 (0)