geektutu / blog

极客兔兔的博客,Coding Coding 创建有趣的开源项目。
https://geektutu.com
Apache License 2.0
166 stars 21 forks source link

Go 逃逸分析 | Go 语言高性能编程 | 极客兔兔 #120

Open geektutu opened 3 years ago

geektutu commented 3 years ago

https://geektutu.com/post/hpg-escape-analysis.html

Go 语言/golang 高性能编程,Go 语言进阶教程,Go 语言高性能编程(high performance go)。介绍了 Go 内存分配逃逸分析(escape analysis)的几种典型场景,变量所使用的内存什么时候分配到栈上,什么时候分配到堆上。以及如何利用逃逸分析的原理优化代码的性能,例如传值 VS 传指针。

lisgroup commented 3 years ago

Go 语言使用的是标记清除算法,并且在此基础上使用了三色标记法和写屏障技术,提高了效率。可以再开一篇详细介绍GC的专题问题吗?

lisgroup commented 3 years ago

2.4 栈空间不足

不包含切片内部字段占用的内存大小。 创建了大小为 8192 的 int 型切片,恰好占用 64 KB 文章提到切片的实际内存占用还包括 Len、Cap 为什么 8192 个 int 就导致逃逸了呢?

geektutu commented 3 years ago

@lisgroup 这是表面测试的现象,很可能代码中只对底层数组的大小做了判断。这一块具体的实现还没看到。

nFreeMason commented 2 years ago

测试目标:返回指针与返回值性能对比 测试方式:基准测试,返回结构体 测试次数:10+ 测试结果:返回的数据量越大使用返回值形式,性能更好约10%-30%,各指数也比反回指针方式低那么一点 分析:返回值方式,内存分配到栈,而指针是分配到堆,频繁在堆上创建回收GC性能比内存拷贝性能低。估计可能是:在对象频繁创建和删除的场景下,传递指针导致的 GC 开销可能会严重影响性能。 但我把一个变量赋值给返回值的属性时,逃逸分析时看到这个变量是逃逸到了堆?返回值时存分配2次,而返回指针的方式内存分配3次?

gosoon commented 2 years ago

@geektutu @lisgroup 这是表面测试的现象,很可能代码中只对底层数组的大小做了判断。这一块具体的实现还没看到。

大佬,想继续请教一下,看结果这个 8192 字节只是 slice 底层数组的占用量,在runtime/slice.go 中 slice 定义有三个字段的,想问问 slice 在底层是怎么分配空间的

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}
zachturing commented 2 years ago

“一般情况下,对于需要修改原对象值,或占用内存比较大的结构体,选择传指针。对于只读的占用内存较小的结构体,直接传值能够获得更好的性能。”

请教下,这占用内存较小的标准是? 占用多少内存算小呢?

ngyhd commented 2 years ago

GO1.17 我执行代码 interface参数并没有出现逃逸现象

dablelv commented 2 years ago

还有一种情况,变量大小不确定时也会发生逃逸。

yangfx15 commented 1 year ago

文章写得挺好的,赞! 但是有一点,8192为啥是64KB,怎么算出来的

yanboer commented 1 year ago

@yangfx15 文章写得挺好的,赞! 但是有一点,8192为啥是64KB,怎么算出来的

int 在 64 位机器是 int64,占 8 byte,8*8192/1024 = 64Kb