From f2921b0dccbd0e8b7f283477f8f506144dd7d663 Mon Sep 17 00:00:00 2001 From: Konstantin Anisimov Date: Thu, 17 Aug 2017 16:25:31 +0700 Subject: [PATCH] OctoTest benchmark inserted in testsuite --- performance/src/main/kotlin/main.kt | 3 + .../org/jetbrains/ring/OctoTest/basicTest.kt | 46 ++++++ .../org/jetbrains/ring/OctoTest/ocTree.kt | 138 ++++++++++++++++++ .../kotlin/org/jetbrains/ring/launcher.kt | 38 ++++- .../main/kotlin/org/jetbrains/ring/norma.kt | 3 +- 5 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 performance/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt create mode 100644 performance/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt diff --git a/performance/src/main/kotlin/main.kt b/performance/src/main/kotlin/main.kt index 15bd313f0eb..123b54a971b 100644 --- a/performance/src/main/kotlin/main.kt +++ b/performance/src/main/kotlin/main.kt @@ -9,5 +9,8 @@ fun main(args: Array) { numMeasureIterations = args[1].toInt() } + println("Ring starting") + println(" warmup iterations count: $numWarmIterations") + println(" measure iterations count: $numMeasureIterations") Launcher(numWarmIterations, numMeasureIterations).runBenchmarks() } \ No newline at end of file diff --git a/performance/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt b/performance/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt new file mode 100644 index 00000000000..b6b7cc129db --- /dev/null +++ b/performance/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt @@ -0,0 +1,46 @@ +/** + * Created by semoro on 07.07.17. + */ +fun octoTest() { + val tree = OctoTree(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++ + } +} diff --git a/performance/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt b/performance/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt new file mode 100644 index 00000000000..37ad4f6630e --- /dev/null +++ b/performance/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt @@ -0,0 +1,138 @@ + +open class OctoTree(val depth: Int) { + + private var root: Node? = 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).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 { + + abstract fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean + + //---------------------------------------------------------------------// + + class Leaf(var value: T) : Node() { + + 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() : Node() { + + 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 -> { + 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>(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 + } + } +} diff --git a/performance/src/main/kotlin/org/jetbrains/ring/launcher.kt b/performance/src/main/kotlin/org/jetbrains/ring/launcher.kt index 700d1e75731..683d689f87c 100644 --- a/performance/src/main/kotlin/org/jetbrains/ring/launcher.kt +++ b/performance/src/main/kotlin/org/jetbrains/ring/launcher.kt @@ -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() - 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() diff --git a/performance/src/main/kotlin/org/jetbrains/ring/norma.kt b/performance/src/main/kotlin/org/jetbrains/ring/norma.kt index 4b55d880a61..3988f4cbbea 100644 --- a/performance/src/main/kotlin/org/jetbrains/ring/norma.kt +++ b/performance/src/main/kotlin/org/jetbrains/ring/norma.kt @@ -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 )