Golang Go语言中怎么优雅地计算结构占用的内存大小

发布于 1周前 作者 sinazl 来自 Go语言

Golang Go语言中怎么优雅地计算结构占用的内存大小

由于最近我的 filebeat 频繁地 out of memory 。filebeat 只能限制 queue 条数,而不能限制 cache 内存大小,准备小小改造一下

type common.MapStr map[string]interface{}

type EventCache struct {
	m common.MapStr
}

type EventFlags uint8

type beat.Event struct {
	Timestamp  time.Time
	Meta       common.MapStr
	Fields     common.MapStr
	Private    interface{} // for beats private use
	TimeSeries bool        // true if the event contains timeseries data
}

type Event struct {
	Content beat.Event
	Flags   EventFlags
	Cache   EventCache
}

想请问下怎么在运行时优雅地计算 Event 这个结构所占用的内存大小,看到说 unsafe.sizeof 有很多问题,还说这个只是在编译时计算。 不优雅也行,野蛮点也可以。。。


更多关于Golang Go语言中怎么优雅地计算结构占用的内存大小的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

https://pkg.go.dev/runtime?tab=doc#ReadMemStats
直接定时获取一下已申请内存大小

更多关于Golang Go语言中怎么优雅地计算结构占用的内存大小的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这个好像不错,先安排上,多谢

这是 go 的内存布局相关的内容,我之前也查过一些资料,可以看这里: https://www.flysnow.org/2017/07/02/go-in-action-unsafe-memory-layout.html
结合 google 还有更多资料。

B 站 go 夜读 是说 go 源码的,最近的一期就是聊这个内存对齐 可以参考下

野蛮路子:运行时创建 1G 个该类型的值,观察内存占用

这方法我还真用过两次,拿来猜闭源软件里的一些功能是如何实现的

只是为了避免 out of memory,可以考虑直接获取进程的 rss 值

在Golang(Go语言)中,优雅地计算结构体占用的内存大小通常使用标准库中的unsaferuntime包。虽然Go语言本身不直接提供计算结构体内存占用的函数,但结合这两个包可以实现这个功能。

  1. 使用unsafe.Sizeofunsafe.Sizeof函数返回操作数在内存中的大小,以字节为单位。这是最直接的方法,但它只计算结构体本身的内存占用,不包括其字段指向的动态内存(如切片、映射、指针指向的数据)。

  2. 考虑动态内存: 对于包含指针的结构体,要准确计算其总内存占用,需要遍历指针并计算指向的数据的内存大小。这通常需要对结构体的每个字段进行类型检查和递归计算。

  3. 使用runtime.MemStatsruntime.MemStats提供了程序运行时内存分配的各种统计信息,但它不提供直接计算结构体内存大小的功能。它更多地用于监控内存使用情况。

  4. 编写通用函数: 可以编写一个通用的函数,利用反射(reflect包)来遍历结构体的字段,并使用unsafe.Sizeof计算每个字段的大小。对于指针类型,递归调用该函数以计算动态内存。

  5. 注意事项: 计算结构体内存大小时,要考虑到内存对齐和填充(padding),这些由编译器决定,并可能影响最终的计算结果。

总之,通过结合unsaferuntimereflect包,可以编写一个相对优雅且准确的函数来计算Go语言中结构体的内存占用。

回到顶部