OctoTest benchmark inserted in testsuite

This commit is contained in:
Konstantin Anisimov
2017-08-17 16:25:31 +07:00
committed by KonstantinAnisimov
parent 99dd7227dc
commit f2921b0dcc
5 changed files with 219 additions and 9 deletions
+3
View File
@@ -9,5 +9,8 @@ fun main(args: Array<String>) {
numMeasureIterations = args[1].toInt()
}
println("Ring starting")
println(" warmup iterations count: $numWarmIterations")
println(" measure iterations count: $numMeasureIterations")
Launcher(numWarmIterations, numMeasureIterations).runBenchmarks()
}
@@ -0,0 +1,46 @@
/**
* Created by semoro on 07.07.17.
*/
fun octoTest() {
val tree = OctoTree<Boolean>(4)
val to = (2 shl tree.depth)
var x = 0
var y = 0
var z = 0
while (x < to) {
y = 0
while (y < to) {
z = 0
while (z < to) {
val c = (z + to * y + to * to * x) % 2 == 0
tree.set(x, y, z, c)
z++
}
y++
}
x++
}
x = 0
y = 0
z = 0
while (x < to) {
y = 0
while (y < to) {
z = 0
while (z < to) {
val c = (z + to * y + to * to * x) % 2 == 0
val res = tree.get(x, y, z)
assert(res == c)
z++
}
y++
}
x++
}
}
@@ -0,0 +1,138 @@
open class OctoTree<T>(val depth: Int) {
private var root: Node<T>? = null
private var actual = false
//-------------------------------------------------------------------------//
fun get(x: Int, y: Int, z: Int): T? {
var dep = depth
var iter = root
while (true) {
if (iter == null) return null
else if (iter is Node.Leaf) return iter.value
iter = (iter as Node.Branch<T>).nodes[number(x, y, z, --dep)]
}
}
//-------------------------------------------------------------------------//
fun set(x: Int, y: Int, z: Int, value: T) {
if (root == null) root = Node.Branch()
if (root!!.set(x, y, z, value, depth - 1)) {
root = Node.Leaf(value)
}
actual = false
}
//-------------------------------------------------------------------------//
override fun toString(): String = root.toString()
//-------------------------------------------------------------------------//
sealed class Node<T> {
abstract fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean
//---------------------------------------------------------------------//
class Leaf<T>(var value: T) : Node<T>() {
override fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean {
throw UnsupportedOperationException("set on Leaf element")
}
override fun toString(): String = "L{$value}"
}
//---------------------------------------------------------------------//
class Branch<T>() : Node<T>() {
constructor(value: T, exclude: Int) : this() {
var i = 0
while (i < 8) {
if (i != exclude) {
nodes[i] = Leaf(value)
}
i++
}
}
private fun canClusterize(value: T): Boolean {
var i = 0
while (i < 8) {
val w = nodes[i]
if (w == null || w !is Leaf || value != w.value) {
return false
}
i++
}
return true
}
override fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean {
val branchIndex = number(x, y, z, depth)
val node = nodes[branchIndex]
when (node) {
null -> {
if (depth == 0) {
nodes[branchIndex] = Leaf(value)
return canClusterize(value)
} else {
nodes[branchIndex] = Branch()
}
}
is Leaf<T> -> {
if (node.value == value) {
return false
} else if (depth == 0) {
node.value = value
return canClusterize(value)
}
nodes[branchIndex] = Branch(node.value, number(x, y, z, depth - 1))
}
}
if (nodes[branchIndex]!!.set(x, y, z, value, depth - 1)) {
nodes[branchIndex] = Leaf(value)
return canClusterize(value)
}
return false
}
val nodes = arrayOfNulls<Node<T>>(8)
override fun toString(): String = nodes.joinToString(prefix = "[", postfix = "]")
}
}
//-------------------------------------------------------------------------//
companion object {
fun number(x: Int, y: Int, z: Int, depth: Int): Int {
val mask = 1 shl depth
if (x and mask != 0) {
if (y and mask != 0) {
if (z and mask != 0)
return 7
return 6
}
if (z and mask != 0)
return 5
return 4
}
if (y and mask != 0) {
if (z and mask != 0)
return 3
return 2
}
if (z and mask != 0)
return 1
return 0
}
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.ring
import octoTest
import kotlin.system.measureNanoTime
val BENCHMARK_SIZE = 100
@@ -25,16 +26,18 @@ val BENCHMARK_SIZE = 100
class Launcher(val numWarmIterations: Int, val numMeasureIterations: Int) {
val results = mutableMapOf<String, Long>()
fun launch(benchmark: () -> Any?): Long {
var i = numWarmIterations
var j = numMeasureIterations
fun launch(benchmark: () -> Any?, coeff: Double = 1.0): Long { // If benchmark runs too long - use coeff to speed it up.
var i = (numWarmIterations * coeff).toInt()
var j = (numMeasureIterations * coeff).toInt()
while (i-- > 0) benchmark()
val time = measureNanoTime {
while (j-- > 0) benchmark()
while (j-- > 0) {
benchmark()
}
}
return time / numMeasureIterations
return (time / numMeasureIterations / coeff).toLong()
}
//-------------------------------------------------------------------------//
@@ -63,16 +66,29 @@ class Launcher(val numWarmIterations: Int, val numMeasureIterations: Int) {
runStringBenchmark()
runSwitchBenchmark()
runWithIndiciesBenchmark()
runOctoTest()
printResults()
printResultsNormalized()
}
//-------------------------------------------------------------------------//
fun printResults() {
fun printResultsAsTime() {
results.forEach {
val niceName = "\"${it.key}\"".padEnd(51)
val niceTime = "${it.value}".padStart(10)
println(" $niceName to ${niceTime}L,")
}
}
//-------------------------------------------------------------------------//
fun printResultsNormalized() {
var total = 0.0
results.forEach {
val normaTime = NormaResults[it.key]
if (normaTime == null) println("ERROR: no norma for benchmark ${it.key}")
val norma = it.value.toDouble() / normaTime!!.toDouble()
val niceName = it.key.padEnd(50, ' ')
val niceNorma = norma.toString(2).padStart(10, ' ')
@@ -417,7 +433,13 @@ class Launcher(val numWarmIterations: Int, val numMeasureIterations: Int) {
results["WithIndicies.withIndiciesManual"] = launch(benchmark::withIndiciesManual)
}
//-----------------------------------------------------------------------------//
//-------------------------------------------------------------------------//
fun runOctoTest() {
results["OctoTest"] = launch(::octoTest, 0.1)
}
//-------------------------------------------------------------------------//
fun Double.toString(n: Int): String {
val str = this.toString()
@@ -173,5 +173,6 @@ val NormaResults = mapOf(
"Switch.testDenseEnumsSwitch" to 208L,
"Switch.testSealedWhenSwitch" to 172L,
"WithIndicies.withIndicies" to 2303L,
"WithIndicies.withIndiciesManual" to 2256L
"WithIndicies.withIndiciesManual" to 2256L,
"OctoTest" to 2515062L
)