当前位置: 首页 > news >正文

关于gas费优化问题

关于gas费优化问题

首先我们先来看一下这段代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] memory nums) external{for(uint i = 0;i<nums.length;i+=1){bool isEven = nums[i] % 2 == 0;bool isLessThan99 = nums[i] < 99;if(isEven && isLessThan99){total += nums[i];}}}
}

在这段代码中定义了一个total的状态变量,并且将其传入数组的偶数以及小于99的数去进行累加。

当我们一开始运行sum方法的时候,我们可以看出第一次执行的gas费用为

28654

现在我们开始第一个优化:将memory改为calldata

contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] calldata nums) external{for(uint i = 0;i<nums.length;i+=1){bool isEven = nums[i] % 2 == 0;bool isLessThan99 = nums[i] < 99;if(isEven && isLessThan99){total += nums[i];}}}
}

此时我们再看看所需要用到的gas费用,此时少了2000左右

26909

为什么会这样呢?

我们对比一下calldata和memory的区别

在Solidity中,calldata是指函数调用参数的存储位置。而memory是在函数内部声明的临时变量的存储位置。

使用calldatamemory更能节省gas费用的原因是,calldata是只读的,在函数执行期间不能被修改。相反,memory中的数据可以在函数执行期间被修改,这意味着如果你使用memory存储大数据结构,每次修改都需要消耗更多的gas费用。

在这个场景中我们可以看到似乎nums作为一个入参似乎并不需要被改变,所以这里我们直接用calldata即可。

我们再来看看循环体内部

我们发现这里面的total这个状态变量,在每一次循环里面都会将total里面的重新赋值,这种在整体状态变量层面的操作实际上是非常浪费gas的。

我们不妨换一种思路,将total抽离到循环外,方法内单独设置一个变量去将total拷贝到内存中去,也就是我们每次累加的是内存中的一个变量,这样并不会写入状态变量。最后再循环结束后再一次性的将结果写入到状态变量中。

代码如下:

contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] calldata nums) external{uint _total = total;for(uint i = 0;i<nums.length;i+=1){bool isEven = nums[i] % 2 == 0;bool isLessThan99 = nums[i] < 99;if(isEven && isLessThan99){_total += nums[i];}}total = _total;}
}

此时我们可以执行看看gas费用的消耗,此时又节省了200左右

26698

我们再观察一下里面还有什么地方可以优化的

不难看出里面其实isEven和isLessThan99其实没必要单独给他每一次都赋值,我们直接给他合并到条件判断里面就好,合并后的效果如下:

contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] calldata nums) external{uint _total = total;for(uint i = 0;i<nums.length;i+=1){if(nums[i] % 2 == 0 && nums[i] < 99){_total += nums[i];}}total = _total;}
}

此时gas费用又节省了300左右

26380

我们再看看for(uint i = 0;i<nums.length;i+=1)这一段代码,i+=1实际上会将 i 的值复制到一个临时变量中,然后对 i 进行递增操作,最后再将临时变量的值返回给表达式。那有没有可以避免创建临时变量的方法呢?答案是有的:我们只需要改为++i即可

contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] calldata nums) external{uint _total = total;for(uint i = 0;i<nums.length;++i){if(nums[i] % 2 == 0 && nums[i] < 99){_total += nums[i];}}total = _total;}
}

此时的gas费用又节省了300多

26008

同样是刚才的循环,我们可以看出每一次循环中都要读取出数组的长度,这样每次循环都要执行这个方法,那么既然他的长度是不变的,我们不如直接给他存入缓存变量中。代码如下:

contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] calldata nums) external{uint _total = total;uint len = nums.length;for(uint i = 0;i<len;++i){if(nums[i] % 2 == 0 && nums[i] < 99){_total += nums[i];}}total = _total;}
}

此时gas费用又省了100多

25973

再看看循环内部的代码,我们针对循环体内数组的元素nums[i]其实可以提前复制到内存中,代码如下:

contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] calldata nums) external{uint _total = total;uint len = nums.length;for(uint i = 0;i<len;++i){uint num = nums[i];if(num % 2 == 0 && num < 99){_total += num;}}total = _total;}
}

此时gas费用又节省了200左右

25811

相关文章:

关于gas费优化问题

关于gas费优化问题 首先我们先来看一下这段代码 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract GasGolf{uint public total;//[1,2,3,4,5,100]function sum(uint[] memory nums) external{for(uint i 0;i<nums.length;i1){bool isEven nums[i] % 2…...

Linux——中断和时间管理(中)

目录 驱动中的中断处理 中断下半部 软中断 tasklet 工作队列 驱动中的中断处理 通过上一节的分析不难发现&#xff0c;要在驱动中支持中断&#xff0c;则需要构造一个 struct irqaction的结构对象&#xff0c;并根据IRQ 号加入到对应的链表中(因为 irq_des 已经在内核初始…...

嵌入式软件中常见的 8 种数据结构详解

目录 第一&#xff1a;数组 1、数组的应用 第二&#xff1a;链表 1、链表操作 2、链表的应用 第三&#xff1a;堆栈 1、堆栈操作 2、堆栈的应用 第四&#xff1a;队列 1、队列操作 2、队列的应用 第五&#xff1a;哈希表 1、哈希函数 2、哈希表的应用 第六&#…...

vue 修改当前路由参数并刷新界面

项目中经常用到的需求是在当前页面修改路由中的参数&#xff0c;并刷新页面。 我们只用this. r o u t e r . r e p l a c e 或者 t h i s . router.replace或者this. router.replace或者this.router.go是不行的&#xff0c;需配合下面的代码 方法一&#xff1a; this.$router.…...

视频处理之视频抽帧的python脚本

在计算机视觉研究中&#xff0c;处理视频的时候&#xff0c;往往需要将视频抽帧成图片。如果多个视频都存放在一个文件夹里&#xff0c;并且希望抽帧出来的图片&#xff0c;以一个视频对应一个文件夹的形式存放&#xff0c;可以用以下代码&#xff0c;抽帧频率可自己手动修改&a…...

【youcans 的 OpenCV 学习课】22. Haar 级联分类器

专栏地址&#xff1a;『youcans 的图像处理学习课』 文章目录&#xff1a;『youcans 的图像处理学习课 - 总目录』 【youcans 的 OpenCV 学习课】22. Haar 级联分类器 3. Haar 特征及其加速计算3.1 Haar 特征3.2 Haar 特征值的计算3.3 积分图像3.4 基于积分图像加速计算 Haar 特…...

如何避免知识盲区 《人生处处是修行》 读书笔记

如何避免知识盲区 多元化学习&#xff1a;不要只关注自己擅长的领域&#xff0c;应该尝试学习其他领域的知识&#xff0c;例如文学、艺术、科学等。 拓宽阅读&#xff1a;阅读不同领域的书籍、文章、博客等&#xff0c;可以帮助你了解更多的知识和观点。 参加培训和课程&…...

vue返回上一页自动刷新方式

再vue中&#xff0c;返回上一页时&#xff1a;如果页面是打开的状态&#xff0c;页面不会自动刷新&#xff0c;会保持着上次跳转的状态不更新&#xff1b; 原因&#xff1a;vue-router的切换不同于传统的页面切换&#xff0c;而是路由之间的切换&#xff0c;其实就是组件之间的…...

查询SERVER正在执行的SQL语句

--方法一 select * from master..sysprocesses SELECT distinct [Spid] session_Id, ecid, [Database] DB_NAME(sp.dbid), [User] nt_username, [Status] er.status, [Wait] wait_type, [Individual Query] SUBSTRING(qt.text, er.statement_start_offset / 2,…...

现代密码学--结课论文---《70年代公钥传奇》

摘要&#xff1a;在70年代之前&#xff0c;密码学主要被军方用于通信保护。密码学的主要研究也是由情报机构&#xff08;GCHQ、NSA等&#xff09;或IBM等企业运营的获得许可的实验室中进行。这时公众几乎无法获得密码学知识&#xff0c;直到由三位密码学家Hellman、Diffie和Mer…...

cf1348B phoenix and beauty(双指针滑动窗口的构造)

C 题面 Problem - 1348B - Codeforces 输出标准输出 凤凰网喜欢美丽的数组。如果一个数组中所有长度为k的子数组 的子数都有相同的总和&#xff0c;那么这个数组就是美丽的。一个数组的子数组是任何连续元素的序列。 凤凰网目前有一个数组a 的长度为n . 他想在他的数组中插入…...

一文读懂JAVA的hashCode方法:原理、实现与应用

目录 一、概述二、实现原理和重写规则三、如何重写hashCode方法3.1 Objects.hash()方法3.2 Apache HashCodeBuilder.3.3 Google Guava3.4 自定义哈希算法四、hashcode和equals的联系五、注意事项和建议5.1 注意事项5.2 建议六、总结一、概述 在Java中,每个对象都有一个hashCod…...

RocketMQ部署

一 安装mq 1.下载RocketMQ 本教程使⽤的是RocketMQ4.7.1版本&#xff0c;建议使⽤该版本进⾏之后的demo训练。 运⾏版&#xff1a;https://www.apache.org/dyn/closer.cgi?pathrocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip 源码&#xff1a;https://www.apache.org…...

43岁程序员,投了上万份简历都已读不回,只好把年龄改成40岁,这才有了面试机会,拿到了offer!...

40多岁找工作有多难&#xff1f; 一位43岁的程序员讲述了自己找工作的经历&#xff1a; 80年&#xff0c;大专&#xff0c;目前没到43周岁&#xff0c;年前被裁&#xff0c;简历上的年龄是42岁&#xff0c;两个多月投了上万份简历&#xff0c;99.5%是已读未回。后来改变策略把简…...

MySQL分区表相关知识总结

1.创建分区表&#xff1a; create table t(col11 int null, col22 …) engineinnodb partition by hash(col33) partitions 44; create table t(col11 int null, col22 …) engineinnodb partition by range(id) (partition p0 values less than (10), partition p1 values les…...

outlook邮箱pc/mac客户端下载 含最新版

新的 Outlook for Windows or mac 为 Outlook 应用带来了最新功能、智能辅助功能和新的新式简化设计。 你可以根据自己的风格定制它&#xff0c;并使用新的 Outlook for Windows/mac 执行更多操作&#xff01; 览版&#xff0c;与我们一起开始旅程&#xff0c;并帮助我们塑造新…...

缓存雪崩、缓存穿透、缓存击穿分别是什么?如何解决?

缓存中存放的大多都是热点数据&#xff0c;目的就是从缓存中获取数据&#xff0c;而不用直接访问数据库&#xff0c;从而提高查询效率 缓存雪崩 概念 指缓存在同一时间大面积失效&#xff0c;后面的请求直接访问数据库&#xff0c;导致数据库短时间内压力过大而崩溃&#xff…...

VBA实战篇学习笔记02 Err错误处理

文章目录 专题VI 错误处理课时38 常见错误类型错误代码13 :类型不匹配错误代码91: 对象变量或者with变量未设置错误代码1004: 视具体错误类型而变化 课时39 Err错误处理On Error Resume Next :Resume语句:Resume Next语句:未知错误:Exit SubOn Error Goto 0 专题VI 错误处理 课…...

【Git】拉取代码/提交代码

1.从将本地代码放入远程仓库 (如果有分支的情况) [git checkout xx切换分支后 git add . 将本地所有改动文件新增 commit之后 git push(将代码全部提交)] 分支操作 #查看分支 git branch #创建分支 git branch test #切换分支 git checkout test #修改代码 #提交代码git ad…...

产品预览 | 系统仿真与三维专业场仿真融合——MWORKS模型降阶工具箱

1 引言 近二十年来&#xff0c;数字化技术迅猛发展&#xff0c;以美国和中国提出装备数字工程为标志&#xff0c;人类迈入全新的数字化时代。装备数字化需要对装备的运行状态和行为进行准确的模拟和预测&#xff0c;这就需要利用系统仿真技术。系统仿真技术能够综合考虑装备的…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...