Solidity将数组长度作为循环条件的gas优化问题
问题解答
循环判断时是否每次都要从storage读取数组长度
答案是是,默认情况下每次判断循环条件都会触发storage读取。
原因:动态状态数组的length属性本身就存储在storage中,Solidity编译器默认不会对fooArray.length的读取做自动缓存优化,因为编译器无法预判循环体内部会不会修改数组长度。即使你自己明确知道循环内不会修改数组,编译器也不会主动做这个优化,所以每次执行i < fooArray.length判断时,都会执行一次SLOAD操作读取storage中的长度值。
是否需要提前把长度存到局部变量省gas
非常推荐你这么做,gas节省的幅度会随着数组长度增加变得非常明显:
- 一次storage读取(SLOAD)冷读成本为2100gas,热读也需要100gas
- 局部变量存储在栈/内存中,单次读取成本仅为个位数gas
举个例子,如果你的数组有100个元素,缓存长度的写法只会触发1次SLOAD,而原写法会触发100次SLOAD,仅长度读取的部分就能省下近10000gas。
优化后的写法示例
uint256 len = fooArray.length; for (uint256 i = 0; i < len; ++i) { // 循环逻辑,确认不会修改fooArray的长度 }
注意:该优化仅适用于循环过程中不会修改数组长度的场景,如果循环内会对数组做push、pop等修改长度的操作,缓存长度会导致逻辑错误,不要使用该优化。
内容的提问来源于stack exchange,提问作者ktv6
相关产品推荐
相关产品推荐

