Eos发布智能合约所占内存分析

如果你在Eos上发布一个智能合约,细心点的话可能会发现一个问题,就是你发布后代码所占的ram远比你的编译后的wasm代码和abi文件的总字节数大的多,如果减去abi文件所占的存储空间,你会发现,所占的内存刚好是代码大小的10倍。这是一个有意思的问题。答案就在如下的代码中:

找到libraries/chain/eosio_contract.cpp这个文件的

void apply_eosio_setcode(apply_context& context)

这个函数,你会发现如下的代码:

   int64_t code_size = (int64_t)act.code.size();
   int64_t old_size  = (int64_t)account.code.size() * config::setcode_ram_bytes_multiplier;
   int64_t new_size  = code_size * config::setcode_ram_bytes_multiplier;
...
   if (new_size != old_size) {
      context.add_ram_usage( act.account, new_size - old_size );
   }

也即这里把code_size乘以了一个常量:config::setcode_ram_bytes_multiplier,这个常量在config.hpp中定义如下:

const static uint32_t   setcode_ram_bytes_multiplier       = 10;     ///< multiplier on contract size to account for multiple copies and cached compilation

也即为常数10,这就有点奇怪了,为什么要把存储空间乘以十呢。看注释可以看出点名堂来:

multiplier on contract size to account for multiple copies and cached compilation

也即这个乘数是为了将wasm代码的多份拷贝和编译缓存所占的内存计算在内。找到libraries/chain/include/eosio/chain/wasm_interface.hpp,你会发现如下的变量:

map> instantiation_cache;

这个变量即是用来在缓存wasm代码的。

wasm的wabt模式和wavm运行模式都对wasm_instantiated_module_interface这个类进行继承

wasm的wavm运行模式下为:

class wavm_instantiated_module : public wasm_instantiated_module_interface {
      std::vector     _initial_memory;
      //naked pointer because ModuleInstance is opaque
      //_instance is deleted via WAVM's object garbage collection when wavm_rutime is deleted
      ModuleInstance*          _instance;
      std::unique_ptr  _module;
}

wasm的wabt模式的定义如下:

class wabt_instantiated_module : public wasm_instantiated_module_interface {
   private:
      std::unique_ptr              _env;
      DefinedModule*                                    _instatiated_module;  //this is owned by the Environment
      std::vector                              _initial_memory;
      TypedValues                                       _params{3, TypedValue(Type::I64)};
      std::vector>       _initial_globals;
      Limits                                            _initial_memory_configuration;
      Executor                                          _executor;
}

看变量声明就知道除了发布智能合约会占用ram之外,为了运行wasm智能合约也是会占用大量的额外的内存。但是,个人感觉这个把内存乘以十的预计算内存的做法有点简单粗暴了,可能是为了让RAM的计算的代码不会过于复杂吧。另外,setcode_ram_bytes_multiplier这个乘数只是针对wasm虚拟机的,如果是其它虚拟机,这个值应该根据实际情况作下调整。

以上即为个人分析

你可能感兴趣的:(Eos发布智能合约所占内存分析)