Optimization of RAM Usage for DAPPs

How could RAM usage be optimized for DApps?

Greetings, this is Dongjun Kwon of ITAM Network.

Ram optimization is of main concern for anyone creating an EOS-based DApp. We at ITAM Network are also working diligently to find a solution to this matter. This post will be on how to optimize RAM usage.

When is RAM Used?

Ram is used mainly for 2 reasons. (although there are more)

1. When uploading a smart contract

When you write up a DApp and publish it for the first time, it will consume about 10 times as much RAM as your binary. This can vary depending on how well the smart contract is made, and how it was designed. As a result, it can be said that the RAM usage varies depending on the developer’s capabilities. However, because it is consumed at the time of smart contract deployment, it is not too big of a problem.

2. When saving data using the smart contract’s Table

When using a DApp, there needs to be the operation of saving and loading data. Because of this, EOS provides TABLE, and I believe most of the smart contracts are using this. However, it is this TABLE that occupies the most RAM. RAM is used each and every time a TABLE is created or when data is registered. Furthermore, the biggest problem is that if you do not delete the TABLE or the data, you cannot get back the RAM and continues to be occupied.

How could RAM be used more efficiently? An easy way would be for a savvy developer to design and code exquisitely to save RAM. However, this is not a fundamental solution to the use of TABLE. Then thinking a little deeper, one may think “saving and managing the minimal amount of data onto the TABLE to conserve” may be a better option, but this also means that the more the DApp is used, the RAM usage also increases in relation. Then what can we do? Do we need to get rid of TABLE?

The Method to Minimize RAM Usage

While developing at ITAM Network, there were numerous occasions we had to view the BLOCK Data of EOS. Shall we take a look at the BLOCK Data of EOS? (This is the 7813616th data)

{ timestamp: '2018-07-26T04:42:59.500',

producer: 'eosbixinboot',

confirmed: 0,

previous:

'007739ef7cf1462b05106250189fb55e4a8952d14e7db470f635d6f4557963c5',

transaction_mroot:

'a4c4496be9270606a2356eade3b45fad58a16972c2638dff8bd100241c0a4779',

action_mroot:

'147a36d77a0edbb12183f481f4afdaeb0660775b87b600f138ecd40fefa065e5',

schedule_version: 214,

new_producers: null,

header_extensions: [],

producer_signature:

'SIG_K1_Kb6tQTupJ8MTSrgNf1A4mZtDVtbBdUasjRXVw4ZfVmDAYzRLdiPV2WEmh5j1Yd2jubRoc9CjLBSpmoohpCPe8JgKa3xpDm',

transactions:

[ { status: 'executed',

cpu_usage_us: 1274,

net_usage_words: 40,

trx: [Object] },

{ status: 'executed',

cpu_usage_us: 1222,

net_usage_words: 21,

trx: [Object] },

{ status: 'executed',

cpu_usage_us: 1123,

net_usage_words: 40,

trx: [Object] },

{ status: 'executed',

cpu_usage_us: 5393,

net_usage_words: 23,

trx: [Object] },

{ status: 'executed',

cpu_usage_us: 1482,

net_usage_words: 40,

trx: [Object] } ],

block_extensions: [],

id:

'007739f09df05592a9ecae25238896787c8bcfc5b3600f2202134fcdda8cafa4',

block_num: 7813616,

ref_block_prefix: 632220841 }

The part to pay close attention to is the transactions, and amongst the transactions, let’s take a look at trx.

{ id: '45328c80df9aa6f1c09bcf0e2a7eb0eac4e03d0d9b41f2ed35b41cfae2104b12',

signatures: ['SIG_K1_KfyZanF2G1fFqLjLtw4x6HnmT9JSxo8k3QgGHbqdwHdn9K5v25yaXPJiRMEEvuA3cTWkPisqKBjvMvsX2EpzbigcYqWvRS' ],

compression: 'none',

packed_context_free_data: '',

context_free_data: [],

packed_trx:

'8e51595ba1388fe4f08d000000000100a6823403ea3055000000572d3ccdcd0110e0a53cab294d7600000000a8ed3232dd0110e0a53cab294d76a09863fa4c9b8965010000000000000004454f5300000000bb01496e74726f647563696e67204954414d204e6574776f726b2c20616e20454f532d426173656420444150502050726f6a656374206f6e20426c6f636b636861696e2047616d696e6720506c6174666f726d20666f722061205472616e73706172656e742047616d696e672045636f73797374656d2e202d2d576562736974653a2068747470733a2f2f6974616d2e67616d65732f656e202d2d54656c656772616d3a2068747470733a2f2f742e6d652f6974616d6e6574776f726b00',

transaction:

{ expiration: '2018-07-26T04:43:58',

ref_block_num: 14497,

ref_block_prefix: 2381374607,

max_net_usage_words: 0,

max_cpu_usage_ms: 0,

delay_sec: 0,

context_free_actions: [],

actions: [ [Object] ],

transaction_extensions: [] } }

We’re almost done. Let’s also take a look at actions.



name: 'transfer',

authorization: [ { actor: 'itamnetwork1', permission: 'active' } ],

data:

{ from: 'itamnetwork1',

to: 'gq4tqnbugige',

quantity: '0.0001 EOS',

memo:

'Introducing ITAM Network, an EOS-Based DAPP Project on Blockchain Gaming Platform for a Transparent Gaming Ecosystem. --Website:

hex_data:

'10e0a53cab294d76a09863fa4c9b8965010000000000000004454f5300000000bb01496e74726f647563696e67204954414d204e6574776f726b2c20616e20454f532d426173656420444150502050726f6a656374206f6e20426c6f636b636861696e2047616d696e6720506c6174666f726d20666f722061205472616e73706172656e742047616d696e672045636f73797374656d2e202d2d576562736974653a2068747470733a2f2f6974616d2e67616d65732f656e202d2d54656c656772616d3a2068747470733a2f2f742e6d652f6974616d6e6574776f726b' } { account: 'eosio.token',name: 'transfer',authorization: [ { actor: 'itamnetwork1', permission: 'active' } ],data:{ from: 'itamnetwork1',to: 'gq4tqnbugige',quantity: '0.0001 EOS',memo:'Introducing ITAM Network, an EOS-Based DAPP Project on Blockchain Gaming Platform for a Transparent Gaming Ecosystem. --Website: https://itam.games/en --Telegram: https://t.me/itamnetwork' },hex_data:'10e0a53cab294d76a09863fa4c9b8965010000000000000004454f5300000000bb01496e74726f647563696e67204954414d204e6574776f726b2c20616e20454f532d426173656420444150502050726f6a656374206f6e20426c6f636b636861696e2047616d696e6720506c6174666f726d20666f722061205472616e73706172656e742047616d696e672045636f73797374656d2e202d2d576562736974653a2068747470733a2f2f6974616d2e67616d65732f656e202d2d54656c656772616d3a2068747470733a2f2f742e6d652f6974616d6e6574776f726b' }

If you look at the above data, you can see the history of the transfer action being used in the eosio.token’s smart contract.

This post is about how to minimize RAM usage, but why did we look at Block data? Allow me to ask you a question.

Does Block data use RAM the same way it uses TABLE?

Block data does not use RAM; the data is accumulated in the BP operating a full node. Some of you may have already gotten the clue, but if you look a little further, we can conclude that we can minimize RAM usage if we use the data in the Block, NOT using TABLE.

Then how can we do this?

The answer is apparent if you look at the Block data; it’s the action data.

An action refers to the action data in a transaction that executes a smart contract’s specific action. Every smart contract’s execution is stored onto the Block, in the above form. This means that if we don’t use TABLE, but use the remaining data of the Block after execution the smart contract’s action, we can minimize the TABLE’s RAM usage.

I’ll Give an Example

At ITAM Network, we need to register the items acquired in a game. We’ll use this as an example.

With the itamnetwork1 account, publish a smart contract. Inside the smart contract, there is the get action, and let’s say we need the parameter value of itamKey, itemName, and onwer.

Execute the get action of itamnetwork1, and below is what we would see if we view it on the Block. (Let’s assume that the account name that obtained the item is itamnetwork2)

{ account: 'itamnetwork1',

name: 'get',

authorization: [ { actor: 'itamnetwork2', permission: 'active' } ],

data:

{ itamKey: '1',

itemName: 'Invisibility Cloak',

onwer: 'itamnetwork2',

},

hex_data:

'10e0a53cab294d76a09863fa4c9b8965010000000000000004454f5300000000bb01496e74726f647563696e67204954414d204e6574776f726b2c20616e20454f532d426173656420444150502050726f6a656374206f6e20426c6f636b636861696e2047616d696e6720506c6174666f726d20666f722061205472616e73706172656e742047616d696e672045636f73797374656d2e202d2d576562736974653a2068747470733a2f2f6974616d2e67616d65732f656e202d2d54656c656772616d3a2068747470733a2f2f742e6d652f6974616d6e6574776f726b' }

As you can see, we can see all the data that you want to save as the action’s data in the Block information. If you use the data of the block like this, I believe it will be a way to minimize the amount of RAM used by the TABLE.

What are the Preparations?

This is pretty evident, but you need to able to take advantage of Block data. If you store the EOS Block data in a database, you can easily search and process based on that database.

Therefore, what’s needed is a way of retrieving the Block’s data every time while maintaining full node, or, as a good alternative store specific actions in the database using demux-js that was recently released on EOS.

Things to Consider

There are things you must think about when using Block data.

1. EOS Fullnode / demux-js

To utilize the block data, it is necessary to have a way of maintaining a full node or to use demux-js. We need to think about if this is an effective method.

2. Smart Contract Design

Because this is not a common way to use TABLE, the design of the smart contracts is critical.

3. Business Model

Because all the data is exposed on the block, you need to design your business model accordingly.

Conclusion

In conclusion, we went over using action data, which goes on the block, while avoiding the use of TABLE, which uses a lot of RAM. Please keep in mind this is only one alternative method, and is not the only correct answer. Review by the ones that apply this method is crucial.