美文网首页践行区块链
哪种写法更省 gas

哪种写法更省 gas

作者: Ashton | 来源:发表于2023-03-14 09:10 被阅读0次

0x01 有趣的问题

有人提出这么个问题,下面哪种写法更省 gas

 function mul(uint256 x) public pure returns (uint256) {
      return x * x * x;
 }

 function exp(uint256 x) public pure returns (uint256) {
      return x ** 3;
 }

0x02 如何分析

两个写法最终的差别体现在是用运算符 " * " 还是 " ** " 上。
运算符 " * " 最终会用到 EVM 指令 MUL
运算符 " ** " 最终会用到 EVM 指令 EXP
对于 MUL 和 EXP 两个指令的消耗,我们可以查表:https://ethereum.org/en/developers/docs/evm/opcodes/
通过查表得知,MUL 指令一次消耗的 gas 是 5,两次 MUL 消耗的 gas 就是 10
EXP 指令的消耗有个动态计算公式

gas_cost = 10 + 50 * byte_len_exponent

" x ** 3 " 所用到 EXP 指令的消耗就是 10 + 50 * 1 = 60

但是不是这就意味着 "mul" 这个函数比 "exp" 这个函数更省 gas 呢?

0x03 实证

把代码在 remix 运行,当输入为 100 时,“exp” 的消耗是 1052


image.png

“mul” 的消耗是 1084


image.png

“exp” 函数比 "mul" 更省 gas,为啥呢?
这是因为 “ x * x * x" 这种写法需要更多的中间指令,如果对比 "x * x" 和 "x ** 2" 就会发现 "x * x" 要更省 gas 了。

但是,当我们把输入改为 1000 时,“exp“ 的消耗变为 1293


image.png

而 “mul” 的消耗仍然为 1084


image.png

这是为啥呢?

Solidity 的官方 blog https://blog.soliditylang.org/2020/12/16/solidity-v0.8.0-release-announcement/ 有这么一段话:

For bases up to 306, if the exponent is smaller than a hard-coded safe upper bound, it will use the exp opcode directly. If the base or the exponent is too large, it might fall back to the loop-based implementation.

明白了么?如果基数大小超过 306,solidity 会使用 MUL 而不是 EXP 指令,消耗了比直接用 MUL 更多的 gas。

如果我们不希望 solidity 为我们做这样的处理,可以使用 assembly:

 function exp(uint256 x) public pure returns (uint256) {
      assembly {
        mstore(0x0, exp(x, 0x3))
        return (0x0, 32)
      }
    }

相关文章

网友评论

    本文标题:哪种写法更省 gas

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