Skip to content

Instantly share code, notes, and snippets.

@Malinskiy
Last active March 29, 2021 12:18
Show Gist options
  • Save Malinskiy/2dbe05a38321417fd4f23e1872593806 to your computer and use it in GitHub Desktop.
Save Malinskiy/2dbe05a38321417fd4f23e1872593806 to your computer and use it in GitHub Desktop.
package com.malinskiy.adam
import com.malinskiy.adam.transport.withDefaultBuffer
import io.ktor.util.cio.*
import io.ktor.utils.io.*
import kotlinx.coroutines.runBlocking
import org.junit.AfterClass
import org.junit.BeforeClass
import org.junit.Test
import java.io.File
import java.io.RandomAccessFile
import java.nio.ByteBuffer
import kotlin.system.measureTimeMillis
class KtorIoPerformance {
companion object {
private lateinit var testFile: File
@BeforeClass
@JvmStatic
fun setup() {
testFile = File.createTempFile("performance", "test")
testFile.writer().use {
for (i in 0..1024 * 1024 * 128) //~100M
it.append('x')
}
}
@AfterClass
@JvmStatic
fun cleanup() {
testFile.delete()
}
}
@Test
fun testKtorFileRead() {
measure("Ktor channel read (128MiB)") {
var size = 0L
val channel = testFile.readChannel()
while (!channel.isClosedForRead) {
val read = channel.readAvailable(this)
size += read
}
channel.cancel()
}
}
@Test
fun testJvmStreamRead() {
measure("Stream Read (128MiB)") {
testFile.inputStream().buffered().use { stream ->
var size = 0L
while (true) {
val read = stream.read(this)
if (read == -1) break
size += read
}
}
}
}
@Test
fun testJvmRandomFileRead() {
measure("Random File Read (128MiB)") {
val byteBuffer = ByteBuffer.wrap(this)
var size = 0L
RandomAccessFile(testFile, "r").use { file ->
file.channel.use { channel ->
while (true) {
val read = channel.read(byteBuffer)
byteBuffer.clear()
if (read == -1) break
size += read
}
}
}
}
}
private fun measure(name: String, iterations: Int = 20, block: suspend ByteArray.() -> Unit) {
val results = mutableListOf<Long>()
runBlocking {
withDefaultBuffer {
for (i in 1..iterations) {
measureTimeMillis {
block(this.array())
}.let { results.add(it) }
}
}
}
println(
"""
--------------------------------------------------------------------
$name, ${results.size} iterations
Avg: ${results.average()}ms Min: ${results.minOrNull()}ms, Max: ${results.maxOrNull()}ms
Raw: ${results.sorted().joinToString()}
""".trimIndent()
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment