The Bright Future of WebAssembly Smart Contracts — Part 2
In Part 1 we compared the performance of different smart contract technologies. For simplicity we restricted ourselves to the idealized case of smart contracts that are computation heavy and do not access any storage. In this article we will look at more practical examples and will analyze whether WebAssembly smart contracts can keep their performance advantage.
Computational Instructions and Storage Instructions
Every smart contract consists of a series of instructions. These instructions can be roughly divided into two classes: 1) logical or computational instructions and 2) storage instructions. The instructions in the first class are responsible for the logical flow of the smart contract algorithm and for any kind of computation. The purpose of the instructions in the second class is to access the blockchain state, i.e., to read from the state or to alter the state.
The majority of the instructions of a smart contract fall into the first class. However, even if storage instructions are used more infrequently, they are of utmost importance. A smart contract that neither reads from nor writes to the blockchain state would be very impractical. For this reason the smart contract examples we considered in the previous blog post had the limitation of being devoid of any storage instructions.
Accessing the blockchain state is quite time consuming because the state is kept in a database. For that reason the execution of storage instructions requires more time than the execution of logical or computational instructions. When the blockchain runtime executes a smart contract, it will therefore spend a disproportionately large amount of time for executing storage instructions. This is illustrated in the following diagram where the sizes of the boxes should represent the proportional usage.
Different smart contract systems exhibit different levels of performance for the execution of the first class of instructions. The previous blog post showed that WebAssembly smart contracts can be more performant than EVM smart contracts. However, storage instructions will take roughly the same amount of time for each smart contract technology as their execution speed is limited by the underlying database of the blockchain.
This has an interesting implication: if the original smart contract is less heavy on computation, then the performance difference between WebAssembly and EVM will be less pronounced. This becomes apparent in the following diagram. Here we suppose that WebAssembly can execute computational instructions twice as fast as EVM. The upper row represents a smart contract that is computationally expensive. The lower row represents a smart contract that has a high proportion of storage instructions. Note that the execution of the storage instructions takes the same amount of time for both Wasm and EVM smart contracts. Observe that the difference in execution time is smaller for the latter smart contract.
For the comparison of the performance of Wasm and EVM in the previous blog post we considered only the extreme case where the smart contract comprised computation instructions only. This extreme case reflects the maximally possible performance difference.
Smart Contracts Comparison Taking into Account Storage Instructions
We will now have a look at smart contracts that use computational as well as storage instructions. Our results are shown in the chart below. Each line represents a combination of source language and smart contract engine:
- Ink: smart contract written in Ink! and compiled to Wasm
- Wat: smart contract written in Wasm text format and compiled to Wasm
- Solang: smart contract written in Solidity and compiled to Wasm via Solang
- EVM Pallet: smart contract written in Solidity, compiled to EVM and executed via Substrate’s pallet-evm
- Go Ethereum: smart contract written in Solidity, compiled to EVM and executed in the Go Ethereum client
The horizontal axis stands for the percentage of storage instructions in relation to all executed instructions. The vertical axis measures the execution time. Note that both axes are logarithmic. The diagram shows that the difference in execution time diminishes for smart contracts with higher utilization of storage instructions. Two observations are noteworthy: firstly, the fact that the Go Ethereum line crosses the lines for the Wasm based technologies is due to the fact that Go Ethereum uses a storage implementation that differs from the one in Substrate’s pallet-contract and is more efficient. This gives Go Ethereum a performance edge in case the smart contract interacts a lot with the storage. Secondly, the difference between the performance of the EVM Pallet line and pallet-contracts even increases further for storage heavy smart contracts (the logarithmic scale makes this hard to see).
Where would a typical smart contract be located in this diagram? To answer this question we analyzed a huge number of smart contract executions from the smart contract library Open Brush by Supercolony. We consider these prototypical practical smart contracts. The ratio of storage to computational instructions vary wildly for each smart contract execution. The next diagram shows the frequencies we determined. Most executions fall into the range between 0.05 and 0.1, i.e., most smart contracts execute 5% to 10% storage instructions.
We conclude that Wasm is still the most performant smart contract technology even for practical smart contracts that access the blockchain storage.