Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mini evaluator #3792

Draft
wants to merge 1 commit into
base: version-1.5.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions benchmark/src/main/scala/com/wavesplatform/state/DBState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.wavesplatform.lang.directives.DirectiveSet
import com.wavesplatform.settings.WavesSettings
import com.wavesplatform.transaction.smart.WavesEnvironment
import com.wavesplatform.utils.ScorexLogging
import monix.eval.Coeval
import org.openjdk.jmh.annotations.{Param, Scope, State, TearDown}

import java.io.File
Expand All @@ -33,14 +32,13 @@ abstract class DBState extends ScorexLogging {
AddressScheme.current = new AddressScheme { override val chainId: Byte = 'W' }

lazy val environment = WavesEnvironment(
AddressScheme.current.chainId,
Coeval.raiseError(new NotImplementedError("`tx` is not implemented")),
Coeval(rocksDBWriter.height),
rocksDBWriter,
null,
DirectiveSet.contractDirectiveSet,
ByteStr.empty
)
???,
???,
ByteStr.empty,
DirectiveSet.contractDirectiveSet,
) {
override def blockchain: Blockchain = ???
}

@TearDown
def close(): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ object EnvironmentFunctionsBenchmark {

@State(Scope.Benchmark)
class AddressFromString {
val ctx: EvaluationContext[Environment, Id] =
val ctx: EvaluationContext[Id] =
WavesContext
.build(Global, DirectiveSet(V4, Account, DApp).explicitGet(), true)
.evaluationContext(environment)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package com.wavesplatform.lang.v1

import com.wavesplatform.lang.Common
import com.wavesplatform.lang.directives.values.{V1, V3}
import com.wavesplatform.lang.directives.values.{V1, V3, V5, V6}
import com.wavesplatform.lang.v1.EvaluatorV2Benchmark.*
import com.wavesplatform.lang.v1.compiler.Terms.{EXPR, IF, TRUE}
import com.wavesplatform.lang.v1.compiler.Terms.{CONST_LONG, EXPR, IF, TRUE}
import com.wavesplatform.lang.v1.compiler.TestCompiler
import com.wavesplatform.lang.v1.evaluator.EvaluatorV2
import com.wavesplatform.lang.v1.evaluator.ctx.DisabledLogEvaluationContext
import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext
import com.wavesplatform.lang.v1.traits.Environment
import com.wavesplatform.lang.v1.evaluator.ctx.{DisabledLogEvaluationContext, EvaluationContext, LoggedEvaluationContext}
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole

import java.util.concurrent.TimeUnit
import scala.annotation.tailrec

object EvaluatorV2Benchmark {
val pureContext = PureContext.build(V1, useNewPowPrecision = true).withEnvironment[Environment]
val pureEvalContext = pureContext.evaluationContext(Common.emptyBlockchainEnvironment())
val evaluatorV2 = new EvaluatorV2(DisabledLogEvaluationContext(pureEvalContext), V1, Int.MaxValue, true, false, true, true, true)
val pureContext: CTX = PureContext.build(V1, useNewPowPrecision = true)
val pureEvalContext: EvaluationContext[Id] = pureContext.evaluationContext(Common.emptyBlockchainEnvironment())
val evaluatorV2: EvaluatorV2 = new EvaluatorV2(DisabledLogEvaluationContext(pureEvalContext), V1, true, true, false)
}

@OutputTimeUnit(TimeUnit.MILLISECONDS)
Expand All @@ -42,6 +42,45 @@ class EvaluatorV2Benchmark {

@Benchmark
def conditions(st: Conditions, bh: Blackhole): Unit = bh.consume(eval(pureEvalContext, st.expr, V1))

@Benchmark
def recFunc(st: RecFunc, bh: Blackhole): Unit = bh.consume {
val (_, _, res) = eval(pureEvalContext, st.expr, V1)
require(res == Right(CONST_LONG(13631488)), s"$res")
}

@Benchmark
def overheadCallable(st: OverheadTest, bh: Blackhole): Unit = bh.consume {
val (_, comp, res) = eval(pureEvalContext, st.expr.expr, V6)
require((Int.MaxValue - comp) == 1048576, s"$comp")
}

@Benchmark
def mini_funcs(st: Funcs, bh: Blackhole): Unit = bh.consume(miniEv(st.expr, pureEvalContext))

@Benchmark
def mini_lets(st: Lets, bh: Blackhole): Unit = bh.consume(miniEv(st.expr, pureEvalContext))

@Benchmark
def mini_custom(st: CustomFunc, bh: Blackhole): Unit = bh.consume(miniEv(st.expr, pureEvalContext))

@Benchmark
def mini_littleCustom(st: LittleCustomFunc, bh: Blackhole): Unit = bh.consume(miniEv(st.expr, pureEvalContext))

@Benchmark
def mini_conditions(st: Conditions, bh: Blackhole): Unit = bh.consume(miniEv(st.expr, pureEvalContext))

@Benchmark
def mini_recFunc(st: RecFunc, bh: Blackhole): Unit = bh.consume {
val (log, spentComplexity, res) = miniEv(st.expr, pureEvalContext)
require(res == Right(CONST_LONG(13631488)), s"$res")
}

@Benchmark
def mini_overheadCallable(st: OverheadTest, bh: Blackhole): Unit = bh.consume {
val (_, comp, res) = miniEv(st.expr.expr, pureEvalContext, 52000)
require(comp == 1048576, s"$comp")
}
}

@State(Scope.Benchmark)
Expand All @@ -56,7 +95,10 @@ class Funcs {
| a$count() == a$count()
""".stripMargin

val expr = TestCompiler(V3).compileExpression(script).expr.asInstanceOf[EXPR]
val expr = {
val sc = TestCompiler(V6).compileExpression(script, checkSize = false)
sc.expr
}
}

@State(Scope.Benchmark)
Expand All @@ -69,7 +111,22 @@ class Lets {
| a$count == a$count
""".stripMargin

val expr = TestCompiler(V3).compileExpression(script).expr.asInstanceOf[EXPR]
val expr = TestCompiler(V3).compileExpression(script, checkSize = false).expr
}

@State(Scope.Benchmark)
class RecFunc {
def scriptStr(size: Int) =
s"""func f1(i: Int) = i + 1
|${(2 to size)
.map { i =>
s"func f$i(${(0 until i).map(idx => s"i$idx: Int").mkString(",")}) = ${(1 until i).map(fi => s"f$fi(${(1 to fi).map(ii => s"i$ii").mkString(",")})").mkString("+")}"
}
.mkString("\n")}
|f${size}(${(1 to size).mkString(",")})
|""".stripMargin
private val script: String = scriptStr(22)
val expr = TestCompiler(V6).compileExpression(script, checkSize = false).expr
}

@State(Scope.Benchmark)
Expand Down Expand Up @@ -113,7 +170,7 @@ class CustomFunc {
| f() && f() && f() && f() && f() && f() && f()
""".stripMargin

val expr = TestCompiler(V3).compileExpression(script).expr.asInstanceOf[EXPR]
val expr = TestCompiler(V6).compileExpression(script).expr
}

@State(Scope.Benchmark)
Expand Down Expand Up @@ -157,7 +214,22 @@ class LittleCustomFunc {
| f()
""".stripMargin

val expr = TestCompiler(V3).compileExpression(script).expr.asInstanceOf[EXPR]
val expr = TestCompiler(V3).compileExpression(script).expr
}

@State(Scope.Benchmark)
class OverheadTest {
val expr = {
val n = 20
val scriptTest =
s"""
| func f0() = true
| ${(0 until n).map(i => s"func f${i + 1}() = if (f$i()) then f$i() else f$i()").mkString("\n")}
| f$n()
""".stripMargin
println(scriptTest)
TestCompiler(V5).compileExpression(scriptTest)
}
}

@State(Scope.Benchmark)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ import java.util.concurrent.{ThreadLocalRandom, TimeUnit}
import cats.Id
import com.google.common.primitives.Longs
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils._
import com.wavesplatform.common.utils.*
import com.wavesplatform.lang.directives.DirectiveSet
import com.wavesplatform.lang.directives.values._
import com.wavesplatform.lang.utils._
import com.wavesplatform.lang.directives.values.*
import com.wavesplatform.lang.utils.*
import com.wavesplatform.lang.v1.FunctionHeader.Native
import com.wavesplatform.lang.v1.PureFunctionsRebenchmark._
import com.wavesplatform.lang.v1.PureFunctionsRebenchmark.*
import com.wavesplatform.lang.v1.compiler.Terms
import com.wavesplatform.lang.v1.compiler.Terms._
import com.wavesplatform.lang.v1.compiler.Terms.*
import com.wavesplatform.lang.v1.evaluator.ctx.EvaluationContext
import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext
import com.wavesplatform.lang.v1.evaluator.{FunctionIds, Log}
import com.wavesplatform.lang.v1.traits.Environment
import com.wavesplatform.lang.{Common, ExecutionError, v1}
import org.openjdk.jmh.annotations._
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole

import scala.util.Random
Expand Down Expand Up @@ -217,7 +216,7 @@ class PureFunctionsRebenchmark {
}

object PureFunctionsRebenchmark {
val context: EvaluationContext[Environment, Id] =
val context: EvaluationContext[Id] =
lazyContexts((DirectiveSet(V5, Account, Expression).explicitGet(), true, true))()
.evaluationContext(Common.emptyBlockchainEnvironment())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import com.wavesplatform.lang.v1.EnvironmentFunctionsBenchmark.{curve25519, rand
import com.wavesplatform.lang.v1.FunctionHeader.Native
import com.wavesplatform.lang.v1.ScriptEvaluatorBenchmark.*
import com.wavesplatform.lang.v1.compiler.Terms.*
import com.wavesplatform.lang.v1.evaluator.EvaluatorV1.*
import com.wavesplatform.lang.v1.evaluator.FunctionIds
import com.wavesplatform.lang.v1.evaluator.FunctionIds.{FROMBASE58, SIGVERIFY, TOBASE58}
import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext}
import com.wavesplatform.lang.v1.traits.Environment
import com.wavesplatform.lang.{Common, Global}
import com.wavesplatform.lang.{Common, Global}
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole

Expand All @@ -22,11 +24,10 @@ import scala.concurrent.duration.SECONDS
import scala.util.Random

object ScriptEvaluatorBenchmark {
val lastVersion = StdLibVersion.VersionDic.all.max
val context =
(PureContext.build(lastVersion, useNewPowPrecision = true) |+| CryptoContext.build(Global, lastVersion))
.withEnvironment[Environment]
.evaluationContext(Common.emptyBlockchainEnvironment())
val version = V1
val pureEvalContext: EvaluationContext[Id] =
PureContext.build(V1, useNewPowPrecision = true).evaluationContext(Common.emptyBlockchainEnvironment())
val evaluatorV1: EvaluatorV1[Id] = new EvaluatorV1[Id]()
}

@OutputTimeUnit(TimeUnit.MICROSECONDS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.wavesplatform.lang

import cats.Id
import com.wavesplatform.lang.directives.values.StdLibVersion
import com.wavesplatform.lang.miniev.{Ev, State}
import com.wavesplatform.lang.v1.FunctionHeader.Native
import com.wavesplatform.lang.v1.compiler.Terms
import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BIGINT, CONST_LONG, EXPR, FUNCTION_CALL}
Expand All @@ -10,7 +11,6 @@ import com.wavesplatform.lang.v1.evaluator.FunctionIds.POW_BIGINT
import com.wavesplatform.lang.v1.evaluator.ctx.EvaluationContext
import com.wavesplatform.lang.v1.evaluator.ctx.impl.Rounding
import com.wavesplatform.lang.v1.evaluator.{EvaluatorV2, Log}
import com.wavesplatform.lang.v1.traits.Environment

package object v1 {
def pow(base: BigInt, basePrecision: Int, exponent: BigInt, exponentPrecision: Int, resultPrecision: Int): EXPR =
Expand All @@ -27,7 +27,7 @@ package object v1 {
)

def eval(
ctx: EvaluationContext[Environment, Id],
ctx: EvaluationContext[Id],
expr: EXPR,
stdLibVersion: StdLibVersion = StdLibVersion.VersionDic.all.max
): (Log[Id], Int, Either[ExecutionError, Terms.EVALUATED]) =
Expand All @@ -41,4 +41,7 @@ package object v1 {
enableExecutionLog = false,
fixedThrownError = true
)

def miniEv(expr: EXPR, ctx: EvaluationContext[Id], limit: Int = Int.MaxValue): (Log[Id], Int, Either[ExecutionError, Terms.EVALUATED]) =
Ev.run(expr, ???)
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ object WavesEnvironmentBenchmark {
RDB.open(wavesSettings.dbSettings)
}

val environment: Environment[Id] = {
val environment: Environment[Id] = ???/*{
val state = new RocksDBWriter(rdb, wavesSettings.blockchainSettings, wavesSettings.dbSettings, wavesSettings.enableLightMode)
WavesEnvironment(
AddressScheme.current.chainId,
Expand All @@ -145,7 +145,7 @@ object WavesEnvironmentBenchmark {
DirectiveSet.contractDirectiveSet,
ByteStr.empty
)
}
}*/

@TearDown
def close(): Unit = {
Expand Down
11 changes: 7 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ lazy val lang =

lazy val `lang-jvm` = lang.jvm
.settings(
name := "RIDE Compiler",
normalizedName := "lang",
description := "The RIDE smart contract language compiler",
libraryDependencies += "org.scala-js" %% "scalajs-stubs" % "1.1.0" % Provided
name := "RIDE Compiler",
normalizedName := "lang",
description := "The RIDE smart contract language compiler",
libraryDependencies ++= Seq(
"org.scala-js" %% "scalajs-stubs" % "1.1.0" % Provided,
Dependencies.scalaLogging
)
)

lazy val `lang-js` = lang.js
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.wavesplatform.lang.utils

trait Logging {
def trace(message: => String): Unit = println(message)
}
8 changes: 4 additions & 4 deletions lang/jvm/src/main/scala/com/wavesplatform/lang/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ object Global extends BaseGlobal {
} else {
BigDecimalMath.pow(baseBD, expBD, context)
}
if (useNewPrecision)
(if (useNewPrecision)
setScale(resultPrecision, round, context.getPrecision, result)
else {
val value = result.setScale(resultPrecision.toInt, round.mode).unscaledValue
val value = result.setScale(resultPrecision, round.mode).unscaledValue
Right(BigInt(value))
}
}.flatten.map(_.bigInteger.longValueExact())
}).map(_.bigInteger.longValueExact())
}.flatten

def log(b: Long, bp: Long, e: Long, ep: Long, rp: Long, round: Rounding): Either[String, Long] =
tryEither {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.wavesplatform.lang.utils

import com.typesafe.scalalogging.StrictLogging

trait Logging extends StrictLogging {
def trace(message: => String): Unit = logger.trace(message)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@ sealed trait ExecutionError {
def message: String
}
case class CommonError(details: String, cause: Option[ValidationError] = None) extends ExecutionError {
override def toString: String = s"CommonError($message)"
override def message: String = cause.map(_.toString).getOrElse(details)
}
case class ThrownError(message: String) extends ExecutionError
case class FailOrRejectError(message: String, skipInvokeComplexity: Boolean = true) extends ExecutionError with ValidationError

case class EvaluationException(cause: Throwable) extends ExecutionError {
override lazy val message: String = s"class ${cause.getClass} ${String.valueOf(cause.getMessage)}"
}

case object SoftLimitReached extends ExecutionError {
override val message = "Soft limit reached"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@ object ValidationError {
type Validation[T] = Either[ValidationError, T]

case class ScriptParseError(m: String) extends ValidationError
case class ScriptRunsLimitError(m: String) extends ValidationError

}
Loading
Loading