美文网首页践行区块链
哪种写法更省 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