[K/N] Added benchmarks for KT-46482 and KT-46425
This commit is contained in:
@@ -210,7 +210,9 @@ class RingLauncher : Launcher() {
|
|||||||
"Casts.interfaceCast" to BenchmarkEntryWithInit.create(::CastsBenchmark, { interfaceCast() }),
|
"Casts.interfaceCast" to BenchmarkEntryWithInit.create(::CastsBenchmark, { interfaceCast() }),
|
||||||
"LocalObjects.localArray" to BenchmarkEntryWithInit.create(::LocalObjectsBenchmark, { localArray() }),
|
"LocalObjects.localArray" to BenchmarkEntryWithInit.create(::LocalObjectsBenchmark, { localArray() }),
|
||||||
"LinkedListWithAtomicsBenchmark" to BenchmarkEntryWithInit.create(::LinkedListWithAtomicsBenchmark, { ensureNext() }),
|
"LinkedListWithAtomicsBenchmark" to BenchmarkEntryWithInit.create(::LinkedListWithAtomicsBenchmark, { ensureNext() }),
|
||||||
"Inheritance.baseCalls" to BenchmarkEntryWithInit.create(::InheritanceBenchmark, { baseCalls() })
|
"Inheritance.baseCalls" to BenchmarkEntryWithInit.create(::InheritanceBenchmark, { baseCalls() }),
|
||||||
|
"ChainableBenchmark.testChainable" to BenchmarkEntryWithInit.create(::ChainableBenchmark, { testChainable() }),
|
||||||
|
"BunnymarkBenchmark.testBunnymark" to BenchmarkEntryWithInit.create(::BunnymarkBenchmark, { testBunnymark() })
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.ring
|
||||||
|
|
||||||
|
import org.jetbrains.benchmarksLauncher.Blackhole
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
// Benchmark for KT-46425.
|
||||||
|
open class BunnymarkBenchmark {
|
||||||
|
|
||||||
|
val maxX = 640f
|
||||||
|
val minX = 0f
|
||||||
|
val maxY = 480f
|
||||||
|
val minY = 0f
|
||||||
|
val gravity = 0.5f
|
||||||
|
val framesCount = 60
|
||||||
|
val containerSize = 800_000
|
||||||
|
|
||||||
|
//Benchmark
|
||||||
|
fun testBunnymark() {
|
||||||
|
val bunnys = BunnyContainer(containerSize)
|
||||||
|
|
||||||
|
for (n in 0 until bunnys.maxSize) bunnys.alloc()
|
||||||
|
|
||||||
|
val random = Random(0)
|
||||||
|
|
||||||
|
fun executeFrame() {
|
||||||
|
bunnys.fastForEach { bunny ->
|
||||||
|
bunny.x += bunny.speedXf
|
||||||
|
bunny.y += bunny.speedYf
|
||||||
|
bunny.speedYf += gravity
|
||||||
|
|
||||||
|
if (bunny.x > maxX) {
|
||||||
|
bunny.speedXf *= -1
|
||||||
|
bunny.x = maxX
|
||||||
|
} else if (bunny.x < minX) {
|
||||||
|
bunny.speedXf *= -1
|
||||||
|
bunny.x = minX
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bunny.y > maxY) {
|
||||||
|
bunny.speedYf *= -0.85f
|
||||||
|
bunny.y = maxY
|
||||||
|
bunny.radiansf = (random.nextFloat() - 0.5f) * 0.2f
|
||||||
|
if (random.nextFloat() > 0.5) {
|
||||||
|
bunny.speedYf -= random.nextFloat() * 6
|
||||||
|
}
|
||||||
|
} else if (bunny.y < minY) {
|
||||||
|
bunny.speedYf = 0f
|
||||||
|
bunny.y = minY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n in 0 until framesCount) {
|
||||||
|
executeFrame()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BunnyContainer(maxSize: Int) : FSprites(maxSize) {
|
||||||
|
val speeds = FBuffer(maxSize * Float.SIZE_BYTES * 2).f32
|
||||||
|
var FSprite.speedXf: Float get() = speeds[index * 2 + 0] ; set(value) { speeds[index * 2 + 0] = value }
|
||||||
|
var FSprite.speedYf: Float get() = speeds[index * 2 + 1] ; set(value) { speeds[index * 2 + 1] = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
open class FSprites(val maxSize: Int) {
|
||||||
|
var size = 0
|
||||||
|
val data = FBuffer(maxSize * FSprites.STRIDE * 4)
|
||||||
|
|
||||||
|
val f32 = data.f32
|
||||||
|
|
||||||
|
fun alloc() = FSprite(size++ * STRIDE)
|
||||||
|
|
||||||
|
var FSprite.x: Float get() = f32[offset + 0]; set(value) { f32[offset + 0] = value }
|
||||||
|
var FSprite.y: Float get() = f32[offset + 1]; set(value) { f32[offset + 1] = value }
|
||||||
|
var FSprite.radiansf: Float get() = f32[offset + 4] ; set(value) { f32[offset + 4] = value }
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val STRIDE = 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : FSprites> T.fastForEach(callback: T.(sprite: FSprite) -> Unit) {
|
||||||
|
var m = 0
|
||||||
|
for (n in 0 until size) {
|
||||||
|
callback(FSprite(m))
|
||||||
|
m += FSprites.STRIDE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline class FSprite(val id: Int) {
|
||||||
|
inline val offset get() = id
|
||||||
|
inline val index get() = offset / FSprites.STRIDE
|
||||||
|
}
|
||||||
|
|
||||||
|
class FBuffer private constructor(val mem: MemBuffer, val size: Int = mem.size) {
|
||||||
|
val arrayFloat: Float32Buffer = mem.asFloat32Buffer()
|
||||||
|
|
||||||
|
inline val f32 get() = arrayFloat
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun Int.sizeAligned() = (this + 0xF) and 0xF.inv()
|
||||||
|
operator fun invoke(size: Int): FBuffer = FBuffer(MemBufferAlloc(size.sizeAligned()), size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemBuffer(val data: ByteArray)
|
||||||
|
inline val MemBuffer.size: Int get() = data.size
|
||||||
|
|
||||||
|
class Float32Buffer(val mbuffer: MemBuffer, val byteOffset: Int, val size: Int) {
|
||||||
|
companion object {
|
||||||
|
const val SIZE = 4
|
||||||
|
}
|
||||||
|
val MEM_OFFSET = byteOffset / SIZE
|
||||||
|
val MEM_SIZE = size / SIZE
|
||||||
|
fun getByteIndex(index: Int) = byteOffset + index * SIZE
|
||||||
|
}
|
||||||
|
val Float32Buffer.mem: MemBuffer get() = mbuffer
|
||||||
|
val Float32Buffer.offset: Int get() = MEM_OFFSET
|
||||||
|
val Float32Buffer.size: Int get() = MEM_SIZE
|
||||||
|
operator fun Float32Buffer.get(index: Int): Float = mbuffer.getFloat(getByteIndex(index))
|
||||||
|
operator fun Float32Buffer.set(index: Int, value: Float): Unit = mbuffer.setFloat(getByteIndex(index), value)
|
||||||
|
|
||||||
|
fun MemBufferAlloc(size: Int): MemBuffer = MemBuffer(ByteArray(size))
|
||||||
|
|
||||||
|
fun MemBuffer.getFloat(index: Int): Float = data.getFloatAt(index)
|
||||||
|
fun MemBuffer.setFloat(index: Int, value: Float): Unit = data.setFloatAt(index, value)
|
||||||
|
|
||||||
|
fun MemBuffer.asFloat32Buffer(): Float32Buffer = this.sliceFloat32Buffer()
|
||||||
|
fun MemBuffer.sliceFloat32Buffer(offset: Int = 0, size: Int = (this.size / 4) - offset): Float32Buffer = this._sliceFloat32Buffer(offset, size)
|
||||||
|
fun MemBuffer._sliceFloat32Buffer(offset: Int, size: Int): Float32Buffer =
|
||||||
|
Float32Buffer(this, offset * 4, size)
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.ring
|
||||||
|
|
||||||
|
import org.jetbrains.benchmarksLauncher.Blackhole
|
||||||
|
import org.jetbrains.benchmarksLauncher.Random
|
||||||
|
|
||||||
|
// Benchmark from KT-46482.
|
||||||
|
open class ChainableBenchmark {
|
||||||
|
|
||||||
|
class IntArrayList(capacity: Int = 7) {
|
||||||
|
private var data: IntArray = IntArray(capacity)
|
||||||
|
var size: Int = 0
|
||||||
|
private set
|
||||||
|
val capacity get() = data.size
|
||||||
|
private fun grow(minSize: Int) {
|
||||||
|
data = data.copyOf(kotlin.math.max(minSize, capacity * 3))
|
||||||
|
}
|
||||||
|
private fun ensure(count: Int) {
|
||||||
|
if (size + count >= capacity) {
|
||||||
|
grow(size + count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(value: Int) {
|
||||||
|
ensure(1)
|
||||||
|
data[size++] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addChainable(value: Int): IntArrayList {
|
||||||
|
add(value)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(index: Int): Int = data[index]
|
||||||
|
operator fun set(index: Int, value: Int) {
|
||||||
|
data[index] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val size = BENCHMARK_SIZE * 100
|
||||||
|
|
||||||
|
//Benchmark
|
||||||
|
fun testChainable() {
|
||||||
|
val list = IntArrayList()
|
||||||
|
for (i in 0..size) {
|
||||||
|
list.addChainable(i)
|
||||||
|
}
|
||||||
|
for (i in 0..size) {
|
||||||
|
list[i] = i * 2
|
||||||
|
}
|
||||||
|
var sum = 0
|
||||||
|
for (i in 0..size) {
|
||||||
|
sum += list[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user