+0和不+0的性能差异
前几日,有群友转发了某位技术大佬的weibo。并在群里询问如下两个函数哪个执行的速度比较快(weibo内容)。
func g(n int, ch chan<- int) {r := 0for i := 0; i < n; i++ {r += i}ch <- r + 0
}func f(n int, ch chan<- int) {r := 0for i := 0; i < n; i++ {r += i}ch <- r
}
很显然,g函数中ch <- r + 0 比 f函数中 ch <- r 多了一个+0
g、f的for循环都执行了n次,对r进行更新
那到底哪个快呢?我们搞了一组Benchmark测试
环境如下:
go version: 1.20
go os: windows
go arch: arm64
代码如下:
package mainimport "testing"func BenchmarkG(b *testing.B) {ch := make(chan int)N := 100000for i := 0; i < b.N; i++ {go g(N, ch)}
}func BenchmarkF(b *testing.B) {ch := make(chan int)N := 100000for i := 0; i < b.N; i++ {go f(N, ch)}
}
为了显现出性能差异,我们直接将g、f两个函数中for循环次数 N 设定为100000(十万次)。
执行结果如下
从结果可以看出:
g函数在单位时间,总共执行了167175次,每次耗时7148ns
f函数在单位时间,总共执行了71856次,每次耗时23909ns
很显然,g函数的执行效率更胜一筹
那为什么会产生这样的结果呢?
话不多说,直接上大招
使用:go tool compile -S ./main.go > dump.txt 将目标go文件的汇编写入dump.txt
下面截取了g函数的主要汇编代码
main.g STEXT size=112 args=0x10 locals=0x28 funcid=0x0 align=0x00x0000 00000 (main.go:11) TEXT main.g(SB), ABIInternal, $48-16...0x0018 00024 (main.go:11) MOVD ZR, R20x001c 00028 (main.go:11) MOVD ZR, R30x0020 00032 (main.go:13) JMP 480x0024 00036 (main.go:13) ADD $1, R2, R40x0028 00040 (main.go:14) ADD R2, R3, R30x002c 00044 (main.go:13) MOVD R4, R20x0030 00048 (main.go:13) CMP R2, R00x0034 00052 (main.go:13) BGT 360x0038 00056 (main.go:16) MOVD R3, main..autotmp_4-8(SP)0x003c 00060 (main.go:16) MOVD R1, R00x0040 00064 (main.go:16) MOVD $main..autotmp_4-8(SP), R10x0044 00068 (main.go:16) PCDATA $1, $10x0044 00068 (main.go:16) CALL runtime.chansend1(SB)0x0048 00072 (main.go:17) LDP -8(RSP), (R29, R30)0x004c 00076 (main.go:17) ADD $48, RSP0x0050 00080 (main.go:17) RET (R30)
下面截取了f函数的主要汇编代码
main.f STEXT size=112 args=0x10 locals=0x28 funcid=0x0 align=0x00x0000 00000 (main.go:3) TEXT main.f(SB), ABIInternal, $48-16...0x0018 00024 (main.go:4) MOVD ZR, main.r-8(SP)0x001c 00028 (main.go:4) MOVD ZR, R20x0020 00032 (main.go:5) JMP 520x0024 00036 (main.go:6) MOVD main.r-8(SP), R30x0028 00040 (main.go:6) ADD R2, R3, R30x002c 00044 (main.go:6) MOVD R3, main.r-8(SP)0x0030 00048 (main.go:5) ADD $1, R2, R20x0034 00052 (main.go:5) CMP R2, R00x0038 00056 (main.go:5) BGT 360x003c 00060 (main.go:8) MOVD R1, R00x0040 00064 (main.go:8) MOVD $main.r-8(SP), R10x0044 00068 (main.go:8) PCDATA $1, $10x0044 00068 (main.go:8) CALL runtime.chansend1(SB)0x0048 00072 (main.go:9) LDP -8(RSP), (R29, R30)0x004c 00076 (main.go:9) ADD $48, RSP0x0050 00080 (main.go:9) RET (R30)
对比一下
不难看出,g函数在循环结构中,只使用了R0、R2、R3、R4寄存器。
f函数在循环结构中,使用了R0、R2、R3寄存器,并在单次循环内,操作了两次栈内存
0x0024 00036 (main.go:6) MOVD main.r-8(SP), R3
将main.r-8(SP)栈内存对应的内容,加载进R3寄存器
0x002c 00044 (main.go:6) MOVD R3, main.r-8(SP)
将R3寄存器的内容写入,main.r-8(SP)栈内存
因为CPU读写内存的速度远低于读写寄存器的速度,所以在大样本量的数据驱动下,g函数的执行速度要远快于f函数的执行速度。
至于为什么出现该性能差异,究其根本,是Go编译器、优化器、对源码编译导致的,也就是编译器的黑魔法使然。
相关文章:
+0和不+0的性能差异
前几日,有群友转发了某位技术大佬的weibo。并在群里询问如下两个函数哪个执行的速度比较快(weibo内容)。 func g(n int, ch chan<- int) {r : 0for i : 0; i < n; i {r i}ch <- r 0 }func f(n int, ch chan<- int) {r : 0for …...
美颜技术讲解:视频美颜SDK的开发与集成
如今,美颜技术的应用愈发成为吸引用户的一项重要功能。本文将深入探讨视频美颜SDK的开发与集成,揭示其背后的技术原理和实现步骤。 一、美颜技术的背后 美颜技术并非仅仅是简单的滤镜效果,而是一项涉及复杂图像处理和算法的技术。在视频美颜…...
期末数组函数加强练习
前言:由于时间问题,部分题解取自网友,但都是做过的好题。 对于有些用c实现的题目,可以转化成c实现,cin看成c的读入,可以用scanf,输出cout看作printf,endl即换行符 开胃菜ÿ…...
如何下载B站视频?我来教你B站视频下载方法
如何下载B站视频?B站作为一个巨大的宝藏库,日常可以拿它作为娱乐工具,刷一些有趣新奇的短视频。也可以把它作为一款成长学习工具,具有丰富的公开课、纪录片内容。 对于较短的视频来说,花费几分钟时间看一下就结束了&am…...
AcWing 3709:单链表节点交换 ← 四川大学考研机试题
【题目来源】 https://www.acwing.com/problem/content/3712/【题目描述】 输入一个单链表,依次交换前2个数,第3、4个数,第5、6个数,…,以此类推,直到操作完整个链表。 如果链表长度是奇数,则最…...
RocketMQ源码 Broker-ConsumerFilterManager 消费者数据过滤管理组件源码分析
前言 ConsumerFilterManager 继承了ConfigManager配置管理组件,拥有将内存数据持久化到磁盘文件consumerFilter.json的能力。它主要负责,对在消费者拉取消息时,进行消息数据过滤,且只针对使用表达式过滤的消费者有效。 源码版本&…...
数据挖掘-07-航空公司客户价值分析(包括数据和代码)
文章目录 0. 数据代码下载1. 背景与挖掘目标2. 导入相关库,加载数据2.1客户基本信息分布a. 绘制会员性别比例饼图b. 绘制会员各级别人数条形图c. 绘制年龄分布图 2.2 客户乘机信息分布分析a. 绘制客户飞行次数箱线图b. 绘制客户总飞行公里数箱线图 2.3 客户积分信息…...
浏览器 css 默认的字体图表
以下是一些常见的浏览器(PC端)中网站 CSS 默认字体及其对应的字体系列(font family): 浏览器默认字体字体系列(font family)ChromeArial, sans-serif“Arial”, “Helvetica Neue”, Helvetica…...
JAVA:注册表窗口的实现
目录 题目要求: 思路大意: 窗体的实现: 窗口A: 窗口B: 窗体之间的构思: 关键代码的实现: 窗口A: 封装列表: 窗口B: 题目要求: 使用…...
Liunx Centos 防火墙操作
liunx centos 防火墙 查看防火墙状态 systemctl status firewalld查看已经开放的端口 firewall-cmd --list-ports添加端口3306 firewall-cmd --zonepublic --add-port3306/tcp --permanent重启防火墙 firewall-cmd --reload数据库开放账号可以外网登陆 mysql -u root -p …...
VirtualBox 和 Vagrant 快速安装 Centos7 报错
VirtualBox 和 Vagrant 快速安装 Centos7 报错 今天尝试用 VirtualBox 和 Vagrant 快速安装 Centos7,BUG 多多! 1)下载 6.1.26 版本 VirtualBox,Windows11 不兼容???什么鬼? 解决…...
使用Python进行数学四则运算
当我们讨论到Python中的计算问题时,我们必然涉及到加法运算符()、减法运算符(-)、乘法运算符(*)以及除法运算符(/)这四大常见的算术运算。下面,我将为您展示如…...
成都工业学院2021级操作系统专周课程设计FCFS,SSTF,SCAN,LOOK算法的实现
运行环境 操作系统:Windows 11 家庭版 运行软件:CLion 2023.2.2 源代码文件 #include <iostream> #include <vector> #include <algorithm> #include <random> using namespace std;// 生成随机数 int generateRandomNumber…...
【51单片机系列】矩阵按键扩展实验
本文对矩阵按键的一个扩展,利用矩阵按键和动态数码管设计一个简易计算器。代码参考:https://blog.csdn.net/weixin_47060099/article/details/106664393 实现功能:使用矩阵按键,实现一个简易计算器,将计算数据及计算结…...
大数据云计算——Docker环境下部署Hadoop集群及运行集群案列
大数据云计算——Docker环境下部署Hadoop集群及运行集群案列 本文着重介绍了在Docker环境下部署Hadoop集群以及实际案例中的集群运行。首先,文章详细解释了Hadoop的基本概念和其在大数据处理中的重要性,以及为何选择在Docker环境下部署Hadoop集群。接着&…...
计算机网络链路层(期末、考研)
计算机网络总复习链接🔗 目录 组帧差错控制检错编码纠错编码 流量控制与可靠传输机制流量控制、可靠传输与滑动窗口机制单帧窗口与停止-等待协议多帧滑动窗口与后退N帧协议(GBN)多帧滑动窗口与选择重传协议 介质访问控制信道划分介质访问控制…...
洛谷 P8794 [蓝桥杯 2022 国 A] 环境治理
文章目录 [蓝桥杯 2022 国 A] 环境治理题目链接题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 思路解析CODE给点思考 [蓝桥杯 2022 国 A] 环境治理 题目链接 https://www.luogu.com.cn/problem/P8794 题目描述 LQ 国拥有 n n n 个城市,从 0 0 …...
力扣面试150题 | 买卖股票的最佳时期
力扣面试150题 | 买卖股票的最佳时期 题目描述解题思路代码实现 题目描述 121.买卖股票的最佳时期 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一…...
uniapp 之 图片 视频 文件上传
<view class"" style"padding: 24rpx 0"><text>相关资料 <text class"fs-26 color-666">(图片、视频、文档不超过9个)</text> </text><view class"flex align-center" style&…...
MIT线性代数笔记-第28讲-正定矩阵,最小值
目录 28.正定矩阵,最小值打赏 28.正定矩阵,最小值 由第 26 26 26讲的末尾可知在矩阵为实对称矩阵时,正定矩阵有以下四种判定方法(都是充要条件): 所有特征值都为正左上角所有 k k k阶子矩阵行列式都为正&…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
