Golang 简单的数据对齐可提高程序速度和内存使用率

这篇具有很好参考价值的文章主要介绍了Golang 简单的数据对齐可提高程序速度和内存使用率。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Golang 中的结构或 struct 是用户定义的类型,允许将可能不同类型的项分组/组合为单一类型。
可以说是一个不支持继承但支持组合的轻量级类。
我们使用 Golang 编写代码的时候,你肯定使用过struct
但是,你可能不知道的是,通过简单地重新排序结构中的字段,可以极大地提高 Go 程序的速度和内存使用率!

示例演示

type EmployeeStruct struct {
	IsPublic bool
	Age      int64
	Status   bool
	Name     string
	Image    float32
}

我们来看一下Employee结构体的内存大小:

  • IsPublic(boolean) 1 字节
  • Age(int64) 8 字节
  • Status(boolean) 1 字节
  • Name(string) 16 字节
  • Image(float32) 4 字节

总计: 30 字节

通过unsafe.Sizeof检查一下:

package main

import (
	"fmt"
	"unsafe"
)

type EmployeeStruct struct {
	IsPublic bool
	Age      int64
	Status   bool
	Name     string
	Image    float32
}

func main() {
	var employee EmployeeStruct
	fmt.Println(unsafe.Sizeof(employee))
}

执行后输出: 48字节,为什么呢?

处理器类型

我们知道CPU 分为32位、34位,但是,它是如何运作的呢?

想象一下我们有一个 64 位的 CPU,每个时钟周期传输 64 位数据的能力。

时钟周期是CPU处理一个信息需要多少时间,CPU 32位在1个周期内转换4字节数据,CPU 64位在1个周期内转换8字节数据(32位= 4字节,64位= 8字节)

上面我们定义的EmployeeStruct结构体,并且计算得到了每个字段在内存中占用的字节数。下面我们看CPU处理信息需要多少时间呢?
先来看下面的一张图:

图里面6个周期,每个周期有八个盒子,表示是CPU处理能力,为 8 字节

  • 周期1
    第一个属性是IsPublic,数据类型为布尔型bool 的大小为 1 个字节。因此,当前周期 1 由属性IsPublic(bool ~ 1 byte)填充。
    下一个属性是Age,数据类型为int64,int64的大小是8字节,由于第1个周期的剩余内存大小只有7个字节,因此第1个周期无法填充Age属性,因此,会进入第2个周期,但是,“剩余的空间呢,怎么办?”。

  • 周期2
    第2个周期由Age属性填充,数据类型为int64,大小为8字节,刚好填充满。

  • 周期3
    第三个属性Status,数据类型为bool,大小为1字节,填充(bool~1 byte),剩余内存大小为7字节,然后,下一个属性是Name,类型为字符串,大小为 16 字节,与周期1的情况相同,因为没有足够的空间容纳下一个属性,所以将在下一个周期中进入。所以意味着有7个字节的内存被浪费了

  • 周期 4 和周期 5
    第四个是Name,数据类型为字符串,大小为16字节。从图上面看,它将在两个周期中填充,周期 4 中填充 8 个字节,周期 5 中填充 8 个字节。

  • 周期6
    最后一个属性是Image, 数据类型为float32,大小为4字节,浪费剩余的 4 个字节

最后通过计算统计:

总时钟周期 = 6 个时钟周期
结构体大小 = 48 字节
浪费的总内存 = 18 字节

所以我们在开发的时候,如果对于一个比较大的数据结构体来说,可能会使结构体的大小变得更大。

那么,如何解决呢?

实际上我们可以根据数据类型的大小来组成序列,最简单的方法是:

按元素内存大小的降序排列字段

type EmployeeStruct struct {
	Name     string
	Age      int64
	Image    float32
	IsPublic bool
	Status   bool
}

这个时候我们再来看一下时间周期:

  • 周期 1 和周期 2
    第一个属性是Name,数据类型为字符串,大小为16字节。因此,它将在两个周期中填充,周期 1 中填充 8 个字节,周期 2 中填充 8 个字节。

  • 周期3
    第3个周期由Age属性填充,数据类型为int64,大小为8字节

  • 周期4
    下一个属性是Image,数据类型为float32,大小为4字节。因此,当前周期 4 由属性 Image ( float32 ~ 4 字节)填充,剩余大小为 4 字节。

下一个属性是IsPublic(bool ~ 1 字节)和 Status(bool ~ 1 字节)。因为最后两个属性的总大小只有2个字节,所以我们可以将其放在循环4中。这样一来,循环4就被Image ( float32 ~ 4字节)、IsPublic (bool ~ 1字节)、Status(bool~1 字节)填满了,仅浪费 2 字节内存。

最后通过计算统计:

总时钟周期 = 4 个时钟周期
结构体大小 = 32 字节
浪费的总内存 = 2 字节

package main

import (
	"fmt"
	"unsafe"
)

type EmployeeStruct struct {
	Name     string
	Age      int64
	Image    float32
	IsPublic bool
	Status   bool
}

func main() {
	var employee EmployeeStruct
	fmt.Println(unsafe.Sizeof(employee)) // output: 32
}

结束

所以我们在开发的时候,重新排序结构字段是可以提高应用程序的内存使用率和运行速度的。

转载:风向阅读 - Golang 开发技巧 - 简单的数据对齐可提高程序速度和内存使用率
地址:https://www.aiweimeng.top/archives/56.html文章来源地址https://www.toymoban.com/news/detail-505834.html

到了这里,关于Golang 简单的数据对齐可提高程序速度和内存使用率的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • golang内存对齐

    golang内存对齐

    CPU访问内存时,以CPU的位数为单位进行访问。 如果访问未对齐的内存,处理器需要做两次内存访问,对齐的内存的访问可能仅需要一次,利用内存对齐后提升读取速度。 golang结构体内存对齐规则 在代码编译阶段,编译器会对数据的存储布局进行对齐优化。 对于golang结构体来

    2024年02月13日
    浏览(4)
  • Golang学习之结构体和内存对齐、map设计思路

    Golang学习之结构体和内存对齐、map设计思路

    cpu要想从内存读取数据,需要通过地址总线,把地址传输给内存,内存准备好数据,输出到数据总线,交给CPU。 如果地址总线只有8根,那这个地址就只有8位,可以表示256个地址,因为表示不了更多的地址就用不了更大的内存。 所以256就是8根地址总线最大的寻址空间,要使

    2024年02月16日
    浏览(9)
  • python系统监控程序 时间 CPU内存使用率 硬盘大小 天气 日历
  • C语言之结构体内存对齐与内存的简单理解

    C语言之结构体内存对齐与内存的简单理解

    文章目录 内存单元的理解 结构体中内存对齐的规则 为什么会存在内存对齐 首先先要介绍一下C语言中一些常见的存储单元     bit       存放一个二进制位     Byte   1Byte = 8 bit     KB     1KB   = 1024 Byte     MB     1MB   = 1024 KB     GB     1GB   = 1024 MB     TB 

    2023年04月26日
    浏览(10)
  • Python 获取windows下硬件数据信息(CPU,内存,英特尔、英伟达、AMD显卡使用率及详细信息)

    Python 获取windows下硬件数据信息(CPU,内存,英特尔、英伟达、AMD显卡使用率及详细信息)

    前言:最近一直在做关于显卡数据采集的调研工作,也在github上看到了一些三方库比如Python和golang的psutil, python: gpustart,再或者通过wmi或者windowsApi等底层接口 但是都只能获取到显卡的名称以及厂家信息等 无法真正意义上获取到显卡占用率等数据 在或者只能获取到英伟达的显卡

    2024年02月16日
    浏览(20)
  • Oracle 如何提高空间使用率?

    Oracle 如何提高空间使用率?

    oracle尽量保证一行的数据能够放在同一个数据块当中,有的时候行会发生行迁移和行链接。 行链接 :有一个列的字段是大对象(long,longlong)一行占的数据一整个块都放不下,则oracle会把这行的数据分为两部分或多部份,存放到不同的数据块,这种现象叫做行链接。 行链接

    2024年02月21日
    浏览(8)
  • YOLOv7如何提高目标检测的速度和精度,基于模型结构、数据增强提高目标检测速度
  • 高频golang面试题:简单聊聊内存逃逸?

    高频golang面试题:简单聊聊内存逃逸?

    知道golang的内存逃逸吗?什么情况下会发生内存逃逸? golang程序变量会携带有一组校验数据,用来证明它的整个生命周期是否在运行时完全可知。如果变量通过了这些校验,它就可以在栈上分配。否则就说它 逃逸 了,必须在堆上分配。 能引起变量逃逸到堆上的典型情况:

    2024年02月09日
    浏览(11)
  • 汽车数据解决方案:通过更好的数据提高速度

    无论您是负责数字化转型的 CIO 或 IT 团队,还是实施 IoT 和 AI 洞察的工厂经理,或者是管理复杂数据管道的 ADAS 和无人驾驶团队,我们都可以帮您在数据发展曲线上保持领先。 全球数字化浪潮下,传统汽车行业生产模式、制造模式、服务模式,面临着前所未有的挑战,中国传

    2024年01月24日
    浏览(13)
  • Redis内存使用率高,内存不足问题排查和解决

    Redis内存使用率高,内存不足问题排查和解决

    表面现象是系统登录突然失效,排查原因发现,使用redis查询用户信息异常,从而定位到redis问题 我的redis使用的是华为云的redis分布式缓存服务,所以在问题排查方面,我们可以结合华为云提供的丰富的分析诊断工具来辅助排查解决问题。 1、问题定位到redis上,登陆redis服务

    2024年02月03日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包