Paradigm

Releasing Revmc

Jun 20, 2024 | DaniPopes, Georgios Konstantopoulos

Contents

We recently published Reth’s high performance roadmap, calling for broader usage of “gas per second” as a performance metric in EVM blockchains, and detailing our plan to scale blockchains to 1 gigagas per second and beyond, a 1000x improvement from the status quo of Ethereum.

Today, we’re excited to open source revmc, a compiler for lowering EVM Bytecode into native code, demonstrating anywhere from 1.85x to 19x improvements in various realistic EVM benchmarks. We also integrated revmc in Reth and successfully synced the chain. Next up, we’re going to integrate revmc in OP Reth for L2 usage, where its improvements will shine in computationally heavy workloads.

Revmc is extensively tested, and will be further polished for production usage. The code is open source under the Apache/MIT license at github.com/paradigmxyz/revmc.

Why build an EVM to native code compiler?

The development of revmc is motivated by the desire to enhance the performance of the EVM, due to the inherent limitations of bytecode interpretation. Traditional EVM execution involves sequentially processing instructions through an interpreter, introducing significant overhead and latency because the instructions do not execute as native assembly code. By compiling EVM bytecode into optimized native machine code, the compiler enables direct execution on hardware, drastically reducing the overhead associated with virtual machine layers.

Furthermore, compiling bytecode ahead of time (AOT) rather than just-in-time (JIT) during execution mitigates security risks associated with JIT compilation, such as vulnerabilities to malicious code designed to exploit the JIT process. The AOT approach allows for the highest demand contracts to be pre-compiled and stored securely, ensuring that the blockchain operates efficiently without compromising on security.

These ideas have existed for a long time outside of crypto, e.g. in the case of Java or WASM’s JIT compiler, and inside of crypto for the EVM but also other runtimes as well. We expect every blockchain’s runtime will have a compiled native assembly version of its runtime to provide higher performance.

How does it work?

Revmc functions by compiling EVM bytecode, the set of instructions executed within the Ethereum Virtual Machine, into native machine code that the host system's processor can directly execute.

This process is done in two key steps:

  1. Analysis and Optimization: The compiler first analyzes the bytecode to understand the control flow and data dependencies. This is implemented in our own intermediate representation (IR), which we then run custom optimizations over.
  2. Code Generation via LLVM: We proceed to call out to LLVM via the inkwell crate where we pass the optimized IR, and then most of our work is done. LLVM will generate the corresponding native machine code tailored to the specific architecture of the host system. This step is crucial as it determines the efficiency of the resulting executable code.

The compiler is able to work either blocking or in the background. When run in a hot-path, the compiler should be run in the background to ensure that it doesn’t hurt performance of the system while it’s running, and once compilation is done it can hot-swap the interpreted execution for native execution. For benchmarking, it’s better to compile all contracts in blocking mode first and then test against your workload.

Once compiled, the native code can be stored on disk. This ensures that when the node is restarted it doesn’t spend redundant time recompiling contracts, and also allows the node operator to only run compiled contracts that they trust which have been compiled ahead of time, versus allowing any contract to be compiled at runtime.

Revmc is integrated into Reth via the Reth SDK’s NodeBuilder API, allowing node operators to opt-into running native code via the --experimental.compiler flag. We provide examples on how to compile bytecode into native, as well as how to integrate it inside revm’s EVM Builder. We synced the node with revmc enabled and successfully validated the state root at the tip as of June 20th 2024.

How fast is it?

We defined criterion benchmarks against a some simple workloads, and present our results below:

Fibonacci exhibits a 19x improvement, which is representative of computationally heavy workloads. LLVM is particularly impressive here as it auto-vectorizes instructions where it can, and leverages its own native U256 type which is faster than ruint. LLVM is unfortunately not great at optimizing divisions, so code that’s heavy in such or similar operations may not see as great benefit.

WETH and Counter are common cases of workloads we encounter in blockchains, first you read data from the host (e.g. the database), then you do some simple math, finally you write the data back into the host. Given host operations cannot be accelerated with a bytecode compiler, a 1.85x-2.77x improvement is great!

We integrated and benchmarked revmc on Ethereum L1 via Reth’s execution stage (using reth stage run execution), which is the dominant component of our historical sync. Because most of the historical sync’s workload on L1 is not compute-heavy, we saw less impressive results, O(1-10%) depending on the block range.

What is the future of Revmc?

We think revmc will truly shine on high performance L2s with computationally-heavy workloads such as Base or OP Mainnet. To prove it out, we will roll out revmc in our upcoming Reth AlphaNet release.

Roadmap-wise, we’d like to do a few things:

  • Extensively test, fuzz, benchmark it for production usage.
  • JIT compile code while the node is running in the background, without impacting sync time, allowing JIT bombs, or allowing remote code execution.
  • Implement EOF support.
  • Use more LLVM features and optimizations to make it faster.
  • Explore integrating it with other Ethereum clients over FFI.

Until then, check our implementation on Github. If you’re interested in working with us, reach out to georgios@paradigm.xyz

Disclaimer: This post is for general information purposes only. It does not constitute investment advice or a recommendation or solicitation to buy or sell any investment and should not be used in the evaluation of the merits of making any investment decision. It should not be relied upon for accounting, legal or tax advice or investment recommendations. This post reflects the current opinions of the authors and is not made on behalf of Paradigm or its affiliates and does not necessarily reflect the opinions of Paradigm, its affiliates or individuals associated with Paradigm. The opinions reflected herein are subject to change without being updated.