当前位置: 首页 > 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;这就需要利用系统仿真技术。系统仿真技术能够综合考虑装备的…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...