美文网首页
Eos发布智能合约所占内存分析

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

作者: learnforever01 | 来源:发表于2018-10-26 17:22 被阅读57次

    如果你在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<uint64_t, std::unique_ptr<wasm_instantiated_module_interface>> instantiation_cache;
    

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

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

    wasm的wavm运行模式下为:

    class wavm_instantiated_module : public wasm_instantiated_module_interface {
          std::vector<uint8_t>     _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>  _module;
    }
    

    wasm的wabt模式的定义如下:

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

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

    以上即为个人分析

    相关文章

      网友评论

          本文标题:Eos发布智能合约所占内存分析

          本文链接:https://www.haomeiwen.com/subject/ildhtqtx.html