Skip to content

EVM Optimization via Multi-threaded Parallelization

The Ethereum Virtual Machine (EVM) is widely recognized as both the "execution engine" and the "smart contract execution environment" of Ethereum, making it one of the blockchain's most critical components. A public blockchain consists of an open network with thousands of nodes, each potentially differing in hardware specifications. To ensure that smart contracts produce identical results across all nodes, achieving "consistency," it is essential to establish a uniform environment across various devices. Virtual machines make this possible.

The EVM enables smart contracts to run uniformly across different operating systems, such as Windows, Linux, and macOS. This cross-platform compatibility ensures that every node, regardless of its system, achieves the same results when executing a contract. A prime example of such technology is the Java Virtual Machine (JVM).

jvm

The smart contracts we typically see on block explorers are first compiled into EVM bytecode before being stored on the blockchain. When the EVM executes a contract, it reads the bytecode sequentially. Each instruction in the bytecode (opcode) has an associated gas cost. The EVM tracks the gas consumption of each instruction during execution, with the consumption depending on the complexity of the operation.

Furthermore, as the core execution engine of Ethereum, the EVM processes transactions in a serial manner. All transactions are queued in a single line and executed in a specific order. Parallel processing is not used because the blockchain must strictly maintain consistency. A batch of transactions must be processed in the same order across all nodes. If transactions were processed in parallel, it would be difficult to accurately predict the transaction order unless a corresponding scheduling algorithm is introduced, which would add complexity.

serialparallel

In 2014-15, due to time constraints, the Ethereum founding team chose a serial execution method because it was simple to design and easy to maintain. However, as blockchain technology has evolved and the user base has grown, the demand for higher TPS (transactions per second) and throughput has increased. With the emergence and maturity of Rollup technology, the performance bottleneck caused by EVM's serial execution has become increasingly apparent on Ethereum Layer 2.

As a key component of Layer 2, the Sequencer handles all computation tasks as a single server. If the efficiency of external modules working with the Sequencer is sufficiently high, the final bottleneck will depend on the efficiency of the Sequencer itself. At this point, serial execution becomes a significant obstacle.

The opBNB team once achieved extreme optimization of the DA layer and data read-write modules, allowing the Sequencer to process up to around 2000 ERC-20 transfers per second. While this number may seem high, if the transactions being processed are much more complex than ERC-20 transfers, the TPS value will inevitably decrease. Therefore, parallelization of transaction processing will be an inevitable trend in the future.

Next, we will delve into more specific details to explain the limitations of the traditional EVM and the advantages of a parallel EVM.

Two core components of Ethereum transaction execution

At the code module level, besides the EVM, another core component related to transaction execution in go-ethereum is stateDB, which is used to manage account states and data storage in Ethereum. Ethereum uses a tree structure called Merkle Patricia Trie as the database index (or directory). Each time a transaction is executed by the EVM, certain data stored in stateDB is modified, and these changes are eventually reflected in the Merkle Patricia Trie (hereafter referred to as the global state tree).

chainofstate

Specifically, stateDB is responsible for maintaining the state of all Ethereum accounts, including both EOA (Externally Owned Account) accounts and contract accounts. The data it stores includes account balances, smart contract code, and more. During transaction execution, stateDB performs read and write operations on the relevant account data. After the transaction execution is complete, stateDB needs to submit the new state to the underlying database (such as LevelDB) for persistence.

In summary, the EVM interprets and executes smart contract instructions, altering the blockchain‘s state based on the computation results, while stateDB acts as the global state storage, managing all account and contract state changes. Together, they build Ethereum’s transaction execution environment.

The Process of Serial Execution

There are two types of transactions in Ethereum: EOA transfers and contract transactions. EOA transfers are the simplest transaction type, which is ETH transfers between ordinary accounts. These transactions do not involve contract calls and are processed very quickly. Due to the simplicity of the operation, the gas fee charged for EOA transfers is very low.

Unlike simple EOA transfers, contract transactions involve calling and executing smart contracts. When processing contract transactions, the EVM interprets and executes each bytecode instruction in the smart contract. The more complex the contract logic means the more instructions involved, which ultimately means the more resources consumed.

For example, processing an ERC-20 transfer takes about twice as long as an EOA transfer. For more complex smart contracts, such as transactions on Uniswap, it takes even longer, potentially being several times slower than an EOA transfer. This is because DeFi protocols require handling complex logic such as liquidity pools, price calculations, and token swaps during transactions, requiring very complex calculations.

So, in the serial execution model, how do the EVM and stateDB work together to process transactions?

In Ethereum’s design, transactions within a block are processed sequentially, one by one. Each transaction (tx) has an independent instance used to perform the specific operations of that transaction. Although each transaction uses a different EVM instance, all transactions share the same state database, which is stateDB.

During transaction execution, the EVM continuously interacts with stateDB, reading relevant data from stateDB and writing the modified data back to stateDB.