关于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是在函数内部声明的临时变量的存储位置。
使用calldata比memory更能节省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 工作队列 驱动中的中断处理 通过上一节的分析不难发现,要在驱动中支持中断,则需要构造一个 struct irqaction的结构对象,并根据IRQ 号加入到对应的链表中(因为 irq_des 已经在内核初始…...
嵌入式软件中常见的 8 种数据结构详解
目录 第一:数组 1、数组的应用 第二:链表 1、链表操作 2、链表的应用 第三:堆栈 1、堆栈操作 2、堆栈的应用 第四:队列 1、队列操作 2、队列的应用 第五:哈希表 1、哈希函数 2、哈希表的应用 第六&#…...
vue 修改当前路由参数并刷新界面
项目中经常用到的需求是在当前页面修改路由中的参数,并刷新页面。 我们只用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是不行的,需配合下面的代码 方法一: this.$router.…...
视频处理之视频抽帧的python脚本
在计算机视觉研究中,处理视频的时候,往往需要将视频抽帧成图片。如果多个视频都存放在一个文件夹里,并且希望抽帧出来的图片,以一个视频对应一个文件夹的形式存放,可以用以下代码,抽帧频率可自己手动修改&a…...
【youcans 的 OpenCV 学习课】22. Haar 级联分类器
专栏地址:『youcans 的图像处理学习课』 文章目录:『youcans 的图像处理学习课 - 总目录』 【youcans 的 OpenCV 学习课】22. Haar 级联分类器 3. Haar 特征及其加速计算3.1 Haar 特征3.2 Haar 特征值的计算3.3 积分图像3.4 基于积分图像加速计算 Haar 特…...
如何避免知识盲区 《人生处处是修行》 读书笔记
如何避免知识盲区 多元化学习:不要只关注自己擅长的领域,应该尝试学习其他领域的知识,例如文学、艺术、科学等。 拓宽阅读:阅读不同领域的书籍、文章、博客等,可以帮助你了解更多的知识和观点。 参加培训和课程&…...
vue返回上一页自动刷新方式
再vue中,返回上一页时:如果页面是打开的状态,页面不会自动刷新,会保持着上次跳转的状态不更新; 原因:vue-router的切换不同于传统的页面切换,而是路由之间的切换,其实就是组件之间的…...
查询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年代公钥传奇》
摘要:在70年代之前,密码学主要被军方用于通信保护。密码学的主要研究也是由情报机构(GCHQ、NSA等)或IBM等企业运营的获得许可的实验室中进行。这时公众几乎无法获得密码学知识,直到由三位密码学家Hellman、Diffie和Mer…...
cf1348B phoenix and beauty(双指针滑动窗口的构造)
C 题面 Problem - 1348B - Codeforces 输出标准输出 凤凰网喜欢美丽的数组。如果一个数组中所有长度为k的子数组 的子数都有相同的总和,那么这个数组就是美丽的。一个数组的子数组是任何连续元素的序列。 凤凰网目前有一个数组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版本,建议使⽤该版本进⾏之后的demo训练。 运⾏版:https://www.apache.org/dyn/closer.cgi?pathrocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip 源码:https://www.apache.org…...
43岁程序员,投了上万份简历都已读不回,只好把年龄改成40岁,这才有了面试机会,拿到了offer!...
40多岁找工作有多难? 一位43岁的程序员讲述了自己找工作的经历: 80年,大专,目前没到43周岁,年前被裁,简历上的年龄是42岁,两个多月投了上万份简历,99.5%是已读未回。后来改变策略把简…...
MySQL分区表相关知识总结
1.创建分区表: 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 应用带来了最新功能、智能辅助功能和新的新式简化设计。 你可以根据自己的风格定制它,并使用新的 Outlook for Windows/mac 执行更多操作! 览版,与我们一起开始旅程,并帮助我们塑造新…...
缓存雪崩、缓存穿透、缓存击穿分别是什么?如何解决?
缓存中存放的大多都是热点数据,目的就是从缓存中获取数据,而不用直接访问数据库,从而提高查询效率 缓存雪崩 概念 指缓存在同一时间大面积失效,后面的请求直接访问数据库,导致数据库短时间内压力过大而崩溃ÿ…...
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 引言 近二十年来,数字化技术迅猛发展,以美国和中国提出装备数字工程为标志,人类迈入全新的数字化时代。装备数字化需要对装备的运行状态和行为进行准确的模拟和预测,这就需要利用系统仿真技术。系统仿真技术能够综合考虑装备的…...
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符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: 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 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: 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日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
