首页 > 其他分享 >什么是 Gas 优化?为什么重要?

什么是 Gas 优化?为什么重要?

时间:2024-12-25 17:52:49浏览次数:3  
标签:为什么 uint256 data 代码 Gas 优化 public

在以太坊和其他 EVM 区块链上,执行智能合约需要支付 Gas 费用。Gas 是衡量智能合约计算成本的单位,用户需要为合约执行支付费用,费用由 Gas 消耗量和当前 Gas 价格决定。高效的智能合约设计可以显著降低 Gas 消耗,从而为用户和开发者节约成本,提升合约的可用性。

在实际应用中,以下场景尤为需要关注 Gas 优化:

  1. 频繁调用的合约,如 DeFi 协议或 NFT 市场。
  2. 大规模操作,如批量转账或复杂逻辑计算。
  3. 链上存储,因存储操作的成本远高于计算。

如何实现 Gas 优化?

1. 减少冗余的状态变量写入

状态变量(storage)操作非常昂贵。写入和读取存储的成本远高于在内存中操作。

示例优化

不优化的代码:

uint256 public total;

function add(uint256 value) public {
    total += value; // 每次操作直接写入存储
}
优化的代码: solidity
uint256 public total;

function add(uint256 value) public {
    uint256 temp = total; // 先读取存储到内存中
    temp += value;
    total = temp; // 最后一次性写回存储
}

 

Gas 节省效果

减少频繁写入 storage 的次数,可以显著降低每次函数调用的成本。


2. 优先使用内存(memory)而非存储(storage)

内存是临时性的,成本低;存储是永久的,成本高。在函数中处理数据时,尽量使用内存变量代替存储变量。

示例优化

不优化的代码:

 
function calculate(uint256[] storage data) public {
    for (uint256 i = 0; i < data.length; i++) {
        data[i] += 1;
    }
}

优化的代码:

solidity function calculate(uint256[] memory data) public pure returns (uint256[] memory) {
    for (uint256 i = 0; i < data.length; i++) {
        data[i] += 1;
    }
    return data;
}

Gas 节省效果

将操作移至内存后,避免了对存储的高成本读写。


3. 用 calldata 替代 memory 参数

对于只读函数,使用 calldata 参数可以进一步节省 Gas,因为 calldata 是不可修改的外部输入数据,其存储成本比 memory 更低。

示例优化

不优化的代码:

solidity function processData(string memory data) public pure returns (uint256) {
    return bytes(data).length;
}

优化的代码:

solidity function processData(string calldata data) public pure returns (uint256) {
    return bytes(data).length;
}

Gas 节省效果

使用 calldata 作为不可变参数时,省去了数据拷贝的开销。


4. 简化复杂的逻辑条件和循环

复杂逻辑和循环会增加计算成本。在可能的情况下,尽量简化条件语句并减少循环的迭代次数。

示例优化

不优化的代码:

solidity function findMax(uint256[] memory data) public pure returns (uint256) {
    uint256 max = 0;
    for (uint256 i = 0; i < data.length; i++) {
        if (data[i] > max) {
            max = data[i];
        }
    }
    return max;
}

优化的代码:

solidity function findMax(uint256[] calldata data) public pure returns (uint256 max) {
    for (uint256 i = 0; i < data.length; i++) {
        max = data[i] > max ? data[i] : max;
    }
}
 

Gas 节省效果

通过三元运算符简化逻辑,并结合 calldata 参数,进一步降低了执行成本。


5. 优化事件日志

事件日志用于链上和链下通信,但过多的日志内容会导致额外的 Gas 消耗。仅记录必要的数据。

示例优化

不优化的代码:

solidity
event Transfer(address indexed from, address indexed to, uint256 amount, uint256 timestamp);

function transfer(address to, uint256 amount) public {
    emit Transfer(msg.sender, to, amount, block.timestamp);
}

优化的代码:

solidity
event Transfer(address indexed from, address indexed to, uint256 amount);

function transfer(address to, uint256 amount) public {
    emit Transfer(msg.sender, to, amount);
}

Gas 节省效果

减少不必要的事件参数,降低日志的存储成本。


6. 优化代币的分发逻辑

在批量分发代币时,避免逐一转账的高成本操作,可以采用批量处理方式。

示例优化

不优化的代码:

solidity:
function distribute(address[] memory recipients, uint256 amount) public {
    for (uint256 i = 0; i < recipients.length; i++) {
        transfer(recipients[i], amount);
    }
}

优化的代码:

solidity
function distribute(address[] calldata recipients, uint256 amount) public {
    uint256 total = recipients.length * amount;
    require(balanceOf(msg.sender) >= total, "Insufficient balance");

    for (uint256 i = 0; i < recipients.length; i++) {
        _transfer(msg.sender, recipients[i], amount);
    }
}

7. 避免浮点计算

EVM 不支持浮点数,因此所有涉及小数的操作需要放大精度。这种放大操作可以通过优化减少不必要的计算。

示例优化

不优化的代码:

solidity function calculate(uint256 value) public pure returns (uint256) {
    return value * 10 / 100; // 计算 10%
}
 

优化的代码:

solidity function calculate(uint256 value) public pure returns (uint256) {
    return value / 10; // 简化为整除操作
}
 

总结

Gas 优化不仅能降低用户的使用成本,还能提高合约的执行效率和可扩展性。以下是常见的优化要点总结:

  1. 避免频繁的存储操作。
  2. 优化数据操作方式,优先使用 memorycalldata
  3. 简化逻辑,减少复杂运算。
  4. 控制事件日志的规模,减少冗余参数。
  5. 在批量操作中优化循环逻辑。

通过上述方法和最佳实践,开发者可以设计出更加高效、经济的智能合约。

标签:为什么,uint256,data,代码,Gas,优化,public
From: https://www.cnblogs.com/zhanchenjin/p/18631122

相关文章

  • Kubernetes 为什么减少对 Docker 的依赖:容器运行时演进背后的技术考量
    引言容器技术的发展离不开Docker和Kubernetes的深度合作。Docker推动了容器化技术的普及,而Kubernetes则为大规模容器编排和自动化管理提供了强有力的支持。然而,随着Kubernetes逐步发展,尤其是在容器运行时(ContainerRuntime)方面的需求发生变化,Kubernetes在1.20版本中......
  • 优化大宽表查询性能,揭秘GaussDB(DWS) 谓词列analyze
    本文分享自华为云社区《GaussDB(DWS)谓词列analyze揭秘》,作者:SmithCoder。1.前言适用版本:【9.1.0.100(及以上)】​当前GaussDB(DWS)中存在手动analyze,查询触发的动态analyze,以及后台线程的轮询analyze三种触发形式,其中动态analyze又分为light模式和normal模式,light模式是基于内......
  • 龙哥量化:TB交易开拓者_趋势跟踪策略_多策略对单品种_A00011880206期货量化策略,不用过
    写在前面,做自动交易的宽客们都在寻找圣杯,目前,我找到一只玻璃杯,经过半年的漫长等待,玻璃杯没让我失望。路漫漫其修远兮,吾将上下而求索。如果您需要代写技术指标公式,请联系我。龙哥QQ:591438821龙哥微信:Long622889也可以把您的通达信,文华技术指标改成TB交易开拓者(金字塔、文华8......
  • HarmonyOs DevEco studio小技巧39--LazyForEach:性能优化与懒加载
    在鸿蒙系统的应用开发中,LazyForEach是一个极为重要的工具,它在处理列表数据展示等场景时展现出独特的性能优化和懒加载特性,为应用开发带来诸多显著优势。一、LazyForEach在鸿蒙中的优势(一)高效的内存管理在处理大量数据时,传统的组件渲染方式可能会一次性创建所有数据对应的......
  • 33. 接口性能优化有哪些方法
    1、优化索引。给where条件的关键字段,或者orderby后面的排序字段,加索引。2、优化sql语句。比如避免使用select*、批量操作、避免深分页、提升groupby的效率等。3、避免大事务。使用@Transactional注解这种声明式事务的方式提供事务功能,容易造成大事务,引发其他的问题。应该避免......
  • 【实战必备】MySQL慢查询优化实战,让你的SQL飞起来!
    本文将详细介绍MySQL慢查询的排查和优化方法,包括如何开启慢查询日志、分析慢查询、优化索引等实用技巧。一、什么是慢查询?在MySQL中,慢查询指的是执行时间超过指定阈值的SQL语句。默认情况下,这个阈值是10秒。通过分析和优化这些慢查询,我们可以显著提升数据库性能。二、开启慢......
  • java~重写hashcode时为什么要乘以31
    在Java中,重写hashCode()方法时常常会使用31作为乘数,这是因为31具有一些独特的数学性质,使其成为一个优秀的选择。以下是几个原因:1.奇质数的特性31是一个奇数和质数,这意味着它能有效地减少哈希冲突的概率。使用质数作为乘数可以帮助分散哈希值,从而提高哈希表的性能。2.位运算效......
  • MySQL 千万 级数据量根据(索引)优化 查询 速度
    MySQL千万级数据量根据(索引)优化查询速度|Id|Title|DateAdded|SourceUrl|PostType|Body|BlogId|Description|DateUpdated|IsMarkdown|EntryName|CreatedTime|IsActive|AutoDesc|AccessPermission||-------------|-------------|------------......
  • vscode怎么连接远程服务器使用jupyter和pycharm?安装了jupyter插件为什么还是打不开jup
    本文主要从下面三个方面进行1.vscode的优势2.怎么安装并配置vscode3.怎么使用jupyter和pycharm4.我遇到的问题(已解决)(1)显示你即将连接到不受visualstudiocode版本(2)解决安装了jupyter插件但是还是打不开.ipynb文件无法打开笔记本编辑器类型为"jupyter-notebook"的资源......
  • 2024/12/25 任务【multi-objective optimization algorithm 多目标优化算法】解决问题
    知识点:Git配合Github的简单使用,硕士开题报告:选题意义(10分),难易程度(5分),对国内外现状的综述(5分)论文的开题报告,写好这些就够了!_哔哩哔哩_bilibili:写清楚研究方向研究的意义现在做到什么程度存在哪些问题你想怎么解决准备用哪些数据去验证你的成果参考文献Github新手够用指......