浅谈IC Storage存储技术

区块链安全 3年前 (2021) admin
493 0 0
浅谈IC Storage存储技术

“经过社区的讨论,Dfinity 开放了提升 Canister 内存容量的 NNS 提案,目前,该提案已经由社区投票通过。该提案建议为容器设计一个新的系统 API,使得 Canister 可使用的内存增加,后续会有代码的正式更新。”

浅谈IC Storage存储技术

浅谈IC Storage存储技术
Canister

Canister的总体内存包含wasm run time和stable memory,对一个Canister而言, 两个都为4G。

浅谈IC Storage存储技术

由于wasmtime是32bit的指针地址空间,因此是4G,而stable memory需要和wasm time适配, 所以也是4G,本次提案提高的内存为Stable内存, 使一个Canister可使用的最大内存为全部子网内存, 但此次开放的API将只支持Canister最大使用8G Stable内存。

浅谈IC Storage存储技术

Wasm 单体的内存空间为4G, 但是由于Motoko所选用的GC(Garbage Collector 垃圾回收)算法为Copying算法[1],造成由Motoko写的Canister只能使用2G内存空间。

浅谈IC Storage存储技术

[1]Coping Collector Algorithm(Minor GC),该算法在WASM Canister中的应用:

1. 4G 的Canister被划分为两个区域 :from space & to space, 分别占用2G;数据写入时, 所有的数据都在from space中。

2. 在进行dfx canister install xxx(default : –all) — mode upgrade的时候, 会进行GC,即:将活动对象(正在使用的对象,可以是引用也可以是元数据)从from space移动到to space, 剩下的即内存垃圾, 接下来,删除掉from space中的数据(内存垃圾), 最后将from space 与 to space的名称互换。

浅谈IC Storage存储技术
3. 优势:内存使用率很高,写数据时是对堆进行连续写入, 所以利用率更高 。适用于快速增删数据的场景。(现在Java的JVM等新一代VM都一定程度上采用了Minor GC)。
4. 缺陷:浪费了一半的堆内存空间, 并且在活体对象数量大时不建议使用Coping gc。
P.S. Motoko现在已可指定Compacting GC算法, 这个算法不会占用一半的内存来进行GC,可以使用尽可能大的WASM内存。
5. 对4G stable内存进行读写仅发生在upgrade过程。

浅谈IC Storage存储技术

这带来的劣势是:当堆内存在升级时有大量要写入stable内存的数据时,可能会将cycle消耗完,导致无法升级。

6. 触发时间:coping gc触发时间是在新生成的变量所 需内存大于已有的变量(2G-已用内存)或者当前已用内存大于2G时。
浅谈IC Storage存储技术
存储提案

浅谈IC Storage存储技术

 https://forum.dfinity.org/t/increased-canister-storage/6148/67

提案内容:提供一个系统API, 使每个Canister都可以使用子网所有的内存空间, 所有的副本都有自己的数据状态, 每个Canister均有自己的WASM运行时内存和Stable内存空间。

新增的System API (面向Canister):

ic0.stable64_write: (offset: i64, src: i64, size: i64) -> ()

ic0.stable64_write接口是为了WASM 64进行准备的

ic0.stable64_read: (dst: i64, offset: i64, size: i64) -> ()
ic0.stable64_size: () -> (page_count: i64)
ic0.stable64_grow: (additional_pagesi64-> (old_page_counti64
提案现状:
    • 提案于9.3日通过NNS审核, 接下来就是更新代码的事情。提案只是一个征求社区看法的提案。
     •  最近将提交修改IC代码的提案。

带来影响:

    • 对Canister而言, Canister可以使用的内存从4G -> 8G(stable内存而非堆内存)。并且 8G是当前提案的结果, 以后会根据社区反馈会提升这个数字。

浅谈IC Storage存储技术

    • 如果stable内存高于4G, 那么使用了升级内存API的Canister和没有使用此API的Canister交互将会出现问题,当前的方案是发生上述情况时,Canister会崩溃。

未来解决方案:
    • 沿用现在的解决方案 :子网内存共享, 3T内存分出300G给stable内存存储(尚不清楚300G这个数字是怎么来的, 8G是怎么来的)。这样的缺陷是:这种情况下,存储内存最大限制就是一个子网内的stable内存的限制, 这显然是不能长久的。
    • BigMap:通过多个Canister分片存储数据,当前状况是没有达到生产级别的要求, 还没有放出。

    • WASM 64 :单个Canister升级为64bit的地址空间, 最大内存为2^64 Byte(16 T)• 数据迁移所牵扯的数据量会很大,会出现新的问题,比如升级时数据迁移量大等。

建议:
    • 现阶段还是一个实验性的API, 建议不要使用。等待成熟以后再使用。
浅谈IC Storage存储技术
浅谈IC Storage存储技术
浅谈IC Storage存储技术
如何获取Canister存储状态

Motoko

RTS : Run Time System 运行时系统, 包含GC, 序列化(通信传输用), low-level 库(底层分配内存等)的调用。
rts_memory_size: () -> Nat :当前WASM的内存, 不是使用了多少的内存, 而是已经分配了的堆内存;
rts_heap_size: () -> Nat :当前实际堆内存大小;
rts_max_live_size : () -> Nat :从上次GC到现在堆最大的大小;

Rust

• 使用IC “aaaaa-aa” Actor可以访问IC.status, 也可以返回上面说到的内存数据;
• Rust可以在非Upgrade时期, 通过cdk中提供的API操作Stable内存。

DFX & Moc

moc 中flag可选 –compacting gc 来更换coping gc, compacting gc下motoko编译的Canister将可以使用4G 的WASM 内存。

Stable内存

stable只能用于需要持久化存储的全局变量,只在upgrade的时候写入stable内存用。对于Canister, Canister的每个Replica都有自己的stable内存, 并非所有的Replica共享一份Stable内存

浅谈IC Storage存储技术
关于数据存储的其他Tips

1. 作用于存储的数组最好使用Blob而非[Nat8], 因为初始化数组时, 由于泛型的需要, 所有通过[X]或者Array.init初始化的数组内存布局是相同的。
2. 当前比较成熟的解决方案:存储的数据直接放入stable内存中, 堆内存用来放置检索数据。

浅谈IC Storage存储技术

外部链接

[1] Forum Stable Memory Roadmap https://forum.dfinity.org/t/increased-canister-storage/6148/70?u=c-b-elite

浅谈IC Storage存储技术

原文始发于微信公众号(ICPLabs):浅谈IC Storage存储技术

版权声明:admin 发表于 2021年9月12日 上午5:16。
转载请注明:浅谈IC Storage存储技术 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...