堆内存与栈内存

Go程序会在两个地方为变量分配内存,一个是全局的堆空间用来动态分配内存,另一个是每个goroutine的栈空间。与Java、Python等语言类似,Go语言实现垃圾回收机制,所以Go语言的内存管理是自动的,通常开发者不用关心内存分配到栈上还是堆上。但是从性能的角度出发,在栈上和堆上分配内存,性能差异是非常大的。

在函数中申请一个对象,,如果分配在栈中,函数执行结束时自动回收;如果分配在堆中,则在函数结束后某个时间点进行垃圾回收。

在栈上分配和回收内存的开销很低,只需要2个cpu指令: PUSH和POP。一个是将数据push到栈空间以完成分配,pop则是释放空间。也就是说在栈上分配内存,消耗的仅是将数据copy到内存的时间。内存的I/O通常能达到30GB/s,因此在栈上分配内存的效率是非常高的。

在堆上分配内存,一个很大的额外开销则是垃圾回收。Go语言使用的是标记清除算法,并且在此基础上使用了三色标记法和写屏障技术,提高了效率。

参考资料:

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