Benchmarks for Speedy/DAML-LF/Protobuf translations [DPP-104] (#8272)

* Fix typos and inconsistencies

* Implement toString for SRequiresOnLedger

* Add benchmarks

changelog_begin
changelog_end

* Add copyright headers

* Make SubmissionBuilder final

* Address missing reference ledger export on Windows

* Fix README.md

* Add clarification on README.md

* Limit visibility of reference ledger export output

* Ensure benchmark recognizes the optionality of exercise return values

* Address https://github.com/digital-asset/daml/pull/8272#discussion_r542194308

* Follow up to changes from https://github.com/digital-asset/daml/pull/8273
This commit is contained in:
Stefano Baghino 2020-12-15 12:49:52 +01:00 committed by GitHub
parent 7375afd4f3
commit 6580dbd15c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 736 additions and 10 deletions

View File

@ -192,7 +192,7 @@ private[engine] final class ValueTranslator(compiledPackages: CompiledPackages)
}
case Some(labeledRecords) =>
recordFlds.map {
case ((lbl, typ)) =>
case (lbl, typ) =>
labeledRecords
.get(lbl)
.fold(fail(s"Missing record label $lbl for record $typeRecordId")) { v =>

View File

@ -148,7 +148,7 @@ private[lf] object Anf {
private[this] type Tx[T, A] = (DepthA, T, K[AExpr, A]) => Trampoline[A]
/**
* K Is the type for contiunations.
* K Is the type for continuations.
*
* @tparam T Type the function would have returned had it not been in CPS.
* @tparam A The return type of the continuation (minus the Trampoline

View File

@ -29,7 +29,9 @@ object SError {
/** Operation is only supported in on-ledger mode but was
* called in off-ledger mode.
*/
final case class SRequiresOnLedger(operation: String) extends SError
final case class SRequiresOnLedger(operation: String) extends SError {
override def toString = s"Requires on-ledger mode: " + operation
}
def crash[A](reason: String): A =
throw SErrorCrash(reason)

View File

@ -9,7 +9,7 @@ import com.daml.lf.data.{FrontStack, Ref}
import com.daml.lf.speedy.SResult._
import com.daml.lf.speedy.SValue._
import com.daml.lf.speedy.SExpr.{SEApp, SEMakeClo, SEImportValue, SELocA}
import com.daml.lf.value.{Value}
import com.daml.lf.value.Value
import com.daml.lf.value.test.TypedValueGenerators.genAddend
import com.daml.lf.value.test.ValueGenerators.{cidV0Gen, comparableCoidsGen}
import com.daml.lf.PureCompiledPackages

View File

@ -651,7 +651,7 @@ object Ast {
returnType: Type,
update: E
): GenTemplateChoice[E] =
new GenTemplateChoice(
GenTemplateChoice(
name,
consuming,
controllers,

View File

@ -88,7 +88,7 @@ object Util {
// A package undefined w.r.t. the function `packages` is treated as a sink.
def dependenciesInTopologicalOrder(
pkgIds: List[Ref.PackageId],
packages: Ref.PackageId PartialFunction Package,
packages: PartialFunction[Ref.PackageId, Package],
): List[Ref.PackageId] = {
@tailrec

View File

@ -22,7 +22,7 @@ object ValueCoder {
import Value.MAXIMUM_NESTING
/**
* Error type for signalling errors occuring during decoding serialized values
* Error type for signalling errors occurring during decoding serialized values
* @param errorMessage description
*/
final case class DecodeError(errorMessage: String)
@ -35,7 +35,7 @@ object ValueCoder {
}
/**
* Error type for signalling errors occuring during encoding values
* Error type for signalling errors occurring during encoding values
* @param errorMessage description
*/
final case class EncodeError(errorMessage: String)
@ -51,7 +51,7 @@ object ValueCoder {
private[lf] def encode(contractId: Cid): proto.ContractId
}
@deprecated("use CidEndocer", since = "1.1.2")
@deprecated("use CidEncoder", since = "1.1.2")
val AbsCidDecoder = CidEncoder
object CidEncoder extends EncodeCid[ContractId] {

View File

@ -202,6 +202,7 @@ client_server_build(
"--contract-id-seeding=testing-weak",
"--participant participant-id=%s,port=%d" % (REFERENCE_LEDGER_EXPORT_NAME, REFERENCE_LEDGER_EXPORT_PORT),
],
visibility = [":__subpackages__"],
) if not is_windows else None
# Test for checking the integrity of the ledger export produced above.

View File

@ -9,6 +9,7 @@ load(
"da_scala_test",
"lf_scalacopts",
)
load("@os_info//:os_info.bzl", "is_windows")
da_scala_library(
name = "tools",
@ -125,3 +126,31 @@ da_scala_benchmark_jmh(
"@maven//:org_scalaz_scalaz_core_2_12",
],
)
da_scala_benchmark_jmh(
name = "benchmark-codec",
srcs = glob(["codec-benchmark/src/benchmark/scala/**/*.scala"]),
data = [
"//ledger/participant-state/kvutils:reference-ledger-export.out",
] if not is_windows else [],
max_heap_size = "4g",
scalacopts = lf_scalacopts,
tags = [
"manual",
],
deps = [
"//bazel_tools/runfiles:scala_runfiles",
"//daml-lf/archive:daml_lf_archive_reader",
"//daml-lf/archive:daml_lf_dev_archive_proto_java",
"//daml-lf/data",
"//daml-lf/engine",
"//daml-lf/interpreter",
"//daml-lf/language",
"//daml-lf/transaction",
"//daml-lf/transaction:transaction_proto_java",
"//daml-lf/transaction:value_proto_java",
"//ledger/participant-state/kvutils",
"@maven//:com_google_protobuf_protobuf_java",
"@maven//:org_scalaz_scalaz_core_2_12",
],
)

View File

@ -0,0 +1,82 @@
### Value and transaction coding benchmarks
#### Running
To run the benchmarks with the default input data, simply run:
bazel run //ledger/participant-state/kvutils/tools:benchmark-codec
The default input data is the reference ledger export. It cannot be used as a
reliable source to compare performances between commits, as the content of the
export may vary over time. This should, however, provide a good dataset to
have a tight feedback loop on improvements to the translation between Speedy,
DAML-LF, and Protobuf objects and messages.
To run the benchmarks with a custom ledger export, you can run the following:
bazel run //ledger/participant-state/kvutils/tools:benchmark-codec -- \
-p ledgerExport=/absolute/path/to/a/ledger/export.bin
Please ensure to use an absolute path, as this will be run in a Bazel sandbox
whose working directory is unlikely to be yours.
There are two main use cases to pass a specific ledger export:
1. evaluate performance improvements over specific datasets, to address edge cases
2. compare the performance improvements of two commits using the same dataset so
that the outcomes are comparable
Note that each benchmark will consume the ledger export in its entirety, so it's
probably better to limit its size.
Note that `-p` is a [JMH](https://github.com/openjdk/jmh) option. You can see
all available options by running:
bazel run //ledger/participant-state/kvutils/tools:benchmark-codec -- -h
JMH is mature and rich of features, ranging from setting up the run to gather
profiling information, persisting the results, tuning the JVM and much more.
You are **strongly** advised to have a look at the available options to make sure
you run the benchmarks that are relevant to you with the proper settings.
##### Examples
* Run only serialization benchmarks (see [Terminology](#terminology)) forking once,
with default data, five warm-up iterations and ten measured iterations:
bazel run //ledger/participant-state/kvutils/tools:benchmark-codec -- \
-f 1 -wi 5 -i 10 ".*Deserialize.*"
* Run only transaction benchmarks forking once, with default data, five warm-up
iterations and five measured iterations, forcing GC between iterations,
reporting the average time:
bazel run //ledger/participant-state/kvutils/tools:benchmark-codec -- \
-f 1 -wi 5 -i 5 -gc true -bm avgt -tu ms ".*Transaction.*"
* List the benchmarks selected by the provided filter and exit:
bazel run //ledger/participant-state/kvutils/tools:benchmark-codec -- -l ".*engine.*"
#### Terminology
* _serialize_: translate from a Protobuf object to its serialized from
* _deserialize_: translate a serialized Protobuf message into its object representation
* _encode_: translate a Protobuf object to a DAML-LF object
* _decode_: translate a DAML-LF object to a Protobuf object
#### Known issues
##### SLF4J warning
On the first warm-up iteration, a warning by SLF4J appears. This does not cause any
functional issue with the benchmarks. A first analysis seems to point at the need
to ensure the runtime dependencies (like the Logback Classic JAR) are correctly
forwarded to the JMH artifact ultimately produced by the Bazel `scala_benchmark_jmh`
rule.
##### Failure to run the benchmarks without an explicit export file on Windows
On Windows the build does not produce the reference ledger export. On Windows, you
must explicitly pass a ledger export to the benchmarks in order to run them.

View File

@ -0,0 +1,28 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.{
BenchmarkWithLedgerExport,
DecodedTransaction,
EncodedTransaction,
assertDecode
}
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class DecodeTransactionBenchmark extends BenchmarkWithLedgerExport {
var encodedTransactions: Vector[EncodedTransaction] = _
@Setup
override def setup(): Unit = {
super.setup()
encodedTransactions = submissions.transactions
}
@Benchmark
def run(): Vector[DecodedTransaction] =
encodedTransactions.map(assertDecode)
}

View File

@ -0,0 +1,23 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, DecodedValue, EncodedValue, assertDecode}
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class DecodeValueBenchmark extends BenchmarkWithLedgerExport {
var encodedValues: Vector[EncodedValue] = _
@Setup
override def setup(): Unit = {
super.setup()
encodedValues = submissions.values.map(_.value).toVector
}
@Benchmark
def run(): Vector[DecodedValue] =
encodedValues.map(assertDecode)
}

View File

@ -0,0 +1,25 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, EncodedTransaction}
import com.google.protobuf.ByteString
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class DeserializeTransactionBenchmark extends BenchmarkWithLedgerExport {
var protobufTransactions: Vector[ByteString] = _
@Setup
override def setup(): Unit = {
super.setup()
val encodedTransactions = submissions.transactions
protobufTransactions = encodedTransactions.map(_.toByteString)
}
@Benchmark
def run(): Vector[EncodedTransaction] =
protobufTransactions.map(EncodedTransaction.deserialize)
}

View File

@ -0,0 +1,25 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, EncodedValue}
import com.google.protobuf.ByteString
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class DeserializeValueBenchmark extends BenchmarkWithLedgerExport {
var protobufValues: Vector[ByteString] = _
@Setup
override def setup(): Unit = {
super.setup()
val encodedValues = submissions.values.map(_.value).toVector
protobufValues = encodedValues.map(_.toByteString)
}
@Benchmark
def run(): Vector[EncodedValue] =
protobufValues.map(EncodedValue.deserialize)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark._
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class EncodeTransactionBenchmark extends BenchmarkWithLedgerExport {
var decodedTransactions: Vector[DecodedTransaction] = _
@Setup
override def setup(): Unit = {
super.setup()
val encodedTransactions = submissions.transactions
decodedTransactions = encodedTransactions.map(assertDecode)
}
@Benchmark
def run(): Vector[EncodedTransaction] =
decodedTransactions.map(assertEncode)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark._
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class EncodeValueBenchmark extends BenchmarkWithLedgerExport {
var decodedValues: Vector[DecodedValue] = _
@Setup
override def setup(): Unit = {
super.setup()
val encodedValues = submissions.values.map(_.value).toVector
decodedValues = encodedValues.map(assertDecode)
}
@Benchmark
def run(): Vector[EncodedValue] =
decodedValues.map(assertEncode)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, EncodedTransaction}
import com.google.protobuf.ByteString
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class SerializeTransactionBenchmark extends BenchmarkWithLedgerExport {
var encodedTransactions: Vector[EncodedTransaction] = _
@Setup
override def setup(): Unit = {
super.setup()
encodedTransactions = submissions.transactions
}
@Benchmark
def run(): Vector[ByteString] =
encodedTransactions.map(_.toByteString)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, EncodedValue}
import com.google.protobuf.ByteString
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class SerializeValueBenchmark extends BenchmarkWithLedgerExport {
var encodedValues: Vector[EncodedValue] = _
@Setup
override def setup(): Unit = {
super.setup()
encodedValues = submissions.values.map(_.value).toVector
}
@Benchmark
def run(): Vector[ByteString] =
encodedValues.map(_.toByteString)
}

View File

@ -0,0 +1,77 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.benchmark
import java.nio.file.{Files, Paths}
import com.daml.bazeltools.BazelRunfiles
import com.daml.ledger.participant.state.kvutils.DamlKvutils.DamlSubmission
import com.daml.ledger.participant.state.kvutils.Envelope
import com.daml.ledger.participant.state.kvutils.`export`.ProtobufBasedLedgerDataImporter
import com.daml.lf.archive.Decode
import com.google.protobuf.ByteString
import org.openjdk.jmh.annotations.{Param, Scope, Setup, State}
import scala.collection.JavaConverters.iterableAsScalaIterableConverter
@State(Scope.Benchmark)
abstract class BenchmarkWithLedgerExport {
@Param(Array(""))
var ledgerExport: String = _
protected var submissions: Submissions = _
@Setup
def setup(): Unit = {
if (ledgerExport.isEmpty) {
ledgerExport = referenceLedgerExportPath
}
val source = Paths.get(ledgerExport)
if (Files.notExists(source)) {
throw new IllegalArgumentException(s"Ledger export file not found at $ledgerExport")
}
val builder = Submissions.newBuilder()
def decodeEnvelope(envelope: ByteString): Unit =
Envelope.open(envelope).fold(sys.error, identity) match {
case Envelope.SubmissionMessage(submission)
if submission.getPayloadCase == DamlSubmission.PayloadCase.PACKAGE_UPLOAD_ENTRY =>
for (archive <- submission.getPackageUploadEntry.getArchivesList.asScala) {
builder += Decode.decodeArchive(archive)
}
case Envelope.SubmissionMessage(submission)
if submission.getPayloadCase == DamlSubmission.PayloadCase.TRANSACTION_ENTRY =>
builder += submission.getTransactionEntry.getTransaction
case Envelope.SubmissionBatchMessage(batch) =>
for (submission <- batch.getSubmissionsList.asScala) {
decodeEnvelope(submission.getSubmission)
}
case _ =>
()
}
val importer = ProtobufBasedLedgerDataImporter(source)
try {
for ((submissionInfo, _) <- importer.read()) {
decodeEnvelope(submissionInfo.submissionEnvelope)
}
} finally {
importer.close()
}
submissions = builder.result()
}
private val relativeReferenceLedgerExportPath: String =
"ledger/participant-state/kvutils/reference-ledger-export.out"
private val referenceLedgerExportPath: String =
BazelRunfiles.rlocation(relativeReferenceLedgerExportPath)
}

View File

@ -0,0 +1,26 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.benchmark
import com.daml.lf.CompiledPackages
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.language.Ast.Package
import com.daml.lf.transaction.TransactionOuterClass.Transaction
private[lf] object Submissions {
def newBuilder(): SubmissionsBuilder =
new SubmissionsBuilder(Map.newBuilder[PackageId, Package], Vector.newBuilder[Transaction])
}
private[lf] final case class Submissions(
compiledPackages: CompiledPackages,
transactions: Vector[EncodedTransaction],
) {
def values: Iterator[EncodedValueWithType] = {
val extract = new TypedValueExtractor(compiledPackages.signatures)
transactions.iterator.flatMap(extract.fromTransaction)
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.benchmark
import com.daml.lf.PureCompiledPackages
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.language.Ast.Package
import com.daml.lf.transaction.TransactionOuterClass.Transaction
import scala.collection.mutable
final class SubmissionsBuilder(
packages: mutable.Builder[(PackageId, Package), Map[PackageId, Package]],
transactions: mutable.Builder[Transaction, Vector[Transaction]],
) {
def +=(fullPackage: (PackageId, Package)): Unit = {
packages += fullPackage
()
}
def +=(transaction: Transaction): Unit = {
transactions += transaction
()
}
def result(): Submissions =
Submissions(
PureCompiledPackages(packages.result()).fold(sys.error, identity),
transactions.result(),
)
}

View File

@ -0,0 +1,10 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.benchmark
import com.daml.lf.language.Ast.Type
private[benchmark] final case class TypedValue[A](value: A, valueType: Type) {
def mapValue[B](f: A => B): TypedValue[B] = TypedValue(f(value), valueType)
}

View File

@ -0,0 +1,67 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.benchmark
import com.daml.lf.data.Ref._
import com.daml.lf.language.Ast.{PackageSignature, TTyCon}
import com.daml.lf.value.ValueOuterClass.Identifier
import scala.collection.JavaConverters.{asScalaIteratorConverter, iterableAsScalaIterableConverter}
final class TypedValueExtractor(signatures: PartialFunction[PackageId, PackageSignature]) {
def fromTransaction(transaction: EncodedTransaction): Iterator[EncodedValueWithType] =
transaction.getNodesList.iterator.asScala.flatMap { node =>
if (node.hasCreate) {
val create = node.getCreate
val (packageId, qualifiedName) =
validateIdentifier(create.getContractInstance.getTemplateId)
val template =
signatures(packageId).lookupTemplate(qualifiedName).fold(sys.error, identity)
val argument =
TypedValue(
create.getContractInstance.getValue,
TTyCon(TypeConName(packageId, qualifiedName)),
)
val key =
template.key.map(key => TypedValue(create.getKeyWithMaintainers.getKey, key.typ))
argument :: key.toList
} else if (node.hasExercise) {
val exercise = node.getExercise
val (packageId, qualifiedName) =
validateIdentifier(exercise.getTemplateId)
val template =
signatures(packageId).lookupTemplate(qualifiedName).fold(sys.error, identity)
val choice = ChoiceName.assertFromString(exercise.getChoice)
val argument =
TypedValue(
exercise.getChosenValue,
template.choices(choice).argBinder._2,
)
val result =
if (exercise.hasReturnValue)
List(
TypedValue(
exercise.getReturnValue,
template.choices(choice).returnType,
)
)
else
Nil
argument :: result
} else {
Nil
}
}
private def validateIdentifier(templateId: Identifier): (PackageId, QualifiedName) = {
val packageId = PackageId.assertFromString(templateId.getPackageId)
val qualifiedName = QualifiedName(
ModuleName.assertFromSegments(templateId.getModuleNameList.asScala),
DottedName.assertFromSegments(templateId.getNameList.asScala),
)
(packageId, qualifiedName)
}
}

View File

@ -0,0 +1,94 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.transaction.TransactionCoder.{
NidDecoder,
NidEncoder,
decodeTransaction,
encodeTransaction
}
import com.daml.lf.transaction.TransactionOuterClass.Transaction
import com.daml.lf.transaction.{NodeId, VersionedTransaction}
import com.daml.lf.value.Value.ContractId
import com.daml.lf.value.ValueCoder._
import com.daml.lf.value.ValueOuterClass.VersionedValue
import com.daml.lf.value.{Value, ValueVersion}
import com.google.protobuf.ByteString
package object benchmark {
/**
* This is the output of a successful call to
* [[com.daml.lf.transaction.TransactionCoder.encodeTransaction]].
* It's the in-memory representation of the Protobuf message that
* describes a transaction, not its serialized form.
*/
private[lf] type EncodedTransaction = Transaction
private[lf] object EncodedTransaction {
def deserialize(bytes: ByteString): EncodedTransaction = Transaction.parseFrom(bytes)
}
/**
* This is the output of a successful call to
* [[com.daml.lf.value.ValueCoder.encodeValue]].
* It's the in-memory representation of the Protobuf message that
* describes a value, not its serialized form.
*/
private[lf] type EncodedValue = VersionedValue
private[lf] object EncodedValue {
def deserialize(bytes: ByteString): EncodedValue = VersionedValue.parseFrom(bytes)
}
private[lf] type EncodedValueWithType = TypedValue[EncodedValue]
private[lf] type DecodedValueWithType = TypedValue[DecodedValue]
/**
* This is the output of a successful call to
* [[com.daml.lf.transaction.TransactionCoder.decodeTransaction]].
* It's the DAML-LF representation of a transaction.
*/
private[lf] type DecodedTransaction = VersionedTransaction[NodeId, ContractId]
/**
* This is the output of a successful call to
* [[com.daml.lf.value.ValueCoder.decodeValue]].
* It's the DAML-LF representation of a value.
*/
private[lf] type DecodedValue = Value[ContractId]
private[lf] def assertDecode(transaction: EncodedTransaction): DecodedTransaction =
assertDecode(decode(transaction))
private[lf] def assertDecode(value: EncodedValue): DecodedValue =
assertDecode(decode(value))
private[lf] def assertEncode(transaction: DecodedTransaction): EncodedTransaction =
assertEncode(encode(transaction))
private[lf] def assertEncode(value: DecodedValue): EncodedValue =
assertEncode(encode(value))
private type DecodeResult[A] = Either[DecodeError, A]
private type EncodeResult[A] = Either[EncodeError, A]
private def assertDecode[A](result: DecodeResult[A]): A =
result.fold(e => sys.error(e.errorMessage), identity)
private def decode(transaction: EncodedTransaction): DecodeResult[DecodedTransaction] =
decodeTransaction(NidDecoder, CidDecoder, transaction)
private def decode(value: EncodedValue): DecodeResult[DecodedValue] =
decodeValue(CidDecoder, value)
private def assertEncode[A](result: EncodeResult[A]): A =
result.fold(e => sys.error(e.errorMessage), identity)
private def encode(transaction: DecodedTransaction): EncodeResult[EncodedTransaction] =
encodeTransaction(NidEncoder, CidEncoder, transaction)
private def encode(value: DecodedValue): EncodeResult[EncodedValue] =
encodeVersionedValue(CidEncoder, value, ValueVersion.DevOutputVersions)
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.engine
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, DecodedValue, assertDecode}
import com.daml.lf.engine.preprocessing.ValueTranslator
import com.daml.lf.speedy.SValue
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class SpeedyToValueBenchmark extends BenchmarkWithLedgerExport {
private var speedyValues: Vector[SValue] = _
@Setup
override def setup(): Unit = {
super.setup()
val decodedValues = submissions.values.map(_.mapValue(assertDecode)).toVector
val translator = new ValueTranslator(submissions.compiledPackages)
speedyValues = decodedValues.map(assertTranslate(translator))
}
@Benchmark
def run(): Vector[DecodedValue] =
speedyValues.map(_.toValue)
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.engine
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, DecodedValueWithType, assertDecode}
import com.daml.lf.engine.preprocessing.ValueTranslator
import com.daml.lf.speedy.SValue
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class ValueTranslatorBenchmark extends BenchmarkWithLedgerExport {
private var translator: ValueTranslator = _
private var decodedValues: Vector[DecodedValueWithType] = _
@Setup
override def setup(): Unit = {
super.setup()
decodedValues = submissions.values.map(_.mapValue(assertDecode)).toVector
translator = new ValueTranslator(submissions.compiledPackages)
}
@Benchmark
def run(): Vector[SValue] =
decodedValues.map(assertTranslate(translator))
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
import com.daml.lf.benchmark.DecodedValueWithType
import com.daml.lf.engine.preprocessing.ValueTranslator
import com.daml.lf.speedy.SValue
package object engine {
private[engine] def assertTranslate(translator: ValueTranslator)(
value: DecodedValueWithType,
): SValue =
translator.translateValue(value.valueType, value.value).fold(e => sys.error(e.msg), identity)
}

View File

@ -0,0 +1,40 @@
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.speedy
import com.daml.lf.CompiledPackages
import com.daml.lf.benchmark.{BenchmarkWithLedgerExport, DecodedValue, assertDecode}
import com.daml.lf.data.Time
import com.daml.lf.speedy.Speedy.Machine
import org.openjdk.jmh.annotations.{Benchmark, Setup}
class MachineImportValueBenchmark extends BenchmarkWithLedgerExport {
private var machine: Speedy.Machine = _
private var decodedValues: Vector[DecodedValue] = _
// Construct a machine for testing.
private def testingMachine(
compiledPackages: CompiledPackages,
): Machine = Machine(
compiledPackages = compiledPackages,
submissionTime = Time.Timestamp.MinValue,
initialSeeding = InitialSeeding.NoSeed,
expr = null,
globalCids = Set.empty,
committers = Set.empty,
)
@Setup
override def setup(): Unit = {
super.setup()
decodedValues = submissions.values.map(_.value).map(assertDecode).toVector
machine = testingMachine(submissions.compiledPackages)
}
@Benchmark
def run(): Vector[Unit] =
decodedValues.map(machine.importValue)
}

View File

@ -102,7 +102,7 @@ private[benchmark] final class Adapter(
}
pkgIds.toSeq match {
case Seq(pkgId) => Right(id.copy(packageId = pkgId))
case Seq() => Left(s"no package foud for ${id.qualifiedName}")
case Seq() => Left(s"no package found for ${id.qualifiedName}")
case _ => Left(s"2 or more packages found for ${id.qualifiedName}")
}
}