Add naive benchmarks to compare MSTExpression, FunctionalExpressions and ASM Expressions API #108
@ -24,6 +24,7 @@ sourceSets {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":kmath-ast"))
|
||||
implementation(project(":kmath-core"))
|
||||
implementation(project(":kmath-coroutines"))
|
||||
implementation(project(":kmath-commons"))
|
||||
|
@ -0,0 +1,55 @@
|
||||
package scientifik.kmath.ast
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import scientifik.kmath.asm.compile
|
||||
import scientifik.kmath.expressions.expressionInField
|
||||
import scientifik.kmath.expressions.invoke
|
||||
import scientifik.kmath.operations.RealField
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import kotlin.random.Random
|
||||
|
||||
fun main() = runBlocking(Dispatchers.Default) {
|
||||
val mstJob = async { runMst() }
|
||||
val asmJob = async { runAsm() }
|
||||
val feJob = async { runFE() }
|
||||
println("ASM: ${asmJob.await()}")
|
||||
println("FE: ${feJob.await()}")
|
||||
println("MST: ${mstJob.await()}")
|
||||
}
|
||||
|
||||
fun runFE(): Any {
|
||||
val startTime = Instant.now()!!
|
||||
val rand = Random(System.currentTimeMillis())
|
||||
var sum = 0.0
|
||||
|
||||
val expr =
|
||||
RealField.expressionInField { ((variable("x") * number(2.0) - 234) + 24.toByte()) * variable("x") * variable("x") }
|
||||
|
||||
repeat(10_000_000) { sum += expr("x" to rand.nextDouble()) }
|
||||
println("asm-fe = $sum")
|
||||
return Duration.between(startTime, Instant.now())
|
||||
}
|
||||
|
||||
fun runAsm(): Any {
|
||||
val startTime = Instant.now()!!
|
||||
val rand = Random(System.currentTimeMillis())
|
||||
var sum = 0.0
|
||||
val expr = RealField.mstInField { ((symbol("x") * number(2.0) - 234) + 24.0) * symbol("x") * symbol("x") }.compile()
|
||||
repeat(10_000_000) { sum += expr("x" to rand.nextDouble()) }
|
||||
println("asm-sum = $sum")
|
||||
return Duration.between(startTime, Instant.now())
|
||||
}
|
||||
|
||||
fun runMst(): Any {
|
||||
val startTime = Instant.now()!!
|
||||
val rand = Random(System.currentTimeMillis())
|
||||
var sum = 0.0
|
||||
val expr = RealField.mstInField { ((symbol("x") * number(2.0) - 234) + 24.0) * symbol("x") * symbol("x") }
|
||||
repeat(10_000_000) { sum += expr("x" to rand.nextDouble()) }
|
||||
println("asm-mst = $sum")
|
||||
return Duration.between(startTime, Instant.now())
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ kotlin.sourceSets {
|
||||
implementation("com.github.h0tk3y.betterParse:better-parse-jvm:0.4.0-alpha-3")
|
||||
implementation("org.ow2.asm:asm:8.0.1")
|
||||
implementation("org.ow2.asm:asm-commons:8.0.1")
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,10 @@ import org.objectweb.asm.MethodVisitor
|
||||
import org.objectweb.asm.Opcodes
|
||||
import scientifik.kmath.asm.internal.AsmBuilder.ClassLoader
|
||||
import scientifik.kmath.operations.Algebra
|
||||
import scientifik.kmath.ast.MST
|
||||
|
||||
/**
|
||||
* ASM Builder is a structure that abstracts building a class that unwraps [AsmExpression] to plain Java expression.
|
||||
* ASM Builder is a structure that abstracts building a class that is used to unwrap [MST] to plain Java expression.
|
||||
* This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class.
|
||||
*
|
||||
* @param T the type of AsmExpression to unwrap.
|
||||
@ -205,7 +206,7 @@ internal class AsmBuilder<T> internal constructor(
|
||||
|
||||
private fun loadThis(): Unit = invokeMethodVisitor.visitLoadObjectVar(invokeThisVar)
|
||||
|
||||
internal fun loadNumberConstant(value: Number) {
|
||||
private fun loadNumberConstant(value: Number) {
|
||||
val clazz = value.javaClass
|
||||
val c = clazz.name.replace('.', '/')
|
||||
val sigLetter = SIGNATURE_LETTERS[clazz]
|
||||
@ -280,7 +281,7 @@ internal class AsmBuilder<T> internal constructor(
|
||||
|
||||
internal companion object {
|
||||
private val SIGNATURE_LETTERS: Map<Class<out Any>, String> by lazy {
|
||||
mapOf(
|
||||
hashMapOf(
|
||||
java.lang.Byte::class.java to "B",
|
||||
java.lang.Short::class.java to "S",
|
||||
java.lang.Integer::class.java to "I",
|
||||
|
@ -3,12 +3,14 @@ package scientifik.kmath.asm.internal
|
||||
import org.objectweb.asm.Opcodes
|
||||
import scientifik.kmath.operations.Algebra
|
||||
|
||||
private val methodNameAdapters: Map<String, String> = mapOf("+" to "add", "*" to "multiply", "/" to "divide")
|
||||
private val methodNameAdapters: Map<String, String> by lazy {
|
||||
hashMapOf("+" to "add", "*" to "multiply", "/" to "divide")
|
||||
}
|
||||
|
||||
internal fun <T> hasSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
|
||||
val aName = methodNameAdapters[name] ?: name
|
||||
|
||||
context::class.java.methods.find { it.name == aName && it.parameters.size == arity }
|
||||
context.javaClass.methods.find { it.name == aName && it.parameters.size == arity }
|
||||
?: return false
|
||||
|
||||
return true
|
||||
@ -17,7 +19,7 @@ internal fun <T> hasSpecific(context: Algebra<T>, name: String, arity: Int): Boo
|
||||
internal fun <T> AsmBuilder<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
|
||||
val aName = methodNameAdapters[name] ?: name
|
||||
|
||||
context::class.java.methods.find { it.name == aName && it.parameters.size == arity }
|
||||
context.javaClass.methods.find { it.name == aName && it.parameters.size == arity }
|
||||
?: return false
|
||||
|
||||
val owner = context::class.java.name.replace('.', '/')
|
||||
|
Loading…
Reference in New Issue
Block a user