虚拟机的执行资源

以太坊的虚拟机经常被拿来与x86台式机的结构作对比,它们有相同点也有很大的不同点。

相比于台式机或者手机,以太坊的虚拟机更加紧凑,资源更加匮乏。 它并不包含正常的CPU 所具备的硬件寄存器(Register),所以执行速度没有这么快。 它的执行宽度都是 256bit 的固定长度值,所以相对比较容易编程,它包含了存储、堆栈、内存三大存储机构。

7-2 显示了以太坊的虚拟机的执行资源。

../_images/Picture46.png

以太坊虚拟机的执行资源


Storage 存储

存储里的值都是永久记录在区块链上的。存储在写和读取上都代价昂贵,如非必须,则数据不要存储在存储区。 存储区是全世界计算机都会同步到硬盘上的区块链的一部分,哪怕关机以后也被永久记录。 那么哪些值需要保存在这里呢?只有那些需要在程序执行后任然留存的数字才需要, 例如以太坊的ERC20智能合约追踪token持有者和token数量的关系,这个数据需要持久化保存到存储区。 存储区的数据都是 256bit 的键和值配对存储,如图7-3所示。如果查询时一个键对应的值不存在,则它读取的值为 0 。 存储区的读写操作都是以 256bit 为单位的,没有更小的操作空间。故而 uint8 和 uint256 在单值存储的情况下占用的空间相同,耗费的 Gas 也相同。 将 unit8 包裹进入 struct 结构体以后可以通过优化来节约空间位置,节省gas支出。
../_images/Picture47.png

存储 Storage 示意图,索引和值都是256位的数据


Stack 堆栈

堆栈的花费和内存差不多,堆栈往往保存了执行过程的上下文,如图 7-4。 堆栈有且仅有 1024 层深度,当我们执行递归调用过多的时候,堆栈就会击穿 1024 层,则代码执行失败。

这在其他编程语言中也是相同的原理。

堆栈仅有高处的 16 层是可以被快速访问的,堆栈的宽度也是 256bit,也就是 32byte,一个 word 的长度,任何读写操作都是 256bit 为一个单位进行的。 编译器往往会将代码执行中的临时变量、变量地址放到堆栈上临时保存,变量地址可以进一步索引到内存 Memory 中。

../_images/Picture48.png

堆栈 Stack 示意图,数据都是256bit进出堆栈


Memory 内存

内存在以太坊虚拟机中和真实计算机的内存概念相近:一旦虚拟机启动,内存就处在不断变化之中,承载了程序运行时的指令和数据的保存。 一旦虚拟机执行结束并关机,内存保存的数据就会灰飞烟灭。

内存的管理办法也是按照 256bit 为单位进行读取和写入, 如图 7-5 所示。写入时候也可以选择 8bit 为单位写入,因为内存的宽度是 8bit。内存的读取和写入都相对其他两种存储而言更便宜。

举例来说,读取和写入一个 256bit的值花费仅有 3Gas,是 Storage 存储区的写操作的万分之一多一点。

../_images/Picture49.png

内存 Memory,合约执行完毕就会自动清空