Golang数据结构性能优化实践

仅仅通过对struct字段重新排序,优化内存对齐方式,就可以获得明显的内存和执行效率提升。原文: How to Speed Up Your Struct in Golang

Mike @Pexels
Mike @Pexels

如果你有Golang开发经验,一定定义过struct类型。

但可能你不知道,通过简单的重新排序struct字段,可以极大提高Go程序的速度和内存使用效率!

是不是难以置信?我们一起来看一下吧!

简单Demo
type BadStruct struct {
 age         uint8
 passportNum uint64
 siblings    uint16
}

type GoodStruct struct {
 age         uint8
 siblings    uint16
 passportNum uint64
}

在上面的代码片段中,我们创建了两个具有相同字段的结构体。然后编写一个简单程序分别输出其内存使用情况。

// Output
Bad struct is 24 bytes long
Good struct is 16 bytes long

如你所见,它们在内存使用方面并不一样。

是什么原因导致两个完全相似的struct消耗的内存不同?

答案在于数据在计算机内存中的排列方式。

简而言之,数据结构对齐。

数据结构对齐
SHVETS production @Pexels
SHVETS production @Pexels

CPU以字(word)为单位读取数据,而不是字节(byte)。

64位系统中,一个word是8个字节,而32位系统中,一个word是4个字节。

简而言之,CPU以其字长的倍数读取内存地址。

alt

想象一下,在64位系统中,为了获取变量passportNum,CPU需要两个周期来访问数据。

第一个周期将获取内存的0到7字节,下一个周期获取其余内存字节。

把它想象成一个笔记本,每页只能存储一个字大小的数据(在本例中为8字节)。如果passportNum分散在两个页,则需要两次读取才能检索到完整的数据。

非常低效。

因此需要数据结构对齐,让计算机将数据存储在等于数据大小倍数的地址上。

4字节数据只能从内存地址0或4开始
4字节数据只能从内存地址0或4开始

例如,2字节数据可以存储在内存0、2或4中,而4字节数据可以存储在内存0、4或8中。

alt

通过简单的对齐数据,计算机确保可以在一个CPU周期内检索到变量passportNum

数据结构填充
Angela Roma @Pexels
Angela Roma @Pexels

填充是实现数据对齐的关键。

计算机通过在数据结构之间填充额外的字节,从而对齐字段。

这就是额外内存的来源!

我们来回顾一下BadStructGoodStruct

alt

GoodStruct消耗更少的内存,仅仅因为与BadStruct相比,其struct字段顺序更合理。

由于填充,两个13字节的数据结构分别变成了16字节和24字节。

因此,可以仅仅通过对struct字段重新排序来节省额外的内存!

这种优化为什么重要?

问题来了,你为什么要关心这个?

两个方面,速度和内存使用。

我们做一个简单的基准测试来证明!

func traverseGoodStruct() uint16 {
 var arbitraryNum uint16
  
 for _, goodStruct := range GoodStructArr {
  arbitraryNum += goodStruct.siblings
 }
  
 return arbitraryNum
}

func traverseBadStruct() uint16 {
 var arbitraryNum uint16
  
 for _, badStruct := range BadStructArr {
  arbitraryNum += badStruct.siblings
 }
  
 return arbitraryNum
}

func BenchmarkTraverseGoodStruct(b *testing.B) {
 for n := 0; n < b.N; n++ {
  traverseGoodStruct()
 }
}

func BenchmarkTraverseBadStruct(b *testing.B) {
 for n := 0; n < b.N; n++ {
  traverseBadStruct()
 }
}

GoodStructBadStruct进行基准测试的方法是循环遍历数组,并将struct字段累加到变量中。

alt

从结果中可以看出,遍历GoodStruct确实比BadStruct花费时间更少。

对struct字段重排序可以优化应用程序的内存使用和速度。

想象一下,维护一个具有大量结构体的大型应用程序,改变将会更为明显。

结语

好了,全文到此为止,我们以一个简单的行动呼吁来结束:

一定要对struct结构字段进行重排序!


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/358201.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据据库八之 视图、触发器、事务

【零】数据准备 【1】创建表 &#xff08;1&#xff09;部门表 d_id是部门的编号d_name是部门的名字 # 确保表不存在 drop table if exists department; # 创建表 create table department( d_id int auto_increment primary key, d_name varchar(6) )auto_increment 501 …

【linux|java应用报错】Cannot allocate memory

启动一个java应用报Cannot allocate memory&#xff0c;并且会生产一个hs_ess_pid.log文件。 文件内容为&#xff1a; #内存不足&#xff0c;Java运行时环境无法继续。 #本机内存分配&#xff08;mmap&#xff09;无法映射4294967296字节以提交保留内存。 【排查】 1、尝试使…

Mysql-事务(隔离级别,事务底层原理,MVCC)

什么是事务&#xff1f;有哪些特性&#xff1f; 事务&#xff1a;事务指的是逻辑上的一组操作&#xff0c;组成这组操作的各个单元要么全都成功&#xff0c;要么全都失败。 事务特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a; 原子性是指事务是一个不…

Python tkinter (11) —— Frame控件

本文主要是Python tkinter Frame框架控件介绍及使用简单示例。 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— Button标签 Python tkinter (3) —— Entry标签 Python tkinter (4) —— Text控件 Python tkint…

大健康行业千城万企信用建设工作启动大会在京召开

9月19日&#xff0c;为响应商务部、中宣部、国家发改委等13个部门共同举办的“诚信兴商宣传月”活动&#xff0c;中国国际电子商务中心所属北京国富泰信用管理有限公司联合北京华商国医堂集团及旗下东方岐黄商学院&#xff0c;北京华商国医堂中医药研究院举办的共筑信用月&…

Mov转MP4怎么转换?如何播放mov视频?

MOV文件格式的使用场景 MOV文件格式以其支持多种媒体数据类型的特性而闻名&#xff0c;包括视频、音频、文本、动画等。它常用于存储包含视频剪辑、电影、音频轨道等多媒体元素的文件。由于其在质量和编辑方面的优越性&#xff0c;MOV文件在电影制作、广告宣传、多媒体演示等领…

阿里二面:SpringBoot同时可以处理多少个请求?直接懵了。。。

SpringBoot以其简洁高效的开发方式和强大的内嵌容器特性&#xff0c;为开发者提供了构建高性能后端服务的便利。然而&#xff0c;当面临高并发场景时&#xff0c;理解并合理配置Spring Boot应用以达到最佳的并发处理能力至关重要。在Spring Boot中&#xff0c;应用程序对HTTP请…

Docker最新超详细版教程通俗易懂(基础版)

Docker概述 概念&#xff1a;容器虚拟化技术&#xff0c;系统平滑移植&#xff0c;解决了运⾏环境和配置问题的软件容 器&#xff0c;⽅便做持续集成并有助于整体发布的容器虚拟化技术 意义&#xff1a;Docker的出现使得Docker得以打破过去程序即应⽤的观念&#xff0c;透过…

Flink中的时间语义和TTL

时间语义 事件时间&#xff08;Event Time&#xff09; 事件时间是数据生成的时间&#xff0c;是数据流中每个元素或者每个事件自带的时间属性&#xff0c;一般是事件发生的时间&#xff0c;在实际项目中作为前端的一个属性嵌入。在理想情况下&#xff0c;数据应当按照事件时…

TeX:一款功能强大的Telegram安全监控与管理工具

关于TeX TeX是一款功能强大的Telegram安全监控与管理工具&#xff0c;该工具专为Telegram设计&#xff0c;可以实现针对Telegram的安全监控与管理。 TeX旨在帮助安全研究人员、调查人员和执法人员收集和处理针对网络犯罪分子的取证信息&#xff0c;其中包括网络犯罪、欺诈攻击…

vue3-深入组件-透传属性

透传属性 &#xff08;透传 attribute&#xff09; 什么是透传属性&#xff08;透传 attribute&#xff09;? 传递给一个组件&#xff0c;却没有被该组件声明为 props 或 emits 的 attribute 或者是事件监听器&#xff0c;例如 class style id 等。 属性继承 当一个组件以单…

STM32 1-5

目录 STM32简介 点亮PC13LED GPIO LED闪烁 LED流水灯 按键控制LED 光敏传感器控制蜂鸣器 OLED调试工具 OLED显示 EXTI外部中断 对射式红外传感器计次 旋转编码器计次 继续 STM32简介 点亮PC13LED main.c #include "stm32f10x.h" // D…

【linux】复制cp和硬连接、软连接的区别? innode 关系?

1.命令&#xff1a; cp -r [源文件或目录] [目的目录] #复制 ln -s [被链接的文件] [链接的目录/名称] #软连接 ln [被链接的文件] [链接的目录/名称] #硬连接 注&#xff1a;cp -r 会把所有source当作普通文件&#xff08;regular文件&#xff09;&#x…

代码随想录算法训练营第35天 | 860.柠檬水找零 406.根据身高重建队列 452.用最少数量的箭引爆气球

柠檬水找零 局部最优&#xff1a;收到20元时优先找零10元5元&#xff0c;不够再找零3个5元&#xff0c;因为5元可以找零20和10&#xff0c;更有用。全局最优&#xff1a;完成所有的找零。 class Solution { public:bool lemonadeChange(vector<int>& bills) {int fi…

Flink问题解决及性能调优-【Flink rocksDB读写state大对象导致背压问题调优】

RocksDB是Flink中用于持久化状态的默认后端&#xff0c;它提供了高性能和可靠的状态存储。然而&#xff0c;当处理大型状态并频繁读写时&#xff0c;可能会导致背压问题&#xff0c;因为RocksDB需要从磁盘读取和写入数据&#xff0c;而这可能成为瓶颈。 遇到的问题 Flink开发…

多线程编程3——线程的状态

一、状态是线程的状态 状态是PCB中与调度相关的属性&#xff0c;线程是CPU调度执行的基本单位。所以&#xff0c;状态是线程的属性。谈到状态&#xff0c;考虑的都是线程的状态&#xff0c;不是进程&#xff01;&#xff01;&#xff01; 二、在Java中&#xff0c;线程的状态…

作业车间调度问题:P还是NP

获取更多资讯&#xff0c;赶快关注上面的公众号吧&#xff01; 文章目录 基本概念多项式时间指数时间 P问题&#xff08;多项式问题&#xff09;NP问题&#xff08;非确定性多项式问题&#xff09;暴力穷举法动态规划 P与NP关系&#xff1a;作业车间调度问题是典型的NP难问题 …

将vite项目(vue/react)使用vite-plugin-pwa配置为pwa应用,只需要3分钟即可

将项目配置为pwa模式&#xff0c;就可以在浏览器里面看到安装应用的选项&#xff0c;并且可以将web网页像app一样添加到手机桌面或者pad桌面上&#xff0c;或者是电脑桌面上&#xff0c;这样带来的体验就像真的在一个app上运行一样。为了实现这个目的&#xff0c;我们可以为vue…

vue3-hand-mobile

当我写完手势移动事件后&#xff0c;我又通过svg的方法添加了一段文字和polygon。当我在这个蓝色的polygon上滑动手势的时候&#xff0c;会报错。 可能这个bug只是我个人的代码导致的。但是我觉得vue3-hand-mobile插件的这一段代码写的有问题。 我通过circular-json库修复了这…

vite+vue3+ts项目上线docker 配置反向代理API

这次重点的坑是反向代理。 1。项目中配置代理&#xff0c;为了跨域请求数据 项目根目录中新建vite.config.ts文件 在文件中添加配置代理 注意&#xff1a;其中 /api 和target 的地址后面没有 / 2。在项目根目录中新建Httprequest.ts文件&#xff0c;引入axios&#xff0c;并…