当前位置:首页 > 科技  > 软件

Go 内存分配:结构体中的优化技巧

来源: 责编: 时间:2023-11-21 09:38:46 339观看
导读在使用Golang进行内存分配时,我们需要遵循一系列规则。在深入了解这些规则之前,我们需要先了解变量的对齐方式。Golang的unsafe包中有一个函数Alignof,签名如下:func Alignof(x ArbitraryType) uintptr对于任何类型为v的

在使用Golang进行内存分配时,我们需要遵循一系列规则。在深入了解这些规则之前,我们需要先了解变量的对齐方式。gMD28资讯网——每日最新资讯28at.com

Golang的unsafe包中有一个函数Alignof,签名如下:gMD28资讯网——每日最新资讯28at.com

func Alignof(x ArbitraryType) uintptr

对于任何类型为v的变量x,AlignOf函数会返回该变量的对齐方式。我们将对齐方式记为m。现在,Golang确保m是满足变量x的内存地址 % m == 0的最大可能数,也就是说,变量x的内存地址是m的倍数。gMD28资讯网——每日最新资讯28at.com

让我们来看看一些数据类型的对齐方式:gMD28资讯网——每日最新资讯28at.com

  • byte, int8, uint8 -> 1
  • int16, uint16 -> 2
  • int32, uint32, float32, complex64 -> 4
  • int, int64, uint64, float64, complex128 -> 8
  • string, slice -> 8

对于结构体中的字段,行为可能会有所不同,详细信息请参考包的文档。gMD28资讯网——每日最新资讯28at.com

为了更好地理解结构体内存分配的情况,我们将使用unsafe包中的另一个函数Offsetof。该函数返回字段相对于结构体起始位置的位置,换句话说,它返回字段起始位置与结构体起始位置之间的字节数。gMD28资讯网——每日最新资讯28at.com

func Offsetof(x ArbitraryType) uintptr

为了更好地理解结构体内存分配,让我们以一个示例结构体为例:gMD28资讯网——每日最新资讯28at.com

type Example struct {    a int8    b string    c int8    d int32}

现在,我们将找出类型为Example的变量所占用的总内存,并尝试优化分配。gMD28资讯网——每日最新资讯28at.com

var v = Example{    a: 10,    b: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rhoncus.",    c: 20,    d: 100,}fmt.Println("字段a的偏移量:", unsafe.Offsetof(v.a)) // 输出:0fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 输出:8fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 输出:24fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 输出:28

现在,问题出现了:“为什么结构体中字段b的偏移量是8?它应该是1,因为字段a的类型是int8,只占用1个字节。”回到字符串数据类型的对齐方式,它的值为8,这意味着地址需要被8整除,因此在其中插入了7个字节的“填充”,以确保这种行为。gMD28资讯网——每日最新资讯28at.com

为什么字段c的偏移量是24?字段b中的字符串看起来比16个字节要长得多,如果字符串的偏移量是8,那么字段c的偏移量应该更大一些。gMD28资讯网——每日最新资讯28at.com

上述问题的答案是,在Go中,字符串并不是在结构体内的同一位置分配内存的。有一个单独的数据结构来保存字符串描述符,并且该字符串描述符以原地方式存储在结构体中,用于类型为string的字段,该描述符的大小为16个字节。gMD28资讯网——每日最新资讯28at.com

现在,让我们来看看unsafe包中的另一个函数Sizeof。正如其名称所示,该函数估计并返回类型为x的变量所占用的字节数。gMD28资讯网——每日最新资讯28at.com

注意:它是根据结构体中可能存在的不同大小的字段来估计大小的。gMD28资讯网——每日最新资讯28at.com

func Sizeof(x ArbitraryType) uintptr

现在,让我们来看看我们的结构体Example的大小。gMD28资讯网——每日最新资讯28at.com

fmt.Println("Example的大小:", unsafe.Sizeof(v)) // 输出:32

我们如何优化这个结构体以最小化填充呢?gMD28资讯网——每日最新资讯28at.com

为了优化这个结构体的内存,我们将查看不同数据类型的对齐方式,并尝试减少填充。让我们尝试将两个int8类型的字段放在一起。gMD28资讯网——每日最新资讯28at.com

type y struct {    a int8    c int8    b string    d int32}var v = y{}fmt.Println("字段a的偏移量:", unsafe.Offsetof(v.a)) // 输出:0fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 输出:8fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 输出:1fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 输出:24fmt.Println("Example的大小:", unsafe.Sizeof(v)) // 输出:32

太棒了,我们去掉了一些填充,但是为什么大小仍然是32?大小应该是1(a)+ 1(c)+ 6(填充)+ 16(b)+ 4(d)= 28gMD28资讯网——每日最新资讯28at.com

现在,当结构体的最后一个字段与架构的对齐要求不完全一致时,会在最后一个字段之后添加填充,以确保结构体的整体大小是其字段中最大对齐要求的倍数。因为字符串数据类型的最大对齐方式为8,所以额外添加了填充,使大小成为8的倍数,即在末尾填充了4个字节,使大小为32字节。gMD28资讯网——每日最新资讯28at.com

我们能否进一步减少填充,使其更加优化?gMD28资讯网——每日最新资讯28at.com

让我们尝试通过移动字段位置来实现。gMD28资讯网——每日最新资讯28at.com

type y struct {    b string    d int32    a int8    c int8}var v = y{}fmt.Println("字段a的偏移量:", unsafe.Offsetof(v.a)) // 输出:20fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 输出:0fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 输出:21fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 输出:16fmt.Println("Example的大小:", unsafe.Sizeof(v)) // 输出:24

我们可以看到,通过重新排列字段的位置,使得对齐需要最小化填充,我们已经将结构体的大小从32减小到24,这是内存优化的巨大进步,达到了25%。gMD28资讯网——每日最新资讯28at.com

当前的内存占用是16(b)+ 4(d)+ 1(a)+ 1(b)+ 2(填充)。gMD28资讯网——每日最新资讯28at.com

遗憾的是,由于语言和架构的限制,我们无法进一步去除填充。gMD28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-32009-0.htmlGo 内存分配:结构体中的优化技巧

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】

下一篇: 函数组件和函数式编程有关系么?

标签:
  • 热门焦点
  • 鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    华为全新的HarmonyOS 4.0操作系统将于今天下午正式登场,官方在发布会之前也已经正式给出了可升级的机型产品,这意味着这些机型会率先支持升级享用。这次的HarmonyOS 4.0支持
  • 消息称迪士尼要拍真人版《魔发奇缘》:女主可能也找黑人演员

    8月5日消息,迪士尼确实有点忙,忙着将不少动画改成真人版,继《美人鱼》后,真人版《白雪公主》、《魔发奇缘》也在路上了。据外媒消息称,迪士尼将打造真人版
  • 摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • 学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • 使用LLM插件从命令行访问Llama 2

    最近的一个大新闻是Meta AI推出了新的开源授权的大型语言模型Llama 2。这是一项非常重要的进展:Llama 2可免费用于研究和商业用途。(几小时前,swyy发现它已从LLaMA 2更名为Lla
  • WebRTC.Net库开发进阶,教你实现屏幕共享和多路复用!

    WebRTC.Net库:让你的应用更亲民友好,实现视频通话无痛接入! 除了基本用法外,还有一些进阶用法可以更好地利用该库。自定义 STUN/TURN 服务器配置WebRTC.Net 默认使用 Google 的
  • 品牌洞察丨服务本地,美团直播成效几何?

    来源:17PR7月11日,美团App首页推荐位出现“美团直播”的固定入口。在直播聚合页面,外卖“神枪手”直播间、美团旅行直播间、美团买菜直播间等均已上线,同时
  • 苹果MacBook Pro 2021测试:仍不支持平滑滚动

    据10月30日9to5 Mac 消息报道,苹果新的 14 英寸和 16 英寸 MacBook Pro 2021 上市后获得了不错的评价,亮点包括行业领先的性能,令人印象深刻的电池续航,精美丰
Top