本文采用火币网区块链智能合约语言中的内存映射实体的存储变量。
在datona实验室s-dac模板的开发和测试过程中,我们需要对一些持久性数据进行排序,例如:
“导入”溶剂“ContractsDC100IS…{uint[]文件键;functionsortFileKeys()内部{快速排序(文件键);}//。。。
Solidity有两个数据位置:存储和内存。存储在多个智能合约调用之间是持久的,而内存是临时的,只存在于每个调用中。第三个数据位置称为calldata,它实际上与内存相同。
上述代码段中的数组必须在多个协定调用之间是持久的,因此它必须驻留在存储中。
但是访问存储比内存消耗更多的气体,因此访问数据的算法将非常昂贵。
火币网0中的任何一种传统排序算法,如插入排序或快速排序,都需要大量的数据访问来比较和交换元素。非比较排序(如计数排序)节省了元素比较和交换的时间,但仅限于已知的小数字。
必须重写排序算法以找到正确的数据位置,例如:
函数快速排序(uint[]storagedata)内部{//。。。
映射数据
减少空气消耗是将持久性存储阵列**到内存中,执行排序,然后再次**阵列。
functionsortFileKeys()内部{uint[]memoryshadow=fileKeys;快速排序(shadow);fileKeys=shadow;}
这个函数在数据位置之间**数组需要消耗大量的气体,但与排序成本相比,这是否微不足道?
让我们测量一些样本数据来找出答案。
我们将测量存储和映射内存数据位置中的不同排序算法。元素值是使用生成确定值序列的伪随机数生成器生成的。
结果
运行所有合同并将数据整理到电子表格中,以生成以下结果。
注意,计数排序比快速排序和在存储中插入排序快得多(图1)。
请注意,从存储**到内存(s=gt;m)和再次返回(m=gt;s)的成本占气体消耗(图2)。
复合曲线显示用于比较(图3)。
在存储方面,计数顺序几乎与映射内存一样快(图3)。这是因为它跳过了所有昂贵的元素比较和交换。不幸的是,计数排序只在元素值在一个小的已知范围内时有效。
此外,虽然额外的气体消耗是由在不同数据位置(图2中的s=gt;m和m=gt;s)之间**数组引起的,但使用映射内存(此处为快速排序和插入排序)进行比较排序的气体消耗是使用存储的六倍(图3)。
顺便说一句,如果在调用排序例程之前数据可能处于排序状态,那么只有在数据已更改时才将数组从内存**回存储器是有益的。
functionsortFileKeys()内部{uint[]memoryshadow=fileKeys;如果(快速排序(shadow))//ifdatahaschangedfileKeys=shadow;}
在这种情况下,需要修改排序例程以指示数据是否已更改。
结论
在实体中的存储数据位置使用排序非常昂贵,因此在内存数据位置中映射和排序数据总是值得的。
使用映射技术还可以使执行许多数据访问的其他算法受益。
至于排序算法,请使用ldquo;快速排序或ldquo;插入排序。后者是一种更简单的算法,因此字节码更少。
——————————————
朱利安·戈达德
原始链接:https://medium.com/coinmonks/shadowing-SOLidity-storage-ariables-in-memory-b56f471eddd81
翻译:链三丰
文章链接:https://www.btchangqing.cn/43058.html
更新时间:2020年06月23日
本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。