Skip to content

Commit

Permalink
Miniev implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
phearnot committed Dec 17, 2023
1 parent d7c0785 commit 3ad38d1
Show file tree
Hide file tree
Showing 108 changed files with 2,640 additions and 2,197 deletions.
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

0 comments on commit 3ad38d1

Please sign in to comment.