Implementing Storage Rent in RSK — Part 2
By: Shreemoy Mishra
Tags: Blockchain, Rsk, Ethereum Virtual Machine, Smart Contracts

Node Performance with Increasing Fraction (25, 50, 75%) of Token Transfers

In a previous post, we discussed a proposal to implement storage rent which is a data access fee charged to transaction senders. In this post we present some (engineering) performance implications of storage rent. This post assumes that readers are familiar with blockchain metrics such as VM and Block Execution times, or Trie get value operations times.

Objective: The research implementation of Storage Rent in RSKJ has not been optimized. While we expect it to run somewhat slower than an unmodified RSKJ node, it is important to quantify the performance impact. This can help improve the implementation and also guide future design decisions.

Summary: We expect 2 main areas of impact:

an increase in Trie Get Value operations to query rent timestamps and an increase in VM execution time for rent tracking and payments

We expect the impact to vary across transactions of different complexity.

The following chart shows the quantitative impact for 3 different classes of transactions:

ERC20 contract deployment transactions (4 transactions in the 1st block after genesis).

transactions (4 transactions in the 1st block after genesis). transactions for initial token allocation to some randomly selected users (about 40 blocks containing 125 transactions each).

to some randomly selected users (about 40 blocks containing 125 transactions each). and finally, transfer transactions (180 transactions in the final 100 blocks. 1/2 in native coin and 1/2 token transfers).

Execution time and memory usage for different classes of transactions

Naturally, the impact of the additional VM computations or Trie getValue operations depends on the type of transactions. Those that already involve more computations are less affected by the introduction of storage rent.

The increases in VM execution and Trie GetValue times lead to predictable increases in Block Execution and Connection times. The quantitative impact (% increase ) is summarized in the following table.

Note: values in table represent percentage increase in storage rent implementation compared to baseline RSKJ

Once we have accounted for VM execution and Trie gets, all remaining variation in Block Execution or Block Connection times have no further statistical links with storage rent. We confirmed this with Linear Regression Analysis.

Details

Comparison framework:

As before we use an in-house benchmarking tool developed by Raul Laprida from the research team at IOV Labs.

We generate data from 6 simulated blockchain runs : one set each for Baseline and Storage Rent.

: one set each for Baseline and Storage Rent. Each simulation generates 100 blocks with 180 transactions in each block.

Half of the transactions involve pure coin transfers while the remaining are transfers of ERC20 tokens.

of the transactions involve pure coin transfers while the remaining are transfers of ERC20 tokens. The gasLimits are set higher (exactly double) in the storage rent case. This “doubling” keeps the number and mix of transactions identical across the two settings. This is required because the experimental storage rent implementation splits a transaction’s gaslimit into two equal budgets, one for normal execution gas and another to pay for rent.

are (exactly double) in the storage rent case. This “doubling” keeps the number and mix of transactions identical across the two settings. This is required because the experimental storage rent implementation splits a transaction’s gaslimit into two equal budgets, one for normal execution gas and another to pay for rent. In order to generate transfer transactions, the simulation tool first deploys 5 ERC20 token contracts and then randomly pre-allocates initial token balances to some accounts (from a set of 1000 accounts).

5 ERC20 token contracts and then initial token balances to some accounts (from a set of 1000 accounts). We also track the performance impact of blocks containing these setup (deployment, token-allocation) transactions. Deployment only needs a couple of blocks. The initial allocations take about 120 blocks.

Execution Time

We expect to see higher VM execution time due to additional computation for tracking and collecting rent.

Execution time comparison (Transfer transactions only)

As expected VM execution takes longer. As a consequence, we see this effect spill over to block execution and connection times. But as we saw earlier, the impact is markedly lower for other types of transactions (e.g. contract deployment) or pre allocations. Generally the impact of introducing rent may be smaller for transactions that require more computations anyway.

Trie Task Times

Storage rent does not require querying nodes that would not normally (without rent) be touched by a transaction. Thus, we do not expect any difference in the number of trie nodes generated using calls to fromMessage .

We do expect to see more trie getValue operations with storage rent. These additional operations are to obtain the last rent paid timestamps for value containing nodes. Naturally, these additional operations will consume more time.

Trir task time comparison (Transfer transactions only)

Takeaway: While there are a lot more trie getValue operations with rent, the time taken by those operations does not increase linearly.

Takeaway: Another key takeaway is that introducing storage rent does not increase the number of trie nodes loaded into memory, this can be observed from the plots of TriefromMsg events.

Database and Memory

We do not expect significant difference in database IO, but we do expect somewhat higher RAM use with storage rent for the additional tracking of rent timestamps and outstanding amounts.

IO and memory comparison (Transfer transactions only)

Performance comparison on a per transaction basis

Increasing the complexity of transactions obviously leads to lower performance. We saw some of this impact above when comparing node performance for different categories of transactions. However, quantify-ing “additional complexity” is not straightforward.

A much simpler way to explore the impact of additional smart contract complexity is to somehow control for the complexity by keeping the level of complexity fixed. We can do this by looking at blocks that only contain coin or token transfers (as above). But now, we vary the fraction of token transfers and pure coin transfers. This is what the image at the top of the post does.

The figure is repeated below for convenience. It compares the rent and baseline node implementations while increasing the fraction of token transfers from 25, to 50 and then to 75% of all transactions in a block. Changing the mix of transaction means the number of transactions that can fit in a block is no longer the same. For example, coin transfers cost 21000 gas, while token transfers cost 53000. We can fit a lot more coin transfers in a block. Therefore, — in this case — the performance metrics are presented on a per-transaction basis.

As expected, the impact of introducing storage rent on node performance (on a per transaction basis) responds to the fraction of token transfers.

Aggregated comparison across classes

Note: In some cases, the storage rent version appears to outperform the baseline implementation. In none of these cases is this difference statistically significant. This is merely incidental as each simulation run uses a different set of pseudo random numbers.

Most of the comparison charts above are for coin or token transfer transactions only. The charts below show aggregated results for different transaction classes.

ERC20 contract deployment

ERC20 initial balance allocations

Transfer transactions

Some of these plots have already appeared above in groups