Make JS benchmarks of expressions #451
@ -13,13 +13,22 @@ sourceSets.register("benchmarks")
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.kotlin.link")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
|
||||
js(IR) {
|
||||
nodejs()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
all {
|
||||
languageSettings {
|
||||
progressiveMode = true
|
||||
}
|
||||
}
|
||||
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation(project(":kmath-ast"))
|
||||
@ -29,9 +38,8 @@ kotlin {
|
||||
implementation(project(":kmath-stat"))
|
||||
implementation(project(":kmath-dimensions"))
|
||||
implementation(project(":kmath-for-real"))
|
||||
implementation(project(":kmath-jafama"))
|
||||
implementation(project(":kmath-tensors"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2")
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +50,7 @@ kotlin {
|
||||
implementation(project(":kmath-nd4j"))
|
||||
implementation(project(":kmath-kotlingrad"))
|
||||
implementation(project(":kmath-viktor"))
|
||||
implementation(project(":kmath-jafama"))
|
||||
implementation(project(":kmath-multik"))
|
||||
implementation("org.nd4j:nd4j-native:1.0.0-M1")
|
||||
// uncomment if your system supports AVX2
|
||||
@ -63,6 +72,7 @@ benchmark {
|
||||
// Setup configurations
|
||||
targets {
|
||||
register("jvm")
|
||||
register("js")
|
||||
}
|
||||
|
||||
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
||||
@ -88,7 +98,11 @@ benchmark {
|
||||
}
|
||||
|
||||
configurations.register("expressions") {
|
||||
commonConfiguration()
|
||||
// Some extra precision
|
||||
warmups = 2
|
||||
iterations = 10
|
||||
iterationTime = 2000
|
||||
iterationTimeUnit = "ms"
|
||||
include("ExpressionsInterpretersBenchmark")
|
||||
}
|
||||
|
||||
@ -125,7 +139,6 @@ afterEvaluate {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kotlin.sourceSets.all {
|
||||
with(languageSettings) {
|
||||
optIn("kotlin.contracts.ExperimentalContracts")
|
||||
@ -141,7 +154,6 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readme {
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
||||
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sin
|
||||
import kotlin.random.Random
|
||||
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
class ExpressionsInterpretersBenchmark {
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [expressionInExtendedField].
|
||||
*/
|
||||
@Benchmark
|
||||
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [toExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun wasmExpression(blackhole: Blackhole) = invokeAndSum(wasm, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun estreeExpression(blackhole: Blackhole) = invokeAndSum(estree, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
|
||||
*/
|
||||
@Benchmark
|
||||
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for direct computation w/o [Expression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun justCalculate(blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
|
||||
repeat(times) {
|
||||
val x = random.nextDouble()
|
||||
sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
val m = HashMap<Symbol, Double>()
|
||||
|
||||
repeat(times) {
|
||||
m[x] = random.nextDouble()
|
||||
sum += expr(m)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
private const val times = 1_000_000
|
||||
|
||||
private val functional = DoubleField.expression {
|
||||
val x = bindSymbol(Symbol.x)
|
||||
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
|
||||
private val node = MstExtendedField {
|
||||
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||
}
|
||||
|
||||
private val mst = node.toExpression(DoubleField)
|
||||
private val wasm = node.wasmCompileToExpression(DoubleField)
|
||||
private val estree = node.estreeCompileToExpression(DoubleField)
|
||||
|
||||
private val raw = Expression<Double> { args ->
|
||||
val x = args[x]!!
|
||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ repositories {
|
||||
|
||||
val toolsVersion: String by extra
|
||||
val kotlinVersion = npmlibs.versions.kotlin.asProvider().get()
|
||||
val benchmarksVersion = npmlibs.versions.kotlinx.benchmark.get()
|
||||
val benchmarksVersion = "0.4.2"
|
||||
|
||||
dependencies {
|
||||
api("ru.mipt.npm:gradle-tools:$toolsVersion")
|
||||
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sin
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.Ignore
|
||||
import kotlin.test.Test
|
||||
import kotlin.time.measureTime
|
||||
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
||||
|
||||
// TODO move to benchmarks when https://github.com/Kotlin/kotlinx-benchmark/pull/38 or similar feature is merged
|
||||
@Ignore
|
||||
internal class TestExecutionTime {
|
||||
private companion object {
|
||||
private const val times = 1_000_000
|
||||
private val x by symbol
|
||||
private val algebra = DoubleField
|
||||
|
||||
private val functional = algebra.expressionInExtendedField {
|
||||
bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x))
|
||||
}
|
||||
|
||||
private val node = MstExtendedField {
|
||||
x * number(2.0) + number(2.0) / x - number(16.0) / sin(x)
|
||||
}
|
||||
|
||||
private val mst = node.toExpression(algebra)
|
||||
private val wasm = node.wasmCompileToExpression(algebra)
|
||||
private val estree = node.estreeCompileToExpression(algebra)
|
||||
|
||||
// In JavaScript, the expression below is implemented like
|
||||
// _no_name_provided__125.prototype.invoke_178 = function (args) {
|
||||
// var tmp = getValue(args, raw$_get_x__3(this._$x$delegate_2)) * 2.0 + 2.0 / getValue(args, raw$_get_x__3(this._$x$delegate_2));
|
||||
// var tmp0_sin_0_5 = getValue(args, raw$_get_x__3(this._$x$delegate_2));
|
||||
// return tmp - 16.0 / Math.sin(tmp0_sin_0_5);
|
||||
// };
|
||||
|
||||
private val raw = Expression<Double> { args ->
|
||||
val x = args[x]!!
|
||||
algebra { x * 2.0 + 2.0 / x - 16.0 / sin(x) }
|
||||
}
|
||||
|
||||
private val justCalculate = { args: dynamic ->
|
||||
val x = args[x].unsafeCast<Double>()
|
||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
}
|
||||
|
||||
private fun invokeAndSum(name: String, expr: Expression<Double>) {
|
||||
println(name)
|
||||
val rng = Random(0)
|
||||
var sum = 0.0
|
||||
measureTime {
|
||||
repeat(times) { sum += expr(x to rng.nextDouble()) }
|
||||
}.also(::println)
|
||||
}
|
||||
|
||||
/**
|
||||
* [Expression] created with [expressionInExtendedField].
|
||||
*/
|
||||
@Test
|
||||
fun functionalExpression() = invokeAndSum("functional", functional)
|
||||
|
||||
/**
|
||||
* [Expression] created with [mstExpression].
|
||||
*/
|
||||
@Test
|
||||
fun mstExpression() = invokeAndSum("mst", mst)
|
||||
|
||||
/**
|
||||
* [Expression] created with [wasmCompileToExpression].
|
||||
*/
|
||||
@Test
|
||||
fun wasmExpression() = invokeAndSum("wasm", wasm)
|
||||
|
||||
/**
|
||||
* [Expression] created with [estreeCompileToExpression].
|
||||
*/
|
||||
@Test
|
||||
fun estreeExpression() = invokeAndSum("estree", wasm)
|
||||
|
||||
/**
|
||||
* [Expression] implemented manually with `kotlin.math`.
|
||||
*/
|
||||
@Test
|
||||
fun rawExpression() = invokeAndSum("raw", raw)
|
||||
|
||||
/**
|
||||
* Direct computation w/o [Expression].
|
||||
*/
|
||||
@Test
|
||||
fun justCalculateExpression() {
|
||||
println("justCalculate")
|
||||
val rng = Random(0)
|
||||
var sum = 0.0
|
||||
measureTime {
|
||||
repeat(times) {
|
||||
val arg = rng.nextDouble()
|
||||
val o = js("{}")
|
||||
o["x"] = arg
|
||||
sum += justCalculate(o)
|
||||
}
|
||||
}.also(::println)
|
||||
}
|
||||
}
|
2059
kotlin-js-store/yarn.lock
Normal file
2059
kotlin-js-store/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user