blog
blog copied to clipboard
Go 逃逸分析 | Go 语言高性能编程 | 极客兔兔
https://geektutu.com/post/hpg-escape-analysis.html
Go 语言/golang 高性能编程,Go 语言进阶教程,Go 语言高性能编程(high performance go)。介绍了 Go 内存分配逃逸分析(escape analysis)的几种典型场景,变量所使用的内存什么时候分配到栈上,什么时候分配到堆上。以及如何利用逃逸分析的原理优化代码的性能,例如传值 VS 传指针。
Go 语言使用的是标记清除算法,并且在此基础上使用了三色标记法和写屏障技术,提高了效率。可以再开一篇详细介绍GC的专题问题吗?
2.4 栈空间不足
不包含切片内部字段占用的内存大小。 创建了大小为 8192 的 int 型切片,恰好占用 64 KB
文章提到切片的实际内存占用还包括 Len、Cap 为什么 8192 个 int 就导致逃逸了呢?
@lisgroup 这是表面测试的现象,很可能代码中只对底层数组的大小做了判断。这一块具体的实现还没看到。
测试目标:返回指针与返回值性能对比
测试方式:基准测试,返回结构体
测试次数:10+
测试结果:返回的数据量越大使用返回值形式,性能更好约10%-30%,各指数也比反回指针方式低那么一点
分析:返回值方式,内存分配到栈,而指针是分配到堆,频繁在堆上创建回收GC性能比内存拷贝性能低。估计可能是:在对象频繁创建和删除的场景下,传递指针导致的 GC 开销可能会严重影响性能。
但我把一个变量赋值给返回值的属性时,逃逸分析时看到这个变量是逃逸到了堆?返回值时存分配2次,而返回指针的方式内存分配3次?
@geektutu @lisgroup 这是表面测试的现象,很可能代码中只对底层数组的大小做了判断。这一块具体的实现还没看到。
大佬,想继续请教一下,看结果这个 8192 字节只是 slice 底层数组的占用量,在runtime/slice.go 中 slice 定义有三个字段的,想问问 slice 在底层是怎么分配空间的
type slice struct {
array unsafe.Pointer
len int
cap int
}
“一般情况下,对于需要修改原对象值,或占用内存比较大的结构体,选择传指针。对于只读的占用内存较小的结构体,直接传值能够获得更好的性能。”
请教下,这占用内存较小的标准是? 占用多少内存算小呢?
GO1.17 我执行代码 interface参数并没有出现逃逸现象
还有一种情况,变量大小不确定时也会发生逃逸。
文章写得挺好的,赞! 但是有一点,8192为啥是64KB,怎么算出来的
@yangfx15 文章写得挺好的,赞! 但是有一点,8192为啥是64KB,怎么算出来的
int 在 64 位机器是 int64,占 8 byte,8*8192/1024 = 64Kb