Skip to content

Add UPLC → JVM bytecode demo built from eo optics - #132

Merged
kryptt merged 14 commits into
mainfrom
ccr-1ec1a317-uds4rn
Oct 15, 2026
Merged

kryptt merged 14 commits into
mainfrom
ccr-1ec1a317-uds4rn

Conversation

@kryptt

@kryptt kryptt commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

A demo compiler from Untyped Plutus Core (UPLC, the language Cardano smart contracts run in) to JVM class files. It is built from lawful eo optics, all starting at the script as the ledger stores it: a prism, an iso and a prism.

CborScript ⇀ TypedProgram ≅ JvmClass ⇀ JvmClassScript
           toTyped        lowering   compiling
val script = CborScript.of(program)                 // Either[String, CborScript]; or CborScript.parse(bytes)
UplcJvm.toTyped                                     // CborScript ⇀ TypedProgram: typed Scala-like expression (.body.show prints it)
UplcJvm.toJvmClass                                  // CborScript ⇀ JvmClass: = toTyped andThen lowering
UplcJvm.toBytecode                                  // CborScript ⇀ JvmClassScript: = toJvmClass andThen compiling

UplcJvm.toBytecode.getOption(script) match          // the compiler
  case Some(compiled) =>
    UplcJvm.toBytecode.reverseGet(compiled) == script // the class hands its script back
    Exec.validate(compiled, scriptContext)            // Right(traces) | Left(reason), CIP-117
  case None => // an unknown Plutus Core version, or too large for a class file (UplcJvm.compile says which limit)
  • Why each arrow walks back. Every stage keeps the script it came from. A TypedProgram keeps its source. A class stores the script as Base64 string constants: a class file has no byte-array constants, and one string constant holds at most 65535 bytes. So reverseGet walks back exactly.

  • Two prisms around an iso. lowering is an iso: there and back is the identity in both directions, on everything the compiler produces. The other two are prisms, total on the way back:

    • toTyped: the bytes can declare any Plutus Core version, and Scalus decodes them all. The ledger only takes the versions Plutus V3 has at protocol version 11, 1.0.0 and 1.1.0 (Semantics.versions), so a script of any other version has no typed program. Before this, a script declaring 2.0.0 or 7.3.9 parsed, compiled and ran as if it were 1.1.0.
    • compiling: the JVM caps a method at 64 KB of bytecode and a class at 65 535 constants, so a class can be too large for a class file, and then there is none.

    Prism, iso and prism compose to a prism, so toJvmClass and the compiler, toBytecode, are prisms too.

  • Sealed values.

    • CborScript and JvmClassScript are opaque types over Scalus' ByteString. The two byte encodings can't be swapped by accident, and the laws can compare them with ==.
    • JvmClass is an opaque type over ASM's ClassNode. Only the compiler and UplcJvm.decompile make one, so it always embeds its script.
    • None of the three hands out what it holds: bytes and .tree are copies, and CborScript.parse checks a copy of the caller's array. A value cannot change after the compiler made or checked it, so the way back always works.
    • Both entry points are total. CborScript.of returns Left for a program Scalus can't flat-encode, such as one with a free variable. CborScript.parse returns Left for bytes that don't decode.
    • The demo's main code uses no unsafe* constructors.
  • Stack safety. Compiling cannot overflow the JVM stack, however deep the program. Decoding, typing and lowering are walks of Steps (Step.scala): plain calls while a walk is shallow, and from 128 calls deep the rest runs on the heap, from cats.Eval's loop. Every recursive call goes through Walk.nested. A program nested 100 000 deep compiles on a thread's default 1 MB stack.

    • Trampolining every node with plain Eval made translation 2–2.7× slower. Trampolining only when deep costs 13–19%.
    • A closure's captures are now one fold over its subtree's node ids (pre-order numbering makes a subtree a contiguous range), so FreeVars is gone.
  • Typer (toTyped). Works directly on Scalus' decoded Term tree. It recognises what UPLC compilers emit for constructs UPLC lacks:

    • let, and if over delayed branches;
    • saturated builtin calls;
    • direct calls of let-bound functions and forced builtins;
    • recursion tied by self-application, compiled to direct calls;
    • the case (constr k args…) multi-argument call.

    Every rewrite is exact under the CEK machine's evaluation order. An expression that can only fail is never followed by code, so the generated class has no unreachable instructions.

  • Hybrid typing. A static type is a Scalus DefaultUni. A builtin's signature is Scalus' own TypeScheme, instantiated at its argument types, so fstPair (unConstrData d) is an integer and the constructor-tag match on it becomes a JVM switch. Integers, booleans, bytestrings and strings stay unboxed wherever the typer can prove them.

  • Lowering (lowering). Writes bytecode straight into ASM's class tree (the JvmClass) with asm-commons' InstructionAdapter. It converts closures using a capture layout fixed by the source, so results can be "discharged" back to terms and compared with CEK results. A saturated builtin is a direct call of the scalus.uplc.builtin.Builtins function Scalus' CardanoBuiltins wraps.

  • Compiling (compiling). UplcJvm.compile is ASM's ClassWriter, which computes the frames, and returns Left for a class over a JVM limit (the one place ASM's MethodTooLargeException / ClassTooLargeException become a value). UplcJvm.decompile is its ClassReader. Both are public. A class file survives being read and written again byte for byte.

  • Runtime. List and pair builtins read Data lazily. Builtins used as values, and the rest, run Scalus' CEK meanings. A failure is a stackless MachineError, turned into Scalus' Result by Exec.run.

  • No optimisation of UPLC programs. The compiler translates; it does not optimise. There is no constant folding, inlining, dead-code elimination, CSE, specialisation or tail-call elimination: every operation runs, in the CEK machine's order. The speed-ups come from running as JVM bytecode under the JIT, with values unboxed and calls made directly where the types allow.

Correctness

  • Semantics. Pinned in Semantics.scala: Plutus V3, PV11, variant E, the configuration Scalus 1.3.0 runs the conformance suite under, and the Plutus Core versions it accepts (1.0.0, 1.1.0).
  • Test run. sbt demoUplcJvm/test runs 1067 tests: 1011 passed, 56 skipped, 0 failed.
  • Optic laws. cats-eo-laws' PrismTests check toTyped and toBytecode, over every validator, a closure-valued program, a script declaring Plutus Core 2.0.0, and a program too large for a class file. (JvmClass has no equality, so lowering is checked by the round trips rather than IsoTests.) Oracle.compare also checks the round trips on every program it runs.
  • Sealing and stack safety. OpticSpec checks that changing the arrays and trees a value hands out changes nothing, and compiles programs nested 100 000 deep (force (delay …), builtin calls, lambdas) on a 1 MB stack: each gives a class file, or the JVM limit its class exceeds — never a StackOverflowError.
  • Plutus conformance suite. Plutus 1.63.0.0, vendored. All 943 evaluation cases agree with the CEK machine. The 56 skips are parser-only tests and one bare free-variable program.
  • Validators. Owner + greeting, hash preimage, time lock, 2-of-3 multisig, Fibonacci and HTLC, each compiled with scalus-plugin. There are 20 accepting and rejecting V3 transactions, each checked compiled-then-applied and with the context baked in.
  • The JVM's verifier checks every generated class. Execution budgets are not metered.

Benchmarks (JMH, demos/uplc-jvm-bench, 3 forks)

  • Validation:
    • 8–22× faster than the CEK machine on validators that mostly decode the script context.
    • About 66× faster on the Fibonacci puzzle.
    • 2.9–7.1× faster than this demo's first raw-ASM version.
    • Rejections cost about what acceptances do.
  • Fibonacci scaling: 48× at n=10, 50× at n=100, 22× at n=1000, where large-integer arithmetic dominates.
  • Translation:
    • 82–222 µs to translate, 0.39–0.79 ms with class loading (re-measured after the stack-safety change; a same-session A/B puts its cost at 13–19% of translate). That is about 15% more than the first raw-ASM emitter cost, and about 40% of the intermediate Cojen Maker version's cost.
    • Decoding the script is a pure fold over Scalus' Term tree. It is 2–3× slower than writing into arrays, at a cost of a few microseconds per script.
    • A script pays for its compilation after roughly 13–115 validations.

Size

Code lines (no comments or blanks) against the first raw-ASM version:

before now change
main 1425 1105 −22.5%
whole demo 2218 1745 −21.3%

The prisms, sealing and stack safety added 115 lines of main code (the 37-line Step.scala, plus Lower and Typer written as walks of steps, the prisms and the copies) and 80 lines of tests (the prism laws, misses, copies and depth tests).

Build and CI

  • Three unpublished modules, all outside the root aggregate:
    • demoUplcJvm depends on Scalus and asm-commons. Its tests use asm-util and cats-eo-laws.
    • demoUplcJvmValidators holds the plugin-compiled validators and shared fixtures.
    • demoUplcJvmBench is the JMH project.
  • ci.yml runs the demo tests and compiles the benchmarks on each JDK lane.
  • Scala 3 optimizer.
    • demoUplcJvm compiles with -opt -opt-inline:**,!scala.**. It is unpublished, so it may inline from Scalus, ASM, cats and eo. Inlining from the Scala library is excluded because it made the short validations 12–27% slower: the inlined code makes Rt.force too big for the JIT to inline (seen with -XX:+PrintInlining). Every other scope measured neutral to ~5% faster. The generated classes are byte-identical either way.
    • This touches the published library. scala3LibrarySettings adds -opt-inline:dev.constructive.eo.**, so every library module may inline code from eo's own packages, and never from cats, the JDK or the Scala library. This replaces core's former <sources> scope.
    • The full root-aggregate test suite passes on JDK 25 with these flags.

Limitations

  • No optimisation of UPLC programs (above).
  • No budget metering.
  • One semantics: Plutus V3 at PV11. A script of another Plutus Core version has no typed program.
  • Methods are split at let boundaries only. A class that still exceeds a JVM limit has no class file: toBytecode.getOption is None.
  • Scalus' flat decoder and encoder, which reading and writing a script go through, recurse: on a 1 MB stack they overflow between 2 000 and 20 000 levels deep.
  • Generated code recurses on the JVM stack, so Exec uses a thread with a 512 MB stack.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv

A compiler from Untyped Plutus Core (Cardano smart contracts) to JVM class
files whose spine is a single polymorphic optic:

  Iso[Array[Byte], Array[Byte], TypedProgram, JvmProgram]
      S: flat UPLC   T: class file   A: typed expr   B: JVM-shaped IR

`get` decodes and types, `reverseGet` emits bytecode (ASM), and the compiler
is `iso.modify(Lower.lower)`; `cborScript andThen iso` takes on-chain CBOR.

- Typer (S ⇒ A): re-sugars let / if / saturated builtin calls / direct calls
  of let-bound functions and forced builtins / case-on-constr multi-argument
  calls, with rewrites exact under CEK evaluation order. Hybrid typing keeps
  provable integers, booleans, bytestrings and strings unboxed.
- Lower (A ⇒ B): closure conversion with a capture layout fixed by the
  source, slot allocation, explicit boxing, typed fast paths, and let-body
  outlining to stay under the JVM's 64 KB method limit.
- Runtime: closures, partial builtins, PV11 case-on-builtins, discharge back
  to UPLC terms; builtins delegate to Scalus except the five selectors.

Correctness is differential against the Scalus 1.3.0 CEK machine (Plutus V3,
PV11, variant E): the vendored Plutus conformance suite (plutus 1.63.0.0,
943/943 evaluation cases agree) and Scalus-plugin-compiled validators with
accepting and rejecting V3 script contexts. Every generated class passes
ASM's verifier. Results and errors are compared; budgets are not metered.

The demo and its validator corpus live outside the root aggregate; CI runs
`demoUplcJvm/test` as its own step and checks their formatting and scalafix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Cloudflare Pages preview for ccr-1ec1a317-uds4rn is live:

https://0927a1f3.cats-eo-docs.pages.dev

Branch alias: https://ccr-1ec1a317-uds4rn.cats-eo-docs.pages.dev

Built from commit 94a8ee0ecbd4717af683298b1f2d575f0301ffec · updated on every push.

site/docs/demos/uplc-jvm.md (new "Demos" section in the site nav):

- The idea: a compiler is a polymorphic Iso — S flat UPLC, A typed
  expression, B JVM code, T class file — and `iso.modify(Lower.lower)` is
  the compiler; `cborScript andThen iso` composes on-chain CBOR in front;
  the law that matters is the commuting square against the CEK machine.
- Back and forth: an inline, theme-aware SVG of the round trip, then each
  stage on real output — UPLC text, A (`iso.get`), B (`Lower.lower`), the
  generated bytecode (`javap`), and a closure discharged back to a term,
  α-equal to the CEK machine's result — plus the Fibonacci validator read
  back as A.
- Benchmarks: JMH tables for validation (2.5–3.6× on context-decoding
  validators, ~20× on the recursion-heavy one, 2–14× less allocation),
  Fibonacci scaling (10× → 25× → 18×), and translation cost with the
  break-even number of validations (~10–130).

Supporting changes:

- demos/uplc-jvm-bench: a JMH project (outside the root aggregate and the
  library's nightly sweep) — ValidatorBench, FibonacciBench, TranslateBench;
  setup checks both evaluators accept each transaction before timing. CI
  compiles it and checks its formatting and scalafix.
- Validators module gains the shared off-chain fixtures (Parties,
  Contexts.spending, Scenarios); ValidatorSpec uses them.
- JvmProgram.show renders B as pseudo-code; Demo becomes the stage-by-stage
  walkthrough the page quotes (timings moved to JMH).
- README, CLAUDE.md, benchmarks.md cross-links; ci.yml regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
Scalus already has types for most of what the demo redefined:

- SourceProgram works on Scalus' own decoded Term tree, numbered by
  object identity, instead of a mirror Node enum. Constants are looked
  up by node id.
- A static type is Option[DefaultUni]. Builtin signatures come from
  Scalus' TypeScheme (numTypeVars / arity), replacing Ty, Step,
  Signature and the hand-written PrimOp table. The typed fast paths
  are the builtins Rt defines a method for.
- Evaluation failures are Scalus' MachineError (UplcFailure is gone),
  and Exec.run returns scalus.uplc.eval.Result (Exec.Outcome is gone).

Emit now uses Cojen Maker instead of raw ASM. Code is written against
variables and method names, and Cojen resolves overloads, allocates
locals and computes stack maps. That removes descriptors, the
reflective descriptor table, the B-level case slots and Rt.spread.
The emitter shrinks from 424 to 228 lines, and the generated bytecode
is the same shape.

The embedded program is now Base64. Cojen's constant-pool writer
fails on the non-ASCII strings the Latin-1 encoding produced.
asm-util's verifier is dropped too: the JVM verifies every class when
Exec.load defines it.

Main sources go from 2047 to 1766 lines, and the build depends on
cojen-maker instead of asm + asm-util. The suite is unchanged:
1052 tests, 996 passed, 56 skipped. Re-run JMH: validation speed is
the same within noise (2.6-3.4x on context-decoding validators, ~20x
on Fibonacci). Translation is ~3x slower than with ASM
(160-585 us), so break-even moves to ~25-260 validations. The docs
page, README and CLAUDE.md are updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark A/B

Allocation (B/op) — authoritative

Benchmark params base head Δ
JsoniterBench.jReadId size=64 48.0 72.0 +50.0%
OrderJsoniterBench.eoReadStreet size=512 128.2 72.2 -43.7%
JsoniterBench.jReadId size=8 72.0 48.0 -33.3%
JsoniterBench.jReadId size=512 72.0 48.0 -33.3%
JsoniterBench.jReadStreet size=8 128.0 152.0 +18.7%
JsoniterBench.jReadStreet size=512 128.0 152.0 +18.7%
OptionalBench.mModify_loyalty_empty - 0.0 0.0 +18.0%
JsoniterBench.jReadStreet size=64 152.0 128.0 -15.8%
AffineFoldBench.mGetOption_6 - 0.0 0.0 +11.4%
GetterBench.mGet_6 - 0.0 0.0 -8.7%
GetterBench.eoGet_0 - 0.0 0.0 -6.5%
OptionalBench.mModify_0_empty - 0.0 0.0 +6.2%
AffineFoldBench.eoGetOption_0_asAffineFold - 0.0 0.0 -5.8%
GetterBench.mGet_3 - 0.0 0.0 +5.5%
AffineFoldBench.eoGetOption_0 - 0.0 0.0 -4.7%
JsoniterBench.jMiss size=64 0.0 0.0 -4.1%
OrderCirceBench.eoNamesIor size=512 671,197.2 695,823.9 +3.7%
JsoniterBench.jMiss size=512 0.0 0.0 +3.6%
AffineFoldBench.eoGetOption_0_empty - 0.0 0.0 -3.6%
JsoniterBench.jMiss size=8 0.0 0.0 -3.3%
442 more benchmarks
Benchmark params base head Δ
PowerSeriesNestedBench.eoModify_nested size=4 2,192.0 2,264.0 +3.3%
OpticBuildBench.buildAndUse - 2,816.0 2,888.0 +2.6%
PrismBench.eoGetOptionPresent - 0.0 0.0 -2.3%
SchemesBench.handCata - 0.1 0.1 +2.2%
OrderCirceBench.directNames size=64 76,156.5 77,717.2 +2.0%
OrderCirceBench.hcursorNames size=512 601,633.2 613,950.6 +2.0%
GetterBench.mGet_orderId - 0.0 0.0 -2.0%
OrderCirceBench.eoNames size=64 77,738.7 79,298.6 +2.0%
OrderCirceBench.hcursorNames size=8 10,768.1 10,552.1 -2.0%
OrderCirceBench.eoNamesIor size=8 11,360.1 11,560.1 +1.8%
GetterBench.eoGet_orderId - 0.0 0.0 +1.6%
PowerSeriesNestedBench.eoModify_nested size=16 4,792.0 4,720.0 -1.5%
GenericsBench.handPrismModifyMiss - 0.0 0.0 -1.5%
AvroVulcanBench.encode_bridged - 1,240.0 1,224.0 -1.3%
AvroVulcanBench.encode_vulcanRaw - 1,240.0 1,224.0 -1.3%
MultiFocusCollectBench.eoCollectMap_constSum - 0.0 0.0 +1.3%
AvroJsonBridgeBench.eoClickToJson - 3,952.0 4,000.0 +1.2%
GenericsBench.genPrismGetMiss - 0.0 0.0 +1.2%
PlatedBench.mUniverseJson n=512 699,936.4 691,743.5 -1.2%
CapsBench.foldMapDirect - 0.0 0.0 +1.1%
MultiFocusBench.naive_sumQty size=4 0.0 0.0 -1.0%
PrismBench.eoGetOptionAbsent - 0.0 0.0 -0.9%
GenericsBench.genLensGet - 0.0 0.0 -0.9%
AffineFoldBench.mGetOption_0_empty - 0.0 0.0 +0.9%
OrderCirceBench.directStreet size=8 2,728.0 2,752.0 +0.9%
GenericsBench.handLensGet - 0.0 0.0 -0.7%
JsoniterBench.cSumPrices size=64 156,496.8 157,517.3 +0.7%
AffineFoldBench.eoGetOption_loyalty_empty - 0.0 0.0 +0.6%
PowerSeriesNestedBench.monocle_nested size=4 5,536.0 5,568.0 +0.6%
OptionalBench.eoModify_0_empty - 0.0 0.0 -0.6%
GenericsBench.genPrismModifyMiss - 0.0 0.0 +0.5%
PrismBench.eoGetRightAbsent - 0.0 0.0 -0.5%
SchemesBench.handHylo - 0.1 0.1 -0.5%
AffineFoldBench.mGetOption_3 - 0.0 0.0 -0.5%
PowerSeriesNestedBench.eoModify_nested size=64 14,592.5 14,664.5 +0.5%
ZioDiBench.eoServiceGet - 0.0 0.0 -0.5%
GenericsBench.handPrismGetMiss - 0.0 0.0 +0.5%
CapsBench.foldMapDerivedPerCall - 0.0 0.0 +0.5%
PrismBench.mGetOptionPresent - 0.0 0.0 -0.4%
FoldBench.eoFoldMap size=8 0.0 0.0 -0.4%
GetterBench.eoGet_6 - 0.0 0.0 -0.4%
CapsBench.foldMapCap - 0.0 0.0 -0.4%
KyoDiBench.handMapGet - 0.0 0.0 -0.4%
CapsBench.getDeepCap - 0.0 0.0 -0.4%
CapsBench.foldMapDerivedHeld - 0.0 0.0 -0.4%
CapsBench.getDerivedHeld - 0.0 0.0 -0.3%
LensBench.mGet - 0.0 0.0 -0.3%
OptionalBench.eoModify_loyalty_empty - 0.0 0.0 -0.3%
CapsBench.getDirect - 0.0 0.0 -0.2%
PrismBench.mGetRightAbsent - 0.0 0.0 -0.2%
PrismBench.mGetOptionAbsent - 0.0 0.0 -0.2%
OrderJsoniterBench.nativeSumPrices size=8 1,512.8 1,515.3 +0.2%
KyoDiBench.eoMapGet - 0.0 0.0 -0.1%
OrderJsoniterBench.nativeSumPrices size=512 86,346.1 86,472.2 +0.1%
ZioDiBench.eoDrillGet - 0.0 0.0 -0.1%
GetterBench.mGet_0 - 0.0 0.0 +0.1%
AffineFoldBench.mGetOption_0 - 0.0 0.0 +0.1%
OrderJsoniterBench.monocleSumPrices size=8 6,448.0 6,440.0 -0.1%
JsoniterBench.cReplaceId size=8 20,643.3 20,667.3 +0.1%
JsoniterBench.cModifyId size=8 20,691.3 20,715.3 +0.1%
PowerSeriesBench.monocle_powerEach size=64 14,520.1 14,504.1 -0.1%
CapsBench.getDerivedPerCall - 0.0 0.0 -0.1%
FoldBench.mFoldMap size=8 0.0 0.0 +0.1%
CapsBench.getCap - 0.0 0.0 +0.1%
OrderAvroBench.naiveModifyNames size=64 27,912.2 27,936.2 +0.1%
OrderCirceBench.monocleNames size=8 19,456.1 19,472.1 +0.1%
AffineFoldBench.eoGetOption_loyalty - 0.0 0.0 +0.1%
AffineFoldBench.mGetOption_loyalty_empty - 0.0 0.0 +0.1%
LensBench.eoGet - 0.0 0.0 +0.1%
OrderCirceBench.eoNamesIor size=64 87,490.1 87,552.0 +0.1%
OrderAvroBench.monocleModifyNames size=64 39,841.1 39,865.0 +0.1%
OrderCirceBench.eoStreet size=64 2,721.2 2,720.1 -0.0%
OrderJsoniterBench.nativeSumPrices size=64 10,948.1 10,944.3 -0.0%
PowerSeriesNestedBench.eoModify_nested size=1024 210,442.7 210,512.4 +0.0%
CapsBench.getDeepDirect - 0.0 0.0 -0.0%
OrderCirceBench.eoStreet size=8 2,720.8 2,720.0 -0.0%
OrderCirceBench.monocleStreet size=64 113,812.1 113,844.0 +0.0%
OrderCirceBench.eoStreetIor size=8 2,736.8 2,736.0 -0.0%
AffineFoldBench.mGetOption_loyalty - 0.0 0.0 -0.0%
GenericsBench.rawLensGet - 0.0 0.0 -0.0%
PlatedBench.visitorUniverseJson n=4096 295,053.4 294,994.8 -0.0%
OrderCirceBench.naiveNames size=64 120,808.5 120,832.4 +0.0%
JsoniterBench.cModifyId size=64 136,271.4 136,295.6 +0.0%
JsoniterBench.cReplaceId size=64 136,223.4 136,247.6 +0.0%
GetterBench.eoGet_3 - 0.0 0.0 -0.0%
OrderJsoniterBench.nativeReadStreet size=512 454.3 454.3 -0.0%
MultiFocusBench.eoModify_multiFocus size=1024 331,102.8 331,078.4 -0.0%
JsoniterBench.cModifyId size=512 1,066,728.6 1,066,803.8 +0.0%
OrderAvroBench.monocleModifyStreet size=512 169,078.1 169,084.1 +0.0%
JsoniterBench.cReplaceId size=512 1,066,678.5 1,066,710.2 +0.0%
OrderCirceBench.hcursorNames size=64 77,808.1 77,806.2 -0.0%
OrderCirceBench.eoNames size=512 626,313.5 626,304.2 -0.0%
PlatedBench.mUniverseJson n=4096 6,491,325.0 6,491,241.4 -0.0%
PlatedBench.mUniverseExpr n=4096 4,689,262.3 4,689,205.1 -0.0%
PowerSeriesBench.naive_powerEach size=4096 114,779.5 114,780.8 +0.0%
PowerSeriesNestedBench.monocle_nested size=1024 1,118,799.3 1,118,812.4 +0.0%
OrderJsoniterBench.nativeReadStreet size=64 424.5 424.5 +0.0%
OrderAvroBench.eoModifyNames size=512 97,422.9 97,421.8 -0.0%
MultiFocusBench.eoFold_powerEach size=1024 43,036.7 43,036.2 -0.0%
PowerSeriesBench.monocle_powerEach size=4096 967,861.9 967,854.7 -0.0%
OrderAvroBench.monocleReadStreet size=512 69,786.8 69,786.3 -0.0%
OrderCirceBench.hcursorStreet size=512 3,032.7 3,032.7 -0.0%
OrderCirceBench.eoStreetIor size=512 2,736.7 2,736.7 +0.0%
OrderCirceBench.directNames size=512 601,636.3 601,633.3 -0.0%
JsoniterBench.cReadStreet size=64 101,303.9 101,303.4 -0.0%
MultiFocusBench.eoModify_powerEach size=1024 115,176.7 115,176.2 -0.0%
PowerSeriesPrismBench.eoModify_sparse size=2048 104,681.2 104,680.7 -0.0%
TraversalBench.mModify size=512 176,897.2 176,898.0 +0.0%
PowerSeriesBench.monocle_powerEach size=4 1,176.0 1,176.0 +0.0%
OrderJsoniterBench.monocleSumPrices size=512 1,178,381.5 1,178,376.9 -0.0%
OrderJsoniterBench.eoModifyStreet size=512 42,029.9 42,029.7 -0.0%
PowerSeriesBench.eoModify_powerEach size=4096 164,368.5 164,367.9 -0.0%
OrderJsoniterBench.naiveSumPrices size=512 230,108.4 230,107.6 -0.0%
OrderJsoniterBench.naiveModifyStreet size=512 333,548.1 333,546.9 -0.0%
PlatedBench.eoTransformDeep n=4096 624,386.6 624,384.4 -0.0%
MultiFocusBench.naive_sumQty size=1024 16,129.4 16,129.3 -0.0%
OrderAvroBench.naiveReadStreet size=512 69,786.3 69,786.1 -0.0%
OrderJsoniterBench.eoSumPrices size=512 63,684.1 63,684.0 -0.0%
OrderCirceBench.naiveStreet size=64 113,806.7 113,807.0 +0.0%
PowerSeriesBench.eoModify_powerEach size=1024 41,413.7 41,413.6 -0.0%
OrderCirceBench.eoStreet size=512 2,720.7 2,720.7 -0.0%
OrderAvroBench.naiveModifyStreet size=512 169,060.4 169,060.0 -0.0%
JsoniterBench.jSumPrices size=512 63,630.3 63,630.4 +0.0%
PowerSeriesPrismBench.monocle_sparse size=2048 523,139.1 523,137.9 -0.0%
OrderJsoniterBench.monocleModifyStreet size=512 333,572.3 333,571.6 -0.0%
OrderJsoniterBench.monocleReadStreet size=512 193,214.8 193,214.4 -0.0%
PowerSeriesPrismBench.monocle_sparse size=512 166,691.9 166,691.5 -0.0%
PlatedBench.eoTransformExpr n=4096 655,356.4 655,355.1 -0.0%
OrderJsoniterBench.monocleSumPrices size=64 45,835.2 45,835.3 +0.0%
OrderCirceBench.hcursorStreet size=64 3,032.1 3,032.1 -0.0%
PowerSeriesNestedBench.eoModify_nested size=256 53,770.7 53,770.9 +0.0%
PlatedBench.visitorTransformExpr n=4096 360,472.5 360,471.8 -0.0%
JsoniterBench.cReadId size=64 101,303.9 101,303.7 -0.0%
PlatedBench.mTransformExpr n=4096 753,724.5 753,723.3 -0.0%
PlatedBench.eoUniverseJson n=4096 786,459.6 786,460.9 +0.0%
PowerSeriesNestedBench.naive_nested size=1024 115,071.7 115,071.5 -0.0%
OrderCirceBench.monocleNames size=64 132,761.6 132,761.4 -0.0%
OrderAvroBench.eoModifyStreet size=512 328.0 328.0 -0.0%
PowerSeriesNestedBench.naive_nested size=256 29,019.3 29,019.3 -0.0%
PlatedBench.visitorUniverseDeep n=4096 196,707.9 196,707.6 -0.0%
OrderCirceBench.directStreet size=512 2,728.7 2,728.7 +0.0%
JsoniterBench.jModifyId size=512 41,921.7 41,921.7 -0.0%
PowerSeriesBench.naive_powerEach size=1024 28,730.8 28,730.7 -0.0%
PlatedBench.eoUniverseDeep n=4096 786,610.4 786,609.5 -0.0%
OrderJsoniterBench.monocleModifyStreet size=64 30,081.6 30,081.5 -0.0%
PlatedBench.visitorUniverseExpr n=4096 196,654.3 196,654.1 -0.0%
JsoniterBench.cSumPrices size=512 1,240,754.0 1,240,752.7 -0.0%
OrderJsoniterBench.naiveModifyStreet size=64 30,057.7 30,057.7 -0.0%
OrderAvroBench.eoReadStreet size=512 88.0 88.0 -0.0%
PowerSeriesPrismBench.eoModify_sparse size=512 24,785.5 24,785.5 -0.0%
PlatedBench.mUniverseExpr n=512 475,028.5 475,028.9 +0.0%
JsoniterBench.jReplaceId size=512 41,889.7 41,889.6 -0.0%
OrderCirceBench.eoStreetIor size=64 2,736.1 2,736.1 +0.0%
MultiFocusBench.naive_listMap size=1024 65,578.7 65,578.7 -0.0%
OrderCirceBench.naiveStreet size=512 908,003.7 908,003.1 -0.0%
OrderCirceBench.monocleNames size=512 1,121,753.7 1,121,754.4 +0.0%
OrderJsoniterBench.eoSumPrices size=8 1,176.0 1,176.0 +0.0%
PowerSeriesBench.monocle_powerEach size=1024 279,426.9 279,427.1 +0.0%
OrderJsoniterBench.eoReadStreet size=8 72.0 72.0 -0.0%
OrderAvroBench.monocleModifyNames size=512 382,754.5 382,754.3 -0.0%
TraversalBench.eoFoldPrices size=512 12,312.3 12,312.3 -0.0%
FoldBench.mFoldPrices size=512 12,312.4 12,312.4 -0.0%
FoldBench.eoFoldMap size=512 7,936.2 7,936.2 -0.0%
PlatedBench.eoUniverseExpr n=4096 786,416.8 786,417.2 +0.0%
OrderAvroBench.naiveModifyNames size=512 226,292.5 226,292.6 +0.0%
PowerSeriesPrismBench.naive_sparse size=2048 24,613.2 24,613.2 -0.0%
OrderCirceBench.naiveNames size=512 965,242.9 965,243.3 +0.0%
OrderCirceBench.directStreet size=64 2,728.1 2,728.1 -0.0%
PowerSeriesPrismBench.eoModify_sparse size=8 496.0 496.0 -0.0%
PlatedBench.eoUniverseJson n=64 12,168.1 12,168.1 -0.0%
OrderCirceBench.monocleStreet size=512 908,004.1 908,003.8 -0.0%
PowerSeriesPrismBench.naive_sparse size=512 6,176.4 6,176.4 -0.0%
MultiFocusBench.eoFold_powerEach size=256 9,240.2 9,240.2 -0.0%
PowerSeriesBench.eoModify_powerEach size=256 10,688.4 10,688.4 +0.0%
PlatedBench.eoUniverseDeep n=64 12,360.0 12,360.0 -0.0%
JsoniterBench.jSumPrices size=64 8,120.3 8,120.3 -0.0%
AvroBytesBench.eoModifyPartner - 984.0 984.0 -0.0%
SchemesBench.eoCata - 197,568.5 197,568.4 -0.0%
AvroBytesBench.naiveReadPartner - 5,424.0 5,424.0 -0.0%
PowerSeriesNestedBench.monocle_nested size=64 58,833.1 58,833.0 -0.0%
PlatedBench.visitorUniverseExpr n=512 24,584.7 24,584.7 -0.0%
PlatedBench.visitorTransformDeep n=512 20,496.5 20,496.5 -0.0%
OrderJsoniterBench.nativeReadStreet size=8 424.0 424.0 +0.0%
FoldBench.mFoldMap size=512 7,936.2 7,936.2 -0.0%
PlatedBench.eoTransformDeep n=512 57,361.5 57,361.4 -0.0%
PlatedBench.mTransformExpr n=512 69,585.4 69,585.4 -0.0%
PlatedBench.visitorUniverseJson n=512 40,954.3 40,954.3 +0.0%
OrderJsoniterBench.eoSumPrices size=64 8,121.1 8,121.1 +0.0%
OrderJsoniterBench.eoModifyStreet size=64 5,432.1 5,432.1 -0.0%
PowerSeriesPrismBench.eoModify_sparse size=32 1,360.0 1,360.0 -0.0%
PlatedBench.visitorUniverseJson n=64 5,096.0 5,096.0 -0.0%
AvroBytesBench.eoReadCountry - 520.0 520.0 -0.0%
OrderJsoniterBench.naiveSumPrices size=64 29,337.0 29,337.0 +0.0%
JsoniterBench.cReadStreet size=512 797,920.6 797,920.4 -0.0%
PlatedBench.visitorUniverseDeep n=512 24,632.8 24,632.8 -0.0%
OrderJsoniterBench.naiveModifyStreet size=8 4,640.1 4,640.1 -0.0%
JsoniterBench.jSumPrices size=8 1,176.0 1,176.0 +0.0%
PowerSeriesPrismBench.naive_sparse size=128 1,568.0 1,568.0 -0.0%
TraversalBench.eoFoldNested size=512 20,200.8 20,200.8 -0.0%
OrderJsoniterBench.naiveReadStreet size=512 193,214.6 193,214.6 -0.0%
PlatedBench.eoTransformExpr n=512 81,825.7 81,825.7 -0.0%
PlatedBench.eoUniverseDeep n=512 98,377.9 98,377.9 -0.0%
PowerSeriesPrismBench.eoModify_sparse size=128 4,816.1 4,816.1 -0.0%
PowerSeriesPrismBench.monocle_sparse size=128 27,808.2 27,808.2 -0.0%
PowerSeriesNestedBench.monocle_nested size=256 430,194.6 430,194.7 +0.0%
OrderJsoniterBench.monocleReadStreet size=64 24,704.9 24,704.9 -0.0%
PowerSeriesNestedBench.monocle_nested size=16 15,776.1 15,776.1 -0.0%
PlatedBench.visitorTransformExpr n=512 45,032.8 45,032.8 -0.0%
PowerSeriesBench.eoModify_powerEach size=64 3,008.0 3,008.0 -0.0%
AvroJsonBridgeBench.eoWideToJson - 1,472.0 1,472.0 -0.0%
OrderAvroBench.monocleModifyStreet size=64 20,904.2 20,904.2 -0.0%
AvroBytesBench.prunedReadCountry - 1,976.0 1,976.0 -0.0%
OrderJsoniterBench.monocleModifyStreet size=8 4,664.1 4,664.1 -0.0%
OrderJsoniterBench.eoModifyStreet size=8 1,072.0 1,072.0 -0.0%
PlatedBench.mUniverseExpr n=64 45,424.6 45,424.6 +0.0%
TraversalBench.mFoldPrices size=8 2,000.0 2,000.0 -0.0%
OrderAvroBench.monocleReadStreet size=64 8,848.1 8,848.1 -0.0%
TraversalBench.eoFoldNested size=64 2,680.0 2,680.0 -0.0%
OrderJsoniterBench.naiveReadStreet size=64 24,704.9 24,704.9 -0.0%
PowerSeriesBench.monocle_powerEach size=256 107,335.5 107,335.5 +0.0%
MultiFocusBench.naive_sumQty size=256 3,840.0 3,840.0 -0.0%
MultiFocusBench.naive_listMap size=256 16,424.2 16,424.2 -0.0%
PlatedBench.visitorTransformDeep n=4096 163,888.0 163,888.0 +0.0%
OrderAvroBench.naiveModifyNames size=8 3,752.0 3,752.0 -0.0%
SchemesBench.eoHylo - 295,848.5 295,848.6 +0.0%
AvroBytesBench.naiveModifyPartner - 8,696.0 8,696.0 -0.0%
TraversalBench.mFoldPrices size=512 162,564.6 162,564.6 +0.0%
JsoniterBench.jModifyId size=64 5,328.0 5,328.0 -0.0%
PowerSeriesNestedBench.naive_nested size=16 2,136.0 2,136.0 -0.0%
PowerSeriesBench.eoModify_powerEach size=16 1,088.0 1,088.0 -0.0%
OrderAvroBench.naiveModifyStreet size=64 20,880.2 20,880.2 -0.0%
MultiFocusBench.eoFold_powerEach size=32 920.0 920.0 -0.0%
PowerSeriesBench.naive_powerEach size=256 7,224.2 7,224.2 -0.0%
FoldBench.eoFoldPrices size=512 12,312.4 12,312.4 -0.0%
AvroJsonBridgeBench.naiveClickToJson - 5,856.0 5,856.0 -0.0%
OrderJsoniterBench.naiveReadStreet size=8 3,648.0 3,648.0 +0.0%
AvroBytesBench.eoReadPartner - 480.0 480.0 -0.0%
OrderCirceBench.eoNames size=8 10,944.1 10,944.1 -0.0%
OrderAvroBench.monocleModifyStreet size=8 2,992.0 2,992.0 -0.0%
PlatedBench.eoUniverseJson n=512 98,186.5 98,186.5 -0.0%
OrderJsoniterBench.eoReadStreet size=64 128.0 128.0 +0.0%
SchemesBench.eoAna - 589,712.8 589,712.7 -0.0%
TraversalBench.eoModify size=64 4,640.0 4,640.0 -0.0%
FoldBench.eoFoldPrices size=8 216.0 216.0 -0.0%
AvroBytesBench.prunedReadPartner - 1,592.0 1,592.0 -0.0%
AvroBytesBench.naivePassthroughPayload - 14,088.1 14,088.1 -0.0%
OrderAvroBench.eoModifyNames size=64 12,616.1 12,616.1 +0.0%
MultiFocusBench.eoModify_powerEach size=256 26,080.5 26,080.5 +0.0%
AvroVulcanBench.fieldGet_native - 432.0 432.0 -0.0%
OrderCirceBench.naiveStreet size=8 17,040.1 17,040.1 -0.0%
PlatedBench.mUniverseJson n=64 73,208.7 73,208.7 -0.0%
PowerSeriesPrismBench.monocle_sparse size=8 1,952.0 1,952.0 -0.0%
SchemesBench.drosteHylo - 328,640.4 328,640.4 -0.0%
ClickRecordBench.encode_derivedThroughPrism - 744.0 744.0 +0.0%
AvroEncodeRouteBench.naive_freshPlumbing - 2,624.0 2,624.0 -0.0%
PowerSeriesNestedBench.naive_nested size=64 7,512.2 7,512.2 -0.0%
OrderAvroBench.eoReadStreet size=64 88.0 88.0 -0.0%
OptionalBench.mModify_loyalty - 112.0 112.0 +0.0%
OpticBuildBench.reuseUse - 2,720.0 2,720.0 +0.0%
AvroBytesBench.naiveModifyCountry - 7,616.0 7,616.0 +0.0%
MultiFocusBench.eoModify_multiFocus size=32 8,600.0 8,600.0 -0.0%
OrderAvroBench.eoReadStreet size=8 88.0 88.0 -0.0%
MultiFocusBench.eoModify_multiFocus size=256 76,112.7 76,112.7 -0.0%
PowerSeriesPrismBench.monocle_sparse size=32 7,040.0 7,040.0 +0.0%
OrderAvroBench.naiveReadStreet size=64 8,848.1 8,848.1 -0.0%
OrderJsoniterBench.monocleReadStreet size=8 3,648.0 3,648.0 -0.0%
PowerSeriesPrismBench.naive_sparse size=32 416.0 416.0 -0.0%
AffineFoldBench.eoGetOption_6 - 16.0 16.0 -0.0%
AvroJsonBridgeBench.eoClickToAvro - 4,664.0 4,664.0 -0.0%
OrderCirceBench.hcursorStreet size=8 3,032.0 3,032.0 -0.0%
AvroBytesBench.eoModifyCountry - 928.0 928.0 -0.0%
AvroDecodeReuseBench.freshDecodeRecord - 3,344.0 3,344.0 -0.0%
SchemesBench.handAna - 163,816.2 163,816.2 -0.0%
PowerSeriesNestedBench.naive_nested size=4 792.0 792.0 -0.0%
OptionalBench.eoModify_6 - 208.0 208.0 +0.0%
FoldBench.mFoldPrices size=64 1,560.0 1,560.0 -0.0%
AvroDecodeReuseBench.confluentRecordReader - 1,560.0 1,560.0 -0.0%
OrderCirceBench.monocleStreet size=8 17,048.1 17,048.1 -0.0%
MultiFocusBench.eoModify_multiFocus size=4 1,320.0 1,320.0 -0.0%
AvroEncodeRouteBench.eo_encodeToAny - 312.0 312.0 -0.0%
JsoniterBench.jModifyId size=8 992.0 992.0 -0.0%
MultiFocusCollectBench.eoModify_multiFocusTuple3 - 96.0 96.0 -0.0%
JsoniterBench.cReadStreet size=8 15,568.0 15,568.0 +0.0%
TraversalBench.eoModify size=512 36,897.3 36,897.3 +0.0%
MultiFocusBench.eoModify_powerEach size=32 3,152.0 3,152.0 -0.0%
PowerSeriesBench.eoModify_powerEach size=4 608.0 608.0 -0.0%
FoldBench.mFoldMap size=64 768.0 768.0 -0.0%
AvroVulcanBench.rootGet_native - 600.0 600.0 +0.0%
TraversalBench.eoFoldPrices size=64 1,560.0 1,560.0 -0.0%
TraversalBench.mFoldPrices size=64 15,408.1 15,408.1 -0.0%
MultiFocusBench.naive_listMap size=32 2,088.0 2,088.0 -0.0%
OrderAvroBench.naiveReadStreet size=8 1,208.0 1,208.0 -0.0%
ClickRecordBench.encode_derived - 744.0 744.0 +0.0%
OptionalBench.mModify_6 - 496.0 496.0 +0.0%
IsoBench.mReverseGet - 32.0 32.0 -0.0%
FoldBench.eoFoldMap size=64 768.0 768.0 -0.0%
MultiFocusCollectBench.eoModify_multiFocusTuple6 - 248.0 248.0 -0.0%
FoldBench.eoFoldPrices size=64 1,560.0 1,560.0 -0.0%
AvroJsonBridgeBench.naiveWideToAvro - 3,504.0 3,504.0 -0.0%
KyoDiBench.handMapDrillModify - 216.0 216.0 -0.0%
MultiFocusBench.naive_sumQty size=32 256.0 256.0 -0.0%
PlatedBench.eoUniverseExpr n=64 12,168.0 12,168.0 -0.0%
CompositionBench.reuseLens1 - 40.0 40.0 -0.0%
MultiFocusCollectBench.naive_constSum - 16.0 16.0 +0.0%
AvroEncodeRouteBench.handwritten_stream - 240.0 240.0 +0.0%
JsoniterBench.jReplaceId size=64 5,296.0 5,296.0 -0.0%
JsoniterBench.cReadId size=512 797,920.9 797,920.8 -0.0%
PlatedBench.visitorTransformExpr n=64 5,608.0 5,608.0 -0.0%
OrderAvroBench.naiveModifyStreet size=8 2,968.0 2,968.0 -0.0%
OrderAvroBench.monocleReadStreet size=8 1,208.0 1,208.0 +0.0%
OrderAvroBench.eoModifyStreet size=8 328.0 328.0 -0.0%
JsoniterBench.jReplaceId size=8 960.0 960.0 -0.0%
KyoDiBench.eoMapDrillModify - 216.0 216.0 -0.0%
MultiFocusCollectBench.eoCollectList_listSum - 56.0 56.0 -0.0%
GenericsBench.genLensModify - 24.0 24.0 -0.0%
CompositionBench.buildLens6 - 352.0 352.0 -0.0%
MultiFocusCollectBench.eoCollectMap_zipMean - 880.0 880.0 -0.0%
MultiFocusBench.naive_listMap size=4 296.0 296.0 -0.0%
OptionalBench.eoModify_0 - 112.0 112.0 -0.0%
TraversalBench.eoModify size=8 608.0 608.0 -0.0%
PrismBench.eoGetRightPresent - 16.0 16.0 -0.0%
JsoniterBench.cSumPrices size=8 22,720.1 22,720.1 -0.0%
OrderJsoniterBench.naiveSumPrices size=8 4,248.0 4,248.0 -0.0%
JsoniterBench.cReadId size=8 15,568.0 15,568.0 -0.0%
PlatedBench.eoTransformExpr n=64 10,144.0 10,144.0 -0.0%
PlatedBench.visitorUniverseDeep n=64 3,128.0 3,128.0 -0.0%
PlatedBench.mTransformExpr n=64 11,728.0 11,728.0 -0.0%
GenericsBench.rawPrismGetHit - 16.0 16.0 -0.0%
LensBench.eoModifyDeep - 152.0 152.0 -0.0%
AvroBytesBench.naiveReadCountry - 4,256.0 4,256.0 +0.0%
IsoBench.mGet - 32.0 32.0 -0.0%
TraversalBench.mModify size=64 14,408.1 14,408.1 -0.0%
AvroVulcanBench.fieldGet_bridged - 432.0 432.0 -0.0%
GenericsBench.rawLensModify - 24.0 24.0 -0.0%
PlatedBench.eoTransformDeep n=64 7,184.0 7,184.0 -0.0%
OrderAvroBench.eoModifyStreet size=64 328.0 328.0 -0.0%
AffineFoldBench.eoGetOption_0_asOptional - 16.0 16.0 -0.0%
SetterBench.mModify_orderId - 40.0 40.0 -0.0%
MultiFocusCollectBench.naive_tuple3Rewrite - 96.0 96.0 -0.0%
SetterBench.eoModify_3 - 72.0 72.0 -0.0%
PrismBench.mGetRightPresent - 16.0 16.0 -0.0%
PowerSeriesBench.naive_powerEach size=64 1,848.0 1,848.0 +0.0%
PrismBench.mRightReverseGet - 16.0 16.0 -0.0%
TraversalBench.mModify size=8 1,896.0 1,896.0 -0.0%
OptionalBench.mReplace_0 - 40.0 40.0 -0.0%
MultiFocusBench.eoModify_powerEach size=4 800.0 800.0 -0.0%
PowerSeriesBench.naive_powerEach size=16 504.0 504.0 -0.0%
LensBench.mModifyDeep - 176.0 176.0 +0.0%
ReviewBench.eoReverseGet_6 - 120.0 120.0 -0.0%
OrderAvroBench.eoModifyNames size=8 1,992.0 1,992.0 -0.0%
ReviewBench.naiveBuild_6 - 120.0 120.0 -0.0%
KyoDiBench.handVarUpdate - 200.0 200.0 +0.0%
SchemesBench.drosteCata - 164,824.3 164,824.2 -0.0%
CompositionBench.buildLens3 - 184.0 184.0 -0.0%
AvroJsonBridgeBench.naiveClickToAvro - 3,928.0 3,928.0 -0.0%
LensBench.mModify - 40.0 40.0 -0.0%
AvroDecodeReuseBench.confluentRecordReaderFresh - 3,696.0 3,696.0 -0.0%
PrismBench.mReverseGet - 16.0 16.0 -0.0%
AvroBytesBench.eoSliceGraftPayload - 1,192.0 1,192.0 +0.0%
AvroVulcanBench.decode_native - 48.0 48.0 -0.0%
ClickRecordBench.encode_hand - 768.0 768.0 -0.0%
GenericsBench.genPrismModifyHit - 24.0 24.0 -0.0%
ReviewBench.naiveBuild_0 - 24.0 24.0 -0.0%
GenericsBench.genPrismGetHit - 16.0 16.0 -0.0%
AvroBytesBench.eoGraftPayload - 720.0 720.0 -0.0%
GenericsBench.handPrismModifyHit - 24.0 24.0 -0.0%
CompositionBench.reuseLens6 - 120.0 120.0 -0.0%
OptionalBench.mModify_0 - 112.0 112.0 -0.0%
CapsBench.modifyDirect - 40.0 40.0 -0.0%
CompositionBench.buildLens1 - 72.0 72.0 -0.0%
SchemesBench.drosteAna - 327,632.4 327,632.4 -0.0%
GenericsBench.handLensModify - 24.0 24.0 +0.0%
PrismBench.eoRightReverseGet - 16.0 16.0 -0.0%
OptionalBench.eoModify_loyalty - 112.0 112.0 -0.0%
AvroDecodeReuseBench.cachedDecodeRecord - 1,224.0 1,224.0 -0.0%
IsoBench.eoGet - 32.0 32.0 -0.0%
OrderCirceBench.directNames size=8 10,688.1 10,688.1 -0.0%
ClickRecordBench.encode_vulcanFull - 28,408.0 28,408.0 -0.0%
ZioDiBench.eoDrillModify - 472.0 472.0 +0.0%
GenericsBench.rawPrismModifyHit - 24.0 24.0 -0.0%
TraversalBench.eoFoldPrices size=8 216.0 216.0 -0.0%
MultiFocusCollectBench.naive_zipMeanBroadcast - 1,176.0 1,176.0 -0.0%
AvroEncodeRouteBench.eo_encodeValue - 568.0 568.0 +0.0%
SetterBench.mModify_0 - 24.0 24.0 +0.0%
TraversalBench.eoFoldNested size=8 328.0 328.0 -0.0%
SetterBench.mModify_6 - 288.0 288.0 +0.0%
CapsBench.modifyDeepDirect - 152.0 152.0 -0.0%
CompositionBench.reuseLeaf - 24.0 24.0 -0.0%
PlatedBench.visitorTransformDeep n=64 2,576.0 2,576.0 +0.0%
OptionalBench.eoReplace_0 - 40.0 40.0 -0.0%
ClickRecordBench.encode_positional - 23,912.0 23,912.0 -0.0%
AvroVulcanBench.decode_vulcanRaw - 832.0 832.0 -0.0%
PowerSeriesBench.monocle_powerEach size=16 3,720.0 3,720.0 +0.0%
FoldBench.mFoldPrices size=8 216.0 216.0 -0.0%
PowerSeriesBench.naive_powerEach size=4 168.0 168.0 -0.0%
CompositionBench.reuseLens3 - 72.0 72.0 +0.0%
ZioDiBench.handDrillModify - 592.0 592.0 +0.0%
ReviewBench.eoReverseGet_0 - 24.0 24.0 -0.0%
OrderCirceBench.naiveNames size=8 17,808.1 17,808.1 +0.0%
CompositionBench.reuseLensOptional3 - 160.0 160.0 -0.0%
PrismBench.eoReverseGet - 16.0 16.0 -0.0%
CompositionBench.buildLensOptional3 - 184.0 184.0 -0.0%
LensBench.eoReplace - 40.0 40.0 -0.0%
PowerSeriesPrismBench.naive_sparse size=8 128.0 128.0 -0.0%
MultiFocusCollectBench.naive_tuple6Rewrite - 184.0 184.0 -0.0%
AvroVulcanBench.encode_native - 56.0 56.0 +0.0%
GenericsBench.handPrismGetHit - 16.0 16.0 +0.0%
AvroJsonBridgeBench.eoWideToAvro - 2,040.0 2,040.0 -0.0%
SetterBench.mModify_3 - 168.0 168.0 -0.0%
ZioDiBench.handServiceReplace - 520.0 520.0 -0.0%
SetterBench.eoModify_orderId - 40.0 40.0 -0.0%
OrderAvroBench.monocleModifyNames size=8 5,400.0 5,400.0 +0.0%
PlatedBench.visitorUniverseExpr n=64 3,080.0 3,080.0 -0.0%
OptionalBench.eoReplace_loyalty - 88.0 88.0 -0.0%
OptionalBench.mModify_3 - 304.0 304.0 -0.0%
ZioDiBench.eoServiceReplace - 400.0 400.0 -0.0%
SetterBench.eoModify_0 - 24.0 24.0 -0.0%
AvroVulcanBench.decode_bridged - 832.0 832.0 -0.0%
ReviewBench.naiveBuild_3 - 72.0 72.0 +0.0%
AvroVulcanBench.rootGet_bridged - 1,424.0 1,424.0 -0.0%
KyoDiBench.eoEnvFocus - 320.0 320.0 -0.0%
MultiFocusBench.eoFold_powerEach size=4 328.0 328.0 -0.0%
SetterBench.eoModify_6 - 120.0 120.0 +0.0%
CapsBench.modifyDeepCap - 176.0 176.0 +0.0%
ReviewBench.eoReverseGet_3 - 72.0 72.0 -0.0%
LensBench.eoModify - 40.0 40.0 +0.0%
OptionalBench.eoModify_3 - 160.0 160.0 +0.0%
PlatedBench.eoUniverseExpr n=512 98,185.8 98,185.8 +0.0%
OpticBuildBench.build - 184.0 184.0 -0.0%
CapsBench.modifyCap - 40.0 40.0 -0.0%
AffineFoldBench.eoGetOption_3 - 16.0 16.0 -0.0%
CapsBench.modifyDerivedHeld - 40.0 40.0 +0.0%
AvroJsonBridgeBench.naiveWideToJson - 4,376.0 4,376.0 +0.0%
LensBench.mReplace - 40.0 40.0 -0.0%
ZioDiBench.handServiceGet - 120.0 120.0 +0.0%
ZioDiBench.handDrillGet - 120.0 120.0 -0.0%
IsoBench.eoReverseGet - 32.0 32.0 -0.0%
MultiFocusCollectBench.naive_listSum - 56.0 56.0 -0.0%
OptionalBench.mReplace_loyalty - 88.0 88.0 -0.0%
KyoDiBench.eoVarUpdateFocus - 216.0 216.0 +0.0%
KyoDiBench.handEnvUse - 312.0 312.0 -0.0%
CapsBench.modifyDerivedPerCall - 40.0 40.0 +0.0%
Timing (ns/op) — directional only, same-VM but shared runner
Benchmark params base head Δ
PowerSeriesNestedBench.monocle_nested size=4 1,024.9 1,218.6 +18.9%
OptionalBench.mModify_loyalty_empty - 1.6 1.9 +18.0%
JsoniterBench.jReadId size=64 28.4 33.0 +16.2%
PlatedBench.visitorUniverseJson n=4096 117,366.2 135,687.5 +15.6%
JsoniterBench.jReadId size=512 32.7 27.8 -15.2%
JsoniterBench.jReadId size=8 32.9 28.2 -14.4%
SchemesBench.eoCata - 66,167.5 57,023.5 -13.8%
AffineFoldBench.mGetOption_6 - 18.7 20.8 +11.0%
MultiFocusBench.eoFold_powerEach size=1024 17,991.9 16,164.3 -10.2%
MultiFocusBench.eoModify_multiFocus size=1024 63,564.0 57,337.7 -9.8%
GetterBench.mGet_6 - 20.7 19.0 -8.3%
SchemesBench.eoHylo - 75,582.7 80,727.0 +6.8%
OptionalBench.mModify_0_empty - 1.3 1.4 +6.4%
OrderCirceBench.eoStreet size=8 877.7 822.8 -6.3%
GetterBench.eoGet_0 - 0.8 0.8 -6.2%
MultiFocusBench.eoModify_powerEach size=1024 33,685.3 31,597.8 -6.2%
SchemesBench.eoAna - 107,696.7 101,027.4 -6.2%
OrderCirceBench.hcursorStreet size=64 947.0 891.4 -5.9%
AvroBytesBench.eoModifyPartner - 327.7 308.8 -5.8%
OrderCirceBench.eoNames size=512 201,496.0 189,922.6 -5.7%
FoldBench.eoFoldPrices size=8 31.3 29.5 -5.7%
AffineFoldBench.eoGetOption_0_asAffineFold - 0.8 0.8 -5.7%
AvroBytesBench.naiveReadPartner - 1,946.6 1,839.3 -5.5%
GetterBench.mGet_3 - 6.4 6.8 +5.4%
SchemesBench.drosteHylo - 58,893.6 55,773.7 -5.3%
AvroVulcanBench.fieldGet_native - 87.8 83.2 -5.2%
AvroJsonBridgeBench.eoWideToJson - 536.5 508.6 -5.2%
OptionalBench.mModify_loyalty - 16.8 17.7 +5.1%
AvroBytesBench.eoReadCountry - 148.5 141.6 -4.7%
AffineFoldBench.eoGetOption_0 - 0.9 0.9 -4.5%
OrderCirceBench.eoStreetIor size=8 843.2 880.4 +4.4%
OrderAvroBench.naiveModifyNames size=8 949.2 907.7 -4.4%
JsoniterBench.jMiss size=64 168.8 162.0 -4.0%
OrderCirceBench.directStreet size=8 888.3 852.9 -4.0%
OrderCirceBench.hcursorNames size=512 181,214.3 188,075.4 +3.8%
PowerSeriesBench.eoModify_powerEach size=16 209.8 201.9 -3.7%
MultiFocusBench.naive_sumQty size=1024 5,371.7 5,171.0 -3.7%
MultiFocusCollectBench.eoModify_multiFocusTuple3 - 13.6 13.1 -3.7%
PowerSeriesPrismBench.monocle_sparse size=8 368.3 355.0 -3.6%
MultiFocusBench.eoModify_multiFocus size=4 203.8 196.5 -3.6%
JsoniterBench.jMiss size=512 162.3 168.1 +3.6%
AffineFoldBench.eoGetOption_0_empty - 0.9 0.9 -3.6%
OrderCirceBench.eoNamesIor size=8 3,474.2 3,595.7 +3.5%
IsoBench.mReverseGet - 4.6 4.5 -3.4%
PowerSeriesNestedBench.eoModify_nested size=64 4,268.5 4,122.5 -3.4%
JsoniterBench.jMiss size=8 168.2 162.6 -3.3%
SchemesBench.handAna - 31,256.0 30,222.5 -3.3%
PowerSeriesNestedBench.monocle_nested size=1024 219,267.2 226,503.8 +3.3%
PlatedBench.visitorUniverseJson n=64 1,850.9 1,789.9 -3.3%
AvroEncodeRouteBench.naive_freshPlumbing - 766.0 740.9 -3.3%
AvroEncodeRouteBench.eo_encodeToAny - 53.3 51.7 -3.1%
JsoniterBench.jModifyId size=512 5,995.5 5,817.4 -3.0%
KyoDiBench.handMapDrillModify - 35.6 34.5 -2.9%
OrderAvroBench.monocleModifyStreet size=8 789.1 766.0 -2.9%
MultiFocusCollectBench.eoModify_multiFocusTuple6 - 36.1 35.0 -2.9%
OrderCirceBench.hcursorStreet size=512 947.6 920.7 -2.8%
OpticBuildBench.buildAndUse - 929.0 902.8 -2.8%
OrderCirceBench.directNames size=64 24,667.0 25,356.5 +2.8%
MultiFocusCollectBench.naive_constSum - 2.3 2.4 +2.8%
AvroJsonBridgeBench.naiveClickToJson - 2,709.7 2,634.7 -2.8%
OrderJsoniterBench.eoModifyStreet size=512 6,113.7 5,951.3 -2.7%
JsoniterBench.jModifyId size=8 154.2 150.2 -2.6%
OrderJsoniterBench.monocleModifyStreet size=64 16,949.7 16,507.6 -2.6%
OpticBuildBench.reuseUse - 855.8 877.7 +2.6%
AvroVulcanBench.encode_vulcanRaw - 198.6 193.5 -2.5%
OrderJsoniterBench.eoReadStreet size=512 176.5 172.1 -2.5%
PowerSeriesPrismBench.monocle_sparse size=512 31,666.8 30,878.0 -2.5%
OrderJsoniterBench.eoSumPrices size=8 1,351.4 1,384.9 +2.5%
PowerSeriesBench.eoModify_powerEach size=64 747.8 729.4 -2.5%
JsoniterBench.jModifyId size=64 768.4 749.7 -2.4%
PlatedBench.mUniverseJson n=4096 5,212,064.3 5,086,232.7 -2.4%
TraversalBench.mModify size=512 31,646.8 32,406.9 +2.4%
OrderCirceBench.eoStreetIor size=64 842.5 862.6 +2.4%
PlatedBench.eoTransformDeep n=4096 124,485.6 121,509.0 -2.4%
OrderCirceBench.hcursorNames size=64 24,732.8 24,142.8 -2.4%
PowerSeriesBench.eoModify_powerEach size=4 100.4 98.0 -2.4%
PowerSeriesNestedBench.monocle_nested size=16 2,771.1 2,706.4 -2.3%
AvroVulcanBench.encode_bridged - 199.4 194.8 -2.3%
PowerSeriesBench.monocle_powerEach size=4096 190,270.3 185,838.4 -2.3%
OptionalBench.mModify_6 - 91.6 93.8 +2.3%
OrderJsoniterBench.eoModifyStreet size=8 272.2 266.0 -2.3%
MultiFocusCollectBench.eoCollectMap_zipMean - 133.4 130.4 -2.3%
PlatedBench.mUniverseJson n=512 383,001.5 374,354.8 -2.3%
JsoniterBench.jReadStreet size=8 174.3 170.4 -2.3%
OrderCirceBench.hcursorNames size=8 3,428.5 3,505.7 +2.3%
TraversalBench.eoFoldNested size=64 589.7 576.6 -2.2%
AvroVulcanBench.rootGet_native - 133.8 136.7 +2.2%
SchemesBench.handCata - 14,431.3 14,742.6 +2.2%
PowerSeriesNestedBench.eoModify_nested size=1024 57,575.7 56,341.3 -2.1%
OrderCirceBench.hcursorStreet size=8 926.9 907.2 -2.1%
OrderCirceBench.directNames size=512 185,031.0 181,230.9 -2.1%
OrderCirceBench.eoStreetIor size=512 854.6 872.0 +2.0%
GetterBench.mGet_orderId - 0.4 0.4 -2.0%
GenericsBench.genLensModify - 4.0 4.0 -2.0%
AvroBytesBench.naiveModifyPartner - 2,842.1 2,784.7 -2.0%
OrderCirceBench.eoNames size=8 3,368.4 3,436.2 +2.0%
JsoniterBench.cReplaceId size=64 42,114.9 41,273.7 -2.0%
OrderCirceBench.naiveStreet size=8 2,984.2 2,924.8 -2.0%
PowerSeriesNestedBench.eoModify_nested size=16 1,216.4 1,240.6 +2.0%
PowerSeriesPrismBench.monocle_sparse size=128 4,496.4 4,407.1 -2.0%
JsoniterBench.jReplaceId size=512 5,912.6 5,798.8 -1.9%
JsoniterBench.jSumPrices size=8 1,289.3 1,313.8 +1.9%
OrderAvroBench.eoModifyStreet size=512 100.9 99.0 -1.9%
AvroDecodeReuseBench.confluentRecordReader - 352.7 346.1 -1.9%
PowerSeriesBench.eoModify_powerEach size=1024 11,957.1 11,736.2 -1.8%
AvroBytesBench.prunedReadCountry - 882.1 865.8 -1.8%
JsoniterBench.cReadStreet size=8 3,351.1 3,412.9 +1.8%
PowerSeriesBench.monocle_powerEach size=64 2,293.1 2,335.1 +1.8%
KyoDiBench.eoMapDrillModify - 37.8 37.1 -1.8%
PrismBench.eoGetOptionPresent - 0.8 0.8 -1.8%
CompositionBench.buildLens6 - 52.2 51.3 -1.8%
TraversalBench.eoFoldPrices size=512 2,150.5 2,112.0 -1.8%
PowerSeriesNestedBench.monocle_nested size=64 9,782.9 9,609.1 -1.8%
OrderAvroBench.monocleModifyStreet size=64 5,031.7 4,943.3 -1.8%
PowerSeriesPrismBench.monocle_sparse size=32 1,159.9 1,180.0 +1.7%
OrderJsoniterBench.naiveModifyStreet size=64 16,736.0 16,447.5 -1.7%
MultiFocusBench.naive_listMap size=1024 10,511.9 10,332.6 -1.7%
OrderJsoniterBench.monocleSumPrices size=8 2,148.7 2,184.8 +1.7%
MultiFocusBench.naive_listMap size=4 45.9 45.2 -1.7%
PrismBench.eoGetRightPresent - 2.6 2.6 -1.6%
MultiFocusBench.eoFold_powerEach size=32 323.6 318.3 -1.6%
TraversalBench.eoModify size=64 898.0 883.5 -1.6%
OrderCirceBench.eoNamesIor size=512 206,096.0 209,425.7 +1.6%
PlatedBench.eoUniverseExpr n=64 2,033.2 2,000.4 -1.6%
MultiFocusBench.eoModify_multiFocus size=32 1,573.2 1,548.1 -1.6%
MultiFocusBench.eoFold_powerEach size=256 2,978.9 2,931.5 -1.6%
FoldBench.eoFoldMap size=512 1,395.4 1,373.4 -1.6%
PowerSeriesNestedBench.naive_nested size=16 375.5 369.6 -1.6%
OrderAvroBench.naiveModifyStreet size=512 38,218.7 37,625.3 -1.6%
OptionalBench.eoModify_0 - 19.7 19.4 -1.5%
PlatedBench.mUniverseExpr n=4096 4,931,665.0 4,857,872.5 -1.5%
OrderJsoniterBench.naiveModifyStreet size=8 2,948.4 2,904.6 -1.5%
AffineFoldBench.eoGetOption_0_asOptional - 2.7 2.6 -1.5%
AvroBytesBench.eoReadPartner - 168.3 165.8 -1.5%
OrderJsoniterBench.monocleSumPrices size=512 340,376.9 335,366.7 -1.5%
GenericsBench.handPrismModifyMiss - 0.9 0.9 -1.5%
JsoniterBench.jReplaceId size=8 147.6 145.5 -1.5%
OrderAvroBench.monocleReadStreet size=512 19,881.7 19,593.3 -1.5%
JsoniterBench.cReadStreet size=64 21,800.6 21,485.9 -1.4%
MultiFocusCollectBench.naive_tuple3Rewrite - 12.8 12.6 -1.4%
FoldBench.mFoldPrices size=512 2,588.0 2,551.0 -1.4%
PowerSeriesPrismBench.eoModify_sparse size=2048 21,535.0 21,227.7 -1.4%
OrderCirceBench.eoNames size=64 25,120.1 24,761.7 -1.4%
AvroJsonBridgeBench.naiveWideToAvro - 1,080.0 1,064.7 -1.4%
JsoniterBench.jReadStreet size=64 172.4 174.8 +1.4%
AvroJsonBridgeBench.eoClickToAvro - 2,612.8 2,576.0 -1.4%
MultiFocusBench.naive_listMap size=32 323.4 318.8 -1.4%
ClickRecordBench.encode_derivedThroughPrism - 440.3 446.5 +1.4%
PlatedBench.eoTransformExpr n=4096 126,991.9 125,208.2 -1.4%
PrismBench.mGetRightPresent - 2.7 2.7 -1.4%
PowerSeriesPrismBench.monocle_sparse size=2048 100,082.0 98,695.1 -1.4%
PowerSeriesNestedBench.naive_nested size=4 133.7 131.8 -1.4%
GenericsBench.rawLensModify - 3.5 3.5 -1.4%
OrderAvroBench.eoReadStreet size=8 28.6 28.2 -1.4%
PowerSeriesPrismBench.eoModify_sparse size=512 5,369.5 5,297.1 -1.3%
AvroBytesBench.naivePassthroughPayload - 4,710.2 4,646.9 -1.3%
PlatedBench.visitorTransformExpr n=4096 66,600.4 65,713.5 -1.3%
GenericsBench.handLensModify - 3.5 3.6 +1.3%
FoldBench.mFoldPrices size=64 219.6 216.7 -1.3%
OrderJsoniterBench.eoModifyStreet size=64 879.5 867.9 -1.3%
SetterBench.mModify_orderId - 5.4 5.3 -1.3%
AvroVulcanBench.fieldGet_bridged - 83.1 82.0 -1.3%
OptionalBench.mReplace_0 - 5.5 5.4 -1.3%
CompositionBench.reuseLens1 - 11.8 11.7 -1.3%
OrderAvroBench.monocleReadStreet size=64 2,520.9 2,488.7 -1.3%
CompositionBench.buildLens1 - 10.0 9.9 -1.3%
PlatedBench.mTransformExpr n=512 13,524.3 13,352.3 -1.3%
GenericsBench.rawPrismGetHit - 2.7 2.7 -1.3%
PrismBench.mReverseGet - 2.5 2.5 -1.3%
GetterBench.eoGet_orderId - 0.8 0.8 +1.3%
OrderCirceBench.monocleStreet size=8 2,958.6 2,921.3 -1.3%
PowerSeriesBench.naive_powerEach size=1024 5,837.9 5,764.7 -1.3%
OrderAvroBench.monocleModifyStreet size=512 38,305.4 37,828.0 -1.2%
LensBench.eoModifyDeep - 28.4 28.1 -1.2%
PowerSeriesPrismBench.naive_sparse size=128 348.3 344.0 -1.2%
IsoBench.mGet - 4.6 4.5 -1.2%
OptionalBench.eoModify_6 - 103.6 104.9 +1.2%
PlatedBench.mUniverseExpr n=512 346,040.2 350,216.4 +1.2%
PowerSeriesNestedBench.naive_nested size=256 5,270.2 5,207.1 -1.2%
ReviewBench.naiveBuild_6 - 16.6 16.4 -1.2%
OrderAvroBench.naiveModifyStreet size=64 4,976.6 4,917.6 -1.2%
AvroBytesBench.prunedReadPartner - 604.0 596.9 -1.2%
OrderAvroBench.eoReadStreet size=512 28.5 28.2 -1.2%
PowerSeriesPrismBench.naive_sparse size=32 89.2 88.1 -1.2%
PlatedBench.visitorTransformDeep n=512 4,702.1 4,648.3 -1.1%
PlatedBench.visitorUniverseExpr n=512 6,473.6 6,399.8 -1.1%
SetterBench.eoModify_3 - 11.8 11.7 -1.1%
FoldBench.eoFoldPrices size=64 219.3 216.8 -1.1%
OrderJsoniterBench.naiveSumPrices size=512 79,948.8 79,050.5 -1.1%
PlatedBench.mTransformExpr n=4096 149,074.0 147,400.8 -1.1%
MultiFocusBench.naive_listMap size=256 2,556.6 2,527.9 -1.1%
ClickRecordBench.encode_hand - 125.3 123.9 -1.1%
ClickRecordBench.encode_derived - 442.9 447.7 +1.1%
OrderJsoniterBench.naiveReadStreet size=8 1,501.7 1,518.0 +1.1%
PowerSeriesPrismBench.eoModify_sparse size=8 105.0 103.9 -1.1%
PlatedBench.eoUniverseDeep n=64 2,076.3 2,054.0 -1.1%
PowerSeriesPrismBench.eoModify_sparse size=128 1,249.4 1,236.0 -1.1%
PlatedBench.eoTransformDeep n=512 13,814.5 13,667.4 -1.1%
OrderJsoniterBench.eoReadStreet size=8 172.9 171.1 -1.1%
JsoniterBench.cReadId size=8 3,412.3 3,376.7 -1.0%
TraversalBench.eoModify size=512 7,803.3 7,884.4 +1.0%
GenericsBench.genPrismModifyHit - 3.4 3.4 -1.0%
GenericsBench.genPrismGetMiss - 1.0 1.0 +1.0%
OrderAvroBench.monocleModifyNames size=512 80,103.0 79,280.9 -1.0%
AvroJsonBridgeBench.eoClickToJson - 2,457.4 2,432.4 -1.0%
LensBench.mModify - 5.6 5.5 -1.0%
OrderJsoniterBench.monocleModifyStreet size=8 2,925.7 2,896.5 -1.0%
PrismBench.mRightReverseGet - 2.5 2.5 -1.0%
OrderJsoniterBench.naiveModifyStreet size=512 137,584.3 136,217.7 -1.0%
OrderAvroBench.eoModifyNames size=512 28,939.7 28,653.3 -1.0%
OrderJsoniterBench.nativeReadStreet size=64 4,322.7 4,365.4 +1.0%
PrismBench.eoGetRightAbsent - 0.9 0.9 -1.0%
OrderCirceBench.monocleNames size=64 22,328.5 22,108.7 -1.0%
CapsBench.modifyDirect - 5.6 5.5 -1.0%
MultiFocusBench.naive_sumQty size=256 659.3 652.8 -1.0%
JsoniterBench.cReplaceId size=512 321,313.3 324,434.1 +1.0%
FoldBench.mFoldMap size=512 1,376.8 1,363.5 -1.0%
MultiFocusBench.naive_sumQty size=32 59.7 59.1 -1.0%
OrderJsoniterBench.monocleSumPrices size=64 13,276.1 13,149.0 -1.0%
OrderCirceBench.directStreet size=64 881.7 873.3 -1.0%
JsoniterBench.jSumPrices size=64 9,880.4 9,786.1 -1.0%
AvroDecodeReuseBench.freshDecodeRecord - 1,246.2 1,234.3 -1.0%
CompositionBench.buildLens3 - 27.2 26.9 -0.9%
ReviewBench.eoReverseGet_6 - 25.7 25.4 -0.9%
OrderAvroBench.monocleReadStreet size=8 376.5 380.1 +0.9%
JsoniterBench.cModifyId size=8 7,054.9 7,120.9 +0.9%
OrderCirceBench.eoStreet size=512 849.1 841.2 -0.9%
OptionalBench.mModify_0 - 19.5 19.3 -0.9%
SchemesBench.drosteAna - 55,107.2 54,597.2 -0.9%
JsoniterBench.cModifyId size=512 326,594.3 323,632.9 -0.9%
OptionalBench.eoModify_loyalty - 18.0 17.8 -0.9%
GenericsBench.rawPrismModifyHit - 3.4 3.3 -0.9%
AvroBytesBench.naiveModifyCountry - 2,452.9 2,474.9 +0.9%
TraversalBench.eoModify size=8 103.9 103.0 -0.9%
PlatedBench.eoUniverseDeep n=4096 146,206.7 144,916.1 -0.9%
TraversalBench.eoFoldPrices size=64 219.1 217.1 -0.9%
PlatedBench.eoUniverseDeep n=512 17,832.8 17,676.0 -0.9%
TraversalBench.mModify size=8 331.4 328.5 -0.9%
MultiFocusBench.eoModify_powerEach size=32 858.5 851.1 -0.9%
JsoniterBench.cSumPrices size=8 5,344.1 5,298.3 -0.9%
PlatedBench.eoUniverseJson n=4096 202,817.9 204,557.7 +0.9%
JsoniterBench.cReplaceId size=8 7,056.4 6,996.0 -0.9%
OrderAvroBench.naiveReadStreet size=8 383.7 380.5 -0.9%
GenericsBench.handPrismGetHit - 2.4 2.5 +0.9%
PlatedBench.eoTransformExpr n=512 15,942.9 15,807.8 -0.8%
PowerSeriesPrismBench.eoModify_sparse size=32 326.4 323.6 -0.8%
MultiFocusBench.eoModify_powerEach size=4 145.8 144.5 -0.8%
OrderAvroBench.naiveModifyNames size=512 48,939.7 48,535.1 -0.8%
JsoniterBench.cModifyId size=64 41,754.7 41,411.8 -0.8%
JsoniterBench.cSumPrices size=512 283,705.4 281,379.8 -0.8%
MultiFocusCollectBench.eoCollectMap_constSum - 1.6 1.6 +0.8%
SetterBench.mModify_6 - 53.5 54.0 +0.8%
OrderAvroBench.naiveModifyStreet size=8 762.1 755.9 -0.8%
PlatedBench.visitorTransformExpr n=512 7,815.9 7,753.5 -0.8%
TraversalBench.mFoldPrices size=64 2,462.1 2,442.5 -0.8%
TraversalBench.eoFoldNested size=8 52.6 52.2 -0.8%
GenericsBench.genPrismGetHit - 2.5 2.4 -0.8%
MultiFocusBench.naive_sumQty size=4 6.3 6.3 -0.8%
OrderAvroBench.eoModifyNames size=64 3,441.5 3,468.2 +0.8%
AvroBytesBench.eoModifyCountry - 267.7 265.7 -0.8%
CapsBench.foldMapDirect - 19.1 19.3 +0.8%
MultiFocusCollectBench.eoCollectList_listSum - 28.6 28.4 -0.8%
AvroEncodeRouteBench.handwritten_stream - 157.4 158.6 +0.8%
PrismBench.eoRightReverseGet - 2.6 2.6 -0.7%
OrderJsoniterBench.nativeReadStreet size=8 791.8 797.7 +0.7%
PowerSeriesNestedBench.eoModify_nested size=4 583.6 579.3 -0.7%
PowerSeriesBench.eoModify_powerEach size=256 2,736.5 2,756.1 +0.7%
PowerSeriesBench.monocle_powerEach size=1024 55,371.6 55,765.4 +0.7%
JsoniterBench.jReadStreet size=512 174.7 173.5 -0.7%
GenericsBench.genPrismModifyMiss - 1.0 1.0 +0.7%
ReviewBench.naiveBuild_0 - 3.5 3.4 -0.7%
MultiFocusCollectBench.naive_zipMeanBroadcast - 223.0 221.5 -0.7%
GenericsBench.handPrismModifyHit - 3.4 3.4 -0.7%
JsoniterBench.jReplaceId size=64 745.4 740.3 -0.7%
GenericsBench.handLensGet - 0.9 0.9 -0.7%
TraversalBench.eoFoldPrices size=8 29.6 29.4 -0.7%
AffineFoldBench.mGetOption_3 - 7.1 7.0 -0.7%
FoldBench.mFoldMap size=64 150.5 149.5 -0.7%
OptionalBench.eoReplace_loyalty - 11.8 11.8 -0.7%
JsoniterBench.jSumPrices size=512 78,292.5 78,812.6 +0.7%
PlatedBench.visitorUniverseDeep n=512 7,329.4 7,281.0 -0.7%
AvroVulcanBench.rootGet_bridged - 307.2 305.2 -0.6%
OrderJsoniterBench.naiveSumPrices size=64 9,866.9 9,929.6 +0.6%
ClickRecordBench.encode_vulcanFull - 5,613.2 5,577.8 -0.6%
PrismBench.mGetOptionAbsent - 0.9 0.9 -0.6%
OrderAvroBench.monocleModifyNames size=64 8,264.4 8,212.8 -0.6%
OrderJsoniterBench.monocleModifyStreet size=512 137,874.5 137,013.6 -0.6%
PlatedBench.visitorTransformExpr n=64 1,020.9 1,014.6 -0.6%
PowerSeriesBench.monocle_powerEach size=256 19,758.7 19,881.0 +0.6%
SchemesBench.drosteCata - 35,530.9 35,311.2 -0.6%
PowerSeriesBench.eoModify_powerEach size=4096 48,391.2 48,096.3 -0.6%
GenericsBench.genLensGet - 0.9 0.9 -0.6%
MultiFocusBench.eoModify_multiFocus size=256 13,183.2 13,103.4 -0.6%
OrderCirceBench.naiveStreet size=512 148,399.0 147,507.4 -0.6%
AvroJsonBridgeBench.naiveClickToAvro - 1,439.3 1,430.7 -0.6%
CompositionBench.reuseLeaf - 3.5 3.5 -0.6%
OrderJsoniterBench.monocleReadStreet size=8 1,494.3 1,485.6 -0.6%
FoldBench.eoFoldMap size=64 150.3 149.5 -0.6%
AvroBytesBench.eoSliceGraftPayload - 236.7 238.0 +0.6%
FoldBench.mFoldPrices size=8 29.7 29.5 -0.6%
MultiFocusBench.eoFold_powerEach size=4 62.3 61.9 -0.6%
PowerSeriesPrismBench.naive_sparse size=512 1,265.9 1,259.0 -0.5%
OrderJsoniterBench.monocleReadStreet size=512 73,385.0 72,987.9 -0.5%
PlatedBench.visitorUniverseDeep n=4096 60,254.1 59,929.1 -0.5%
OrderAvroBench.eoModifyStreet size=8 99.5 99.0 -0.5%
PlatedBench.visitorUniverseExpr n=4096 52,656.3 52,373.9 -0.5%
SchemesBench.handHylo - 11,989.8 11,925.7 -0.5%
AffineFoldBench.eoGetOption_6 - 21.9 21.8 -0.5%
PlatedBench.eoTransformExpr n=64 1,934.6 1,924.7 -0.5%
IsoBench.eoGet - 4.6 4.5 -0.5%
OrderCirceBench.directStreet size=512 850.1 854.4 +0.5%
OrderAvroBench.naiveReadStreet size=64 2,504.2 2,491.8 -0.5%
PowerSeriesNestedBench.eoModify_nested size=256 17,244.7 17,160.5 -0.5%
TraversalBench.eoFoldNested size=512 5,067.9 5,043.3 -0.5%
LensBench.eoReplace - 5.4 5.4 -0.5%
OrderAvroBench.eoReadStreet size=64 28.3 28.2 -0.5%
PrismBench.eoGetOptionAbsent - 0.8 0.8 -0.5%
PlatedBench.eoTransformDeep n=64 1,444.0 1,437.1 -0.5%
GenericsBench.handPrismGetMiss - 0.9 0.9 +0.5%
ZioDiBench.handServiceReplace - 90.8 90.3 -0.5%
CompositionBench.buildLensOptional3 - 26.9 26.8 -0.5%
TraversalBench.mModify size=64 2,260.8 2,250.4 -0.5%
PowerSeriesBench.naive_powerEach size=4 27.2 27.0 -0.5%
TraversalBench.mFoldPrices size=8 375.3 377.0 +0.5%
PlatedBench.visitorUniverseJson n=512 21,901.3 22,000.3 +0.5%
ZioDiBench.handDrillModify - 100.6 101.1 +0.5%
PlatedBench.visitorUniverseDeep n=64 748.6 745.4 -0.4%
AvroBytesBench.eoGraftPayload - 120.9 120.4 -0.4%
ReviewBench.eoReverseGet_3 - 14.8 14.7 -0.4%
PowerSeriesNestedBench.naive_nested size=1024 21,398.6 21,306.4 -0.4%
LensBench.mGet - 1.0 1.0 -0.4%
OptionalBench.eoReplace_0 - 5.7 5.7 -0.4%
PrismBench.eoReverseGet - 2.6 2.6 -0.4%
OrderJsoniterBench.monocleReadStreet size=64 9,269.6 9,230.7 -0.4%
OptionalBench.eoModify_0_empty - 1.3 1.3 -0.4%
PlatedBench.eoUniverseExpr n=4096 143,960.4 144,544.2 +0.4%
LensBench.mModifyDeep - 28.2 28.4 +0.4%
AvroJsonBridgeBench.naiveWideToJson - 1,646.6 1,640.0 -0.4%
KyoDiBench.handMapGet - 1.6 1.6 -0.4%
SetterBench.mModify_0 - 3.4 3.4 +0.4%
PowerSeriesBench.naive_powerEach size=16 91.0 90.6 -0.4%
OptionalBench.eoModify_3 - 44.0 43.8 -0.4%
CapsBench.getDirect - 0.9 0.9 -0.4%
PlatedBench.mTransformExpr n=64 2,295.7 2,286.8 -0.4%
ZioDiBench.handDrillGet - 17.3 17.2 -0.4%
OrderAvroBench.naiveReadStreet size=512 19,664.1 19,588.0 -0.4%
AvroDecodeReuseBench.cachedDecodeRecord - 309.1 307.9 -0.4%
CapsBench.foldMapDerivedHeld - 20.6 20.6 -0.4%
CapsBench.getDeepCap - 1.3 1.3 -0.4%
MultiFocusBench.eoModify_powerEach size=256 7,039.8 7,066.5 +0.4%
AffineFoldBench.mGetOption_0_empty - 0.8 0.8 +0.4%
ZioDiBench.eoDrillModify - 95.5 95.8 +0.4%
OrderAvroBench.monocleModifyNames size=8 1,212.9 1,217.4 +0.4%
AvroVulcanBench.decode_bridged - 156.1 155.5 -0.4%
OrderAvroBench.eoModifyStreet size=64 99.3 99.0 -0.4%
TraversalBench.mFoldPrices size=512 29,152.3 29,258.2 +0.4%
PowerSeriesNestedBench.naive_nested size=64 1,323.1 1,318.3 -0.4%
JsoniterBench.cReadStreet size=512 170,724.0 170,132.4 -0.3%
OrderCirceBench.naiveNames size=512 159,045.7 159,594.1 +0.3%
OrderJsoniterBench.nativeSumPrices size=8 992.7 996.1 +0.3%
OrderAvroBench.naiveModifyNames size=64 6,276.0 6,254.8 -0.3%
OrderJsoniterBench.nativeSumPrices size=64 6,665.1 6,642.9 -0.3%
PowerSeriesBench.naive_powerEach size=256 1,342.9 1,338.5 -0.3%
KyoDiBench.handVarUpdate - 66.8 67.1 +0.3%
MultiFocusCollectBench.naive_tuple6Rewrite - 24.3 24.2 -0.3%
GetterBench.eoGet_3 - 11.8 11.7 -0.3%
CapsBench.modifyDeepDirect - 28.2 28.1 -0.3%
SetterBench.eoModify_6 - 21.5 21.6 +0.3%
OrderCirceBench.monocleStreet size=512 149,004.0 148,529.6 -0.3%
PowerSeriesBench.monocle_powerEach size=16 630.4 632.4 +0.3%
MultiFocusCollectBench.naive_listSum - 26.0 25.9 -0.3%
PlatedBench.eoUniverseJson n=512 24,028.7 23,953.5 -0.3%
CapsBench.getDerivedHeld - 1.9 1.9 -0.3%
JsoniterBench.cReadId size=64 21,499.3 21,565.3 +0.3%
AffineFoldBench.mGetOption_loyalty - 0.9 0.9 -0.3%
CapsBench.foldMapDerivedPerCall - 19.3 19.4 +0.3%
PrismBench.mGetOptionPresent - 0.9 0.9 -0.3%
KyoDiBench.eoMapGet - 2.1 2.1 -0.3%
OrderJsoniterBench.naiveReadStreet size=64 9,218.8 9,191.5 -0.3%
GenericsBench.rawLensGet - 0.7 0.7 +0.3%
OptionalBench.eoModify_loyalty_empty - 1.3 1.3 -0.3%
AvroJsonBridgeBench.eoWideToAvro - 713.0 711.1 -0.3%
GetterBench.eoGet_6 - 22.8 22.7 -0.3%
CapsBench.modifyDerivedHeld - 5.7 5.7 +0.3%
OrderCirceBench.monocleStreet size=64 18,763.9 18,713.0 -0.3%
LensBench.mReplace - 5.3 5.3 -0.3%
FoldBench.eoFoldPrices size=512 2,594.5 2,587.7 -0.3%
AvroVulcanBench.decode_native - 13.0 13.0 -0.3%
SetterBench.eoModify_orderId - 5.3 5.3 -0.3%
CompositionBench.reuseLensOptional3 - 43.9 43.8 -0.3%
OrderCirceBench.naiveNames size=64 20,074.6 20,023.4 -0.3%
ClickRecordBench.encode_positional - 4,691.1 4,679.1 -0.3%
JsoniterBench.cSumPrices size=64 35,115.9 35,028.0 -0.3%
OrderAvroBench.eoModifyNames size=8 492.4 491.2 -0.2%
OrderJsoniterBench.eoSumPrices size=512 79,098.2 78,901.5 -0.2%
PowerSeriesBench.naive_powerEach size=64 342.3 343.2 +0.2%
AvroDecodeReuseBench.confluentRecordReaderFresh - 1,311.4 1,308.3 -0.2%
CapsBench.modifyDerivedPerCall - 5.6 5.6 +0.2%
PrismBench.mGetRightAbsent - 1.0 1.0 -0.2%
PowerSeriesPrismBench.naive_sparse size=8 23.0 22.9 -0.2%
LensBench.eoGet - 0.9 0.9 -0.2%
PowerSeriesPrismBench.naive_sparse size=2048 5,215.0 5,203.4 -0.2%
OpticBuildBench.build - 41.6 41.5 -0.2%
OrderCirceBench.monocleNames size=512 193,032.9 192,615.2 -0.2%
ReviewBench.eoReverseGet_0 - 3.5 3.5 -0.2%
CapsBench.getDerivedPerCall - 1.3 1.3 +0.2%
SetterBench.mModify_3 - 27.4 27.4 -0.2%
PowerSeriesBench.naive_powerEach size=4096 21,729.5 21,773.8 +0.2%
OrderJsoniterBench.nativeReadStreet size=512 33,654.8 33,586.5 -0.2%
OrderCirceBench.eoNamesIor size=64 27,872.5 27,927.0 +0.2%
AffineFoldBench.eoGetOption_loyalty - 0.9 0.9 -0.2%
CapsBench.modifyDeepCap - 28.8 28.9 +0.2%
AvroVulcanBench.encode_native - 10.6 10.6 +0.2%
PlatedBench.eoUniverseJson n=64 2,693.1 2,687.9 -0.2%
ZioDiBench.eoServiceGet - 4.7 4.7 -0.2%
PlatedBench.visitorUniverseExpr n=64 765.3 763.9 -0.2%
JsoniterBench.cReadId size=512 171,438.8 171,746.8 +0.2%
OrderJsoniterBench.eoSumPrices size=64 9,788.0 9,805.3 +0.2%
KyoDiBench.handEnvUse - 89.6 89.4 -0.2%
CompositionBench.reuseLens3 - 32.7 32.8 +0.2%
OrderJsoniterBench.naiveSumPrices size=8 1,567.6 1,565.0 -0.2%
AffineFoldBench.eoGetOption_3 - 10.6 10.6 -0.2%
AvroEncodeRouteBench.eo_encodeValue - 519.5 520.3 +0.2%
OrderCirceBench.naiveNames size=8 3,096.4 3,101.1 +0.2%
CapsBench.modifyCap - 5.5 5.5 -0.1%
ZioDiBench.eoDrillGet - 8.7 8.7 -0.1%
PlatedBench.mUniverseJson n=64 34,801.7 34,850.2 +0.1%
SetterBench.eoModify_0 - 3.4 3.4 -0.1%
KyoDiBench.eoEnvFocus - 91.5 91.3 -0.1%
AffineFoldBench.eoGetOption_loyalty_empty - 0.9 0.9 +0.1%
PowerSeriesNestedBench.monocle_nested size=256 83,320.8 83,432.5 +0.1%
OrderCirceBench.monocleNames size=8 3,452.3 3,456.8 +0.1%
ReviewBench.naiveBuild_3 - 10.0 10.0 +0.1%
OrderCirceBench.naiveStreet size=64 18,754.4 18,730.7 -0.1%
OrderJsoniterBench.nativeSumPrices size=512 55,217.5 55,149.4 -0.1%
OrderCirceBench.directNames size=8 3,307.4 3,303.4 -0.1%
PlatedBench.mUniverseExpr n=64 30,488.8 30,523.6 +0.1%
CapsBench.foldMapCap - 19.2 19.2 -0.1%
FoldBench.mFoldMap size=8 19.0 19.0 +0.1%
ZioDiBench.handServiceGet - 17.3 17.3 +0.1%
CapsBench.getCap - 1.0 1.0 +0.1%
IsoBench.eoReverseGet - 4.4 4.4 -0.1%
AffineFoldBench.mGetOption_loyalty_empty - 0.9 0.9 -0.1%
ZioDiBench.eoServiceReplace - 81.8 81.7 -0.1%
AffineFoldBench.mGetOption_0 - 0.8 0.8 -0.1%
PlatedBench.visitorTransformDeep n=4096 43,970.7 43,996.9 +0.1%
OptionalBench.mModify_3 - 56.3 56.3 +0.1%
OrderJsoniterBench.eoReadStreet size=64 176.6 176.7 +0.1%
OrderJsoniterBench.naiveReadStreet size=512 73,175.2 73,137.7 -0.1%
FoldBench.eoFoldMap size=8 19.1 19.1 -0.0%
AvroVulcanBench.decode_vulcanRaw - 153.7 153.6 -0.0%
LensBench.eoModify - 5.5 5.5 +0.0%
PlatedBench.visitorTransformDeep n=64 520.2 520.0 -0.0%
OptionalBench.mReplace_loyalty - 11.7 11.7 -0.0%
CompositionBench.reuseLens6 - 89.5 89.5 -0.0%
CapsBench.getDeepDirect - 1.2 1.2 -0.0%
OrderCirceBench.eoStreet size=64 856.7 856.5 -0.0%
PowerSeriesBench.monocle_powerEach size=4 172.7 172.7 -0.0%
GetterBench.mGet_0 - 0.4 0.4 -0.0%
PlatedBench.eoUniverseExpr n=512 17,424.7 17,426.3 +0.0%
AvroBytesBench.naiveReadCountry - 1,417.5 1,417.5 +0.0%
KyoDiBench.eoVarUpdateFocus - 74.7 74.7 -0.0%

base_sha: e996b12b897f2448ce09599f4b0d46345554e85b · head_sha: 94a8ee0ecbd4717af683298b1f2d575f0301ffec · jdk: temurin-25 · runner: ubuntu-22.04 · jmh_params: -i 3 -wi 2 -f 1 -t 1 -foe true -prof gc -rf json -jvmArgsAppend -XX:-ResizeTLAB -jvmArgsAppend -Xms1g -jvmArgsAppend -Xmx1g · profile: pr:-i3-wi2-f1-t1-gc-rt1g

Informational only · head 94a8ee0ecbd4717af683298b1f2d575f0301ffec · benchmark run

Translation speed. The Cojen Maker version translated 2.3–3.9× slower
than the original raw-ASM emitter. B is now ASM's own ClassNode, written
directly by Lower with asm-commons' InstructionAdapter (no IR of our own,
no library above ASM); reverseGet is ClassWriter. Strings ASM hashes are
built once, switches use the last arm as default, Rt descriptors are
precomputed. Translation is back to the raw-ASM emitter's cost (within
noise; multisig ~20% slower), translate + load is level with it.

Code size (code lines, no comments/blanks, vs the raw-ASM version):
main 1425 → 991 (−30.5%), tests 534 → 330, validators 192 → 153,
total 2218 → 1536 (−30.7%). JvmProgram, Emit and BuiltinCalls are gone.

More Scalus reuse:
- saturated builtins call scalus.uplc.builtin.Builtins directly on
  unboxed values; selectors, builtins used as values and everything
  else run Scalus' CEK meanings (BuiltinRuntime), with non-constant
  arguments swapped back by reference — no reflective twin;
- chooseIndex runs the selector's own meaning on the branch indices;
- builtin result types instantiate Scalus' TypeSchemes at the argument
  types, so `fstPair (unConstrData d)` is an integer and the tag match
  on it is a JVM switch.

Validation speed (JMH, 3 forks): 8–21× the CEK machine on the
context-decoding validators, 63× on Fibonacci; 2.9–7.1× faster than the
raw-ASM version. Mechanisms: lazy Data lists (DataList / ConstrPair),
direct Builtins calls, self-recursion as direct invokestatic, pure
builtin lets computed where read, exact-arity applyAll, typed literals.

Tests: ValidatorSpec is a loop over Scenarios.all (accepting and
rejecting rows shared with the walkthrough and the benchmarks);
CompilerSpec cases are one-liners; a vacuous `Rt.thunk` assertion now
checks `Rt.closure`. dropList on a non-list now fails, as on the CEK
machine. README, docs page (B as bytecode, new benchmark tables) and
CLAUDE.md updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
- Rt.fail throws a MachineError without a stack trace. Filling it cost
  ~1.3 µs — more than a whole validation — so rejecting transactions
  took 1.8–2.7 µs against 0.4–1.4 µs for accepting ones; now 0.5–1.6 µs.
- Exec.run's one catch is a Try turned into Scalus' Result; a compiler
  bug (AssertionError) still escapes, and discharge runs outside it.
- Measured alternative, not taken: a result value from every call needs
  a check after each one — validation unchanged, translation 20–35%
  slower. Rt's scaladoc and the docs page say so.
- Expr renders constants with Scalus' own PrettyPrinter.prettyValue;
  builtin names use scalus.utils.Utils.lowerFirst.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
The single Iso[Array[Byte], Array[Byte], TypedProgram, ClassNode] was
two unrelated functions packaged as an optic: its S was flat bytes, its
T class-file bytes, and nothing walked back. `cborScript andThen iso`
made that visible: cborScript's reverseGet was the identity on class
files, so the composed "iso" never returned to CBOR.

Now every stage keeps the script it came from — TypedProgram its
source, the class the script itself, in its constants — and each arrow
is a lawful monomorphic iso:

  CborScript ≅ TypedProgram ≅ ClassNode ≅ JvmClassScript
             typed          lowering     writing

UplcJvm.typed, bytecode (= typed andThen lowering) and classFile
(= bytecode andThen writing) all start at the script; classFile.get is
the compiler and classFile.reverseGet returns the script exactly.

- CborScript and JvmClassScript are opaque types over Scalus'
  ByteString (value equality, so the laws compare with ==).
  CborScript.of(program) reuses Scalus' cborEncoded / fromCbor;
  CborScript.parse replaces UplcJvm.compile as the checked entry.
- OpticSpec runs cats-eo-laws' IsoTests on typed and classFile;
  Oracle.compare checks the round trips on every program the suites
  run, all 943 conformance programs included.
- writing (ClassWriter / ClassReader) is a byte-exact fixpoint because
  generated code no longer has unreachable instructions: a function
  that can only fail is never applied, and a call whose argument can
  only fail after nothing but values is that failure. (Dead code left
  constant-pool entries behind and reordered the pool on a rewrite.)
- TypedProgram is equal by script and body; its constructor is private.
- Thunk folds into Lam (arity 0); chooseList and trace run their CEK
  meanings; one duplicated CompilerSpec case removed.

Code lines vs the raw-ASM version: main 1425 → 997 (−30.0%), total
2218 → 1549 (−30.2%). Translation unchanged within noise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
@kryptt kryptt changed the title Add UPLC → JVM bytecode demo built on one eo Iso Add UPLC → JVM bytecode demo built from eo isos Oct 14, 2026
A doc comment ran one character past maxColumn; the local check had
passed from scalafmt's incremental cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
The middle of the chain is now `JvmClass`, an opaque type over ASM's
ClassNode, so the optics read in the demo's own vocabulary:

  CborScript ≅ TypedProgram ≅ JvmClass ≅ JvmClassScript

Only `Lower.lower` and `writing.reverseGet` make one, so every JvmClass
embeds its script; `.tree` exposes ASM's tree for inspection. Docs,
README, CLAUDE.md and the build comment follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
…Bytecode

Per review:
- typed     -> toTyped     (CborScript ≅ TypedProgram)
- writing   -> compiling   (JvmClass ≅ JvmClassScript)
- bytecode  -> toJvmClass  (CborScript ≅ JvmClass)
- classFile -> toBytecode  (CborScript ≅ JvmClassScript)

`compiling`'s two halves are now public as `UplcJvm.compile` and
`UplcJvm.decompile`; the Oracle's class-file fixpoint check uses them
directly. Docs, README, the walkthrough's labels and CLAUDE.md follow,
and the last stage-letter labels ((A), (B), (T)) are gone from the
comments and README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
Per review:
- No unsafeFromArray (ByteString or IArray) or unsafeWrapArray left in
  the demo's main code. Scalus' unsafeFromArray skips a defensive copy;
  the scripts now pay that copy.
- CborScript.of returns Either: Scalus' flat encoder throws on a program
  with a free variable, and the conformance suite used to wrap the call
  in a Try. Tests and benches unwrap it through one helper each.
- Lower.direct no longer calls Option.get: an Option for-comprehension
  with cats' traverse replaces it.
- chunks/fromChunks are now CborScript.asConstants/fromConstants, with
  the reason in the doc: a class carries its script, a class file has no
  byte-array constants, and one string constant holds at most 65535
  bytes.
- SourceProgram.decode is a right fold over a shared `subterms` instead
  of writes into arrays. Measured, the fold is 2-3x slower to decode and
  translation 2-9% slower; validation never decodes. children(n) is one
  unfold over subtree sizes. FreeVars walks `subterms` too but keeps its
  mutable set: immutable sets were 2.5x slower.
- Docs: the compiler does no optimisation (no constant folding,
  inlining, dead-code elimination, CSE, specialisation or tail-call
  elimination); translation table re-measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
- demoUplcJvm now compiles with `-opt -opt-inline:**,!scala.**`. It is
  unpublished, so it may inline from Scalus, ASM, cats and eo. Inlining
  from the Scala library is left out: measured with the demo's JMH
  benches, it made the short validations 12-27% slower (PrintInlining
  shows the inlined library code makes Rt.force too big for the JIT to
  inline). Everything else measures neutral to ~5% faster. The
  generated classes are byte-identical either way.
- Published modules (scala3LibrarySettings) add
  `-opt-inline:dev.constructive.eo.**`: the inliner may copy code from
  eo's own packages only, never from cats, the JDK or the Scala library.
  This replaces core's `<sources>` scope and extends inlining to every
  library module. Full test suite green on JDK 25.
- Docs: the demo's "no optimisation" note is about UPLC programs; the
  benchmark tables are re-measured with the new build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
…ealed

- compiling and the composed toBytecode are prisms: a class can exceed
  the JVM's 64 KB method or 65 535-constant class limits, and then there
  is no class file. UplcJvm.compile returns the limit as a Left (the one
  place ASM's MethodTooLargeException / ClassTooLargeException become a
  value); toBytecode.getOption is the compiler.
- CborScript, JvmClassScript and JvmClass hand out copies only (bytes,
  tree), so a value cannot change after the compiler made or checked it
  and reverseGet always walks back.
- Compiling cannot overflow the JVM stack: decoding, typing and lowering
  are walks of Steps (Step.scala), plain calls while shallow and
  cats.Eval on the heap from 128 calls deep; every recursive call goes
  through Walk.nested. Trampolining every node instead doubled
  translation time; this costs 13-19% of it. A closure's captures are a
  fold over its subtree's ids, so FreeVars is gone. Programs nested
  100 000 deep compile on a 1 MB stack.
- OpticSpec: PrismTests for toBytecode (a too-large program among the
  scripts), the miss, the copies, and the 100 000-deep programs.
- Docs: README, site page and CLAUDE.md describe two isos and a prism,
  sealing, stack safety and Scalus' still-recursive flat codec; the
  translation table is re-measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
@kryptt kryptt changed the title Add UPLC → JVM bytecode demo built from eo isos Add UPLC → JVM bytecode demo built from eo optics Oct 15, 2026
…ns miss

Scalus decodes any declared Plutus Core version, and the compiler used to
type every script as if it were 1.1.0: a script declaring 2.0.0 or 7.3.9
parsed, compiled and ran. The ledger only takes the versions Plutus V3 has
at protocol version 11, 1.0.0 and 1.1.0 (Semantics.versions).

- toTyped is a prism: getOption misses on a script of any other version;
  reverseGet stays the script the program was read from. toJvmClass and
  toBytecode compose to prisms; lowering stays an iso, typing the script a
  class embeds without the check (only a typed program is lowered).
- SourceProgram keeps the decoded program's version.
- OpticSpec runs PrismTests on toTyped, with a 2.0.0 script among the
  inputs, and checks the miss. Tests reach the stages through Oracle.typed,
  jvmClass and classFile.
- Docs: the chain is CborScript ⇀ TypedProgram ≅ JvmClass ⇀ JvmClassScript.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
CborScript ⇀ TypedProgram ≅ JvmClass ⇀ JvmClassScript: toTyped and
compiling are prisms since the last two commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5LJsPA524HKbSMvjStrv
@kryptt
kryptt merged commit b9cf763 into main Oct 15, 2026
13 checks passed
@kryptt kryptt mentioned this pull request Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants