EOS 数据库RAM使用量的计算

       如果你是EOS的合约开发者,相信你很有可能跟我一样对内存(RAM)的使用量感到不解。在使用multi_index进行数据存储时,明明只存了一点数据,但区块链浏览器中显示的内存占用量却上升了不少。在这篇文章中,我们就来对内存用量一探究竟,精确计算出存储数据所需要的RAM。我们会首先编写一个简单的合约,用以向multi_index内存入数据。部署合约后,每次调用接口前后都查询一下RAM用量,并予以记录。

合约编写

新建合约目录:

1
2
3
$ mkdir addrow
$ cd addrow
$ touch addrow.cpp

这里是一份简单的合约,用户每次调用add时,数据库中都会多存一行记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <eosiolib/eosio.hpp> 
   
class [[eosio::contract]] addrow : public eosio::contract 
public: 
    addrow( eosio::name receiver, eosio::name code, eosio::datastream<const char*> ds ) 
        : eosio::contract(receiver, code, ds),  _students(receiver, code.value) 
    {} 
   
    //添加学生 
    [[eosio::action]] 
    void add(eosio::name user) 
    
        require_auth(user); 
        eosio::print("Add student ", user); 
        _students.emplace(get_self(), [&](auto& p) { 
            p.id = _students.available_primary_key(); 
        }); 
    
   
    struct [[eosio::table]] students 
    
        uint64_t      id; // primary key 
   
        uint64_t primary_key() const { return id; } 
    }; 
   
    //数据表根据age排序 
    typedef eosio::multi_index<"students"_n, students > studentstable; 
   
    //students数据库表 
    studentstable _students; 
}; 
   
EOSIO_DISPATCH( addrow, (add) )

使用eosiocpp工具进行编译后,得到addrow.wasmaddrow.abi文件:

1
2
$ eosiocpp -o addrow.wast addrow.cpp
$ eosiocpp -g addrow.abi addrow.cpp

部署合约

1
2
3
cleos -u https://jungle2.cryptolions.io:443 set contract zmcheng12345 /root/github.com/addrow -p zmcheng12345@active
查账户内存使用情况:
cleos -u https://jungle2.cryptolions.io:443 get account zmcheng12345 -j

我查询到的数值为:

1
"ram_usage": 52665

这个数值可能根据你的编译工具和参数不同而有所变化。我们以查询到的数值为基础,进行后续的差值计算。

调用合约,新增一行数据:

1
$ cleos push action eosio.ramfee add '' -p eosio.ramfee

查询用量,得到的结果是:

1
"ram_usage": 52897

再新增一行并查询,这次的结果是:

1
"ram_usage": 53017

通过计算可以得出,新增第一行的内存占用量达到了232字节!而第二行的占用量也高达120字节!如果继续新增行数,你会发现后续的行占用量均为120字节。

也就是说,存储一个仅有一个uint64_t字段(大小为8字节)的数据表,首行占用232字节,后续行数占用120字节。

总结

在EOS合约内使用multi_index存储数据(不使用secondary index的情况下),需要承担以下RAM使用量:

  • 首先,每新增一行记录,都会占用112字节+实际数据大小
  • 如果这个数据表本身不存在,需要再额外收取112字节的RAM占用

可以看到,每行数据的overhead(112字节)还是相当大的。如果单纯地使用数据结构大小来计算,预期使用量与实际使用量的误差会非常大(本例中,首次存储8字节数据的实际用量是数据大小的29倍!)。而得知了精确的占用量算法之后,就可以更好地规划dApp所需要的内存量了。

 
posted @   人艰不拆_zmc  阅读(688)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2014-09-18 POJ1426:Find The Multiple(算是bfs水题吧,投机取巧过的)
2014-09-18 POJ:3083 Children of the Candy Corn(bfs+dfs)
点击右上角即可分享
微信分享提示