go 内存分配优化

函数传参使用结构体指针还是结构体?

  • 如果函数不需要修改原始数据,并且数据量较小,建议使用值传递
  • 如果函数需要修改原始数据,或者数据量较大,建议使用指针传递

大量创建复杂对象如何优化?

哪一种初始化方式更好?

go 复制代码
type MyStruct strcut{
    A int
    ...
 }
 
 // 需要构建一个 []*MyStruct
 
// 方式一
// 优点: 申请内存次数为 批量申请内存比多次申请内存效率高
// 缺点: 由于elem申请的是连续的一片内存,任何一个元素被引用,elem都无法释放
arr := make([]*MyStruct, size)
elem = make([]MyStruct, size)
for i := 0; i < size; i++ {
    m[i] = &elem[i]
}

// 方式二
// 缺点: 申请内存次数为 1 + size次
arr:=make([]*MyStruct, size)
for i := 0; i < size; i++ {
    arr[i] = &MyStruct{}
}

结构体体字段定义成基本类型还是指针类型?

go 复制代码
// 内存占用 4个字节
type MyStruct strcut{
    A int
 }
 
 // // 内存占用 8个字节
 type MyStructPoint strcut{
    A *int
 }
  • 指针类型内存占用比基本类型大,所以应该少用指针
  • GC会扫描所有的指针字段, 所以使用MyStructPoint方式定义容易加重GC扫描负担

常驻内存需要维护一个只读mapstringany,有没有优化手段?

由于 go底层字符串的实现会包含一个指针,大量的字符串持有会 加重GC扫描负担 优化思路: 将所有的字符串都保存在byte数组中

go 复制代码
type StringHeader struct {
    Data uintptr
    Len  int
}

cloudwego 中的实现

go 复制代码
// StrMap represents GC friendly readonly string map implementation.
// type V must NOT contain pointer for performance concern.
type StrMap[V any] struct {
	// `data` holds bytes of keys
	data []byte

	// `items` holds key meta
	items []mapItem[V]

	// max hashtable ~ 2 billions which means len(items) < the num as well.
	hashtable []int32 // using int32 for mem efficiency

	// for maphash
	seed maphash.Seed
}

type mapItem[V any] struct {
	off  int
	sz   uint32 // 4GB, big enough for key
	slot uint32
	v    V
}

如何看逃逸分析

在 Go 语言里,逃逸分析这一重要任务是由编译器负责完成的。它会在编译阶段就进行细致的分析,以此来确定变量究竟该分配到栈上,还是堆上,此过程对程序的正常运行和性能表现起着关键作用。

从性能优化的角度考虑,我们要尽可能地减少堆上的内存分配。因为在堆上进行内存分配和回收操作的开销相对较大,会涉及到垃圾回收机制的频繁介入,这会消耗更多的系统资源和时间。所以,合理利用逃逸分析的结果,将变量分配到合适的内存区域,能有效提升程序的整体性能。

可以通过以下编译选项展示变量逃逸的情况,帮助代码优化:

bash 复制代码
go build -gcflags=-m main.go
相关推荐
高频因子挖掘机5 分钟前
实时行情为什么不应该逐只股票请求?批量查询与标的池管理实践
后端·github·api
程序猿DD5 小时前
OctaFuse Gateway 2.15.0:MCP 聚合、向量 Embeddings 与官方目录同步
后端·agent
程序员Sunday8 小时前
TypeScript 的 any、unknown、never 有什么区别?
前端·面试·typescript
余槐i8 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8268 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡8 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
凤山老林9 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne10 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF10 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
pride.li11 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉