内存分配
Go语言的内存分配基于TCMalloc,TCMalloc是Google开发的一个内存分配器,特别适用于高并发场景。
TCMalloc具有现代化内存分配器的基本特征:对抗内存碎片、在多核处理器上可伸缩。
一、内存管理基本概念
内存管理有三种类型:第一种是全手工的内存分配;第二种是全自动分配;第三种是处于两者之间的半自动的内存管理方案。
二、逃逸分析
代码如下:
package main
func toHeap() *int{
var x int
return &x
}
func toStack() int{
x:=new(int)
*x=1
return *x
}
func main() {
}
输入命令行:
go run -gcflags '-m -l' main.go
需要开启逃逸分析日志,在编译的时候加上-gcflags '-m'即可,不过为了不让编译器自动内连函数,一般会加-l参数,所以最终编译参数为-gcflags '-m -l'(-m意思是打印编译器的自动优化策略,使用go tool compile -help查看所有可以被传入编译器的参数列表)。
运行结果:
# command-line-arguments
./main.go:4:6: moved to heap: x
./main.go:9:8: new(int) does not escape
书上运行结果:
# command-line-arguments
./main.go:5:9: &x escapes to heap
./main.go:4:6: moved to heap: x
./main.go:8:10: new(int) does not escape
toHeap()中的x最后在堆上分配,而to Stack()中的x最后分配在栈上(尽管是通过new分配的)。
代码如下:
package main
type S struct{}
func main(){
var a S
x:=&a
_=toStack(x)
_=toHeap(a)
}
func toStack(z *S) *S{
return z
}
func toHeap(z S) *S{
return &z
}
输入命令行如下:
go run -gcflags '-m -l' main.go
运行结果如下:
# command-line-arguments
./main.go:12:14: leaking param: z to result ~r1 level=0
./main.go:16:13: moved to heap: z
书上运行结果:
# command-line-arguments
./main.go:12:18: leaking param: z to result ~r1 level=0
./main.go:17:9: &z escapes to heap
./main.go:16:16: moved to heap: z
./main.go:7:7: main &a does not escape
代码如下:
package main
type S struct{
M *int
}
func main(){
var a int
var b s
ref(&a,&b)
}
func ref(x *int, y *S){
y.M=x
}
命令行如下:
go run -gcflags '-m -l' main.go
运行结果如下:
# command-line-arguments
./main.go:9:8: undefined: s
书上运行结果如下:
# command-line-arguments
./ex.go:13:21: leaking param: x
./ex.go:13:21: ref y does not escape
./ex.go:10:6: &a escapes to heap
./ex.go:8:6: moved to heap: a
./ex.go:10:10: main &b does not escape
TCMalloc
TCMalloc的全称是Thread-Caching Malloc(线程缓存分配器)。
小内存分配和ThreadCache对应。大内存分配和PageHeap对应。
一、整体结构
TCMalloc内存管理体系分为三个层次:ThreadCache、CentralCache和PageHeap。
第一点,线程私有性。
第二点,内存分配粒度。
二、小内存分配
小于256KB的内存申请。
span(由地址连续的page组成一个大块内存)用于内部管理;
object(将span按照特定大小分割为多个小块,每一个小块可以存储一个对象)用于面向对象分配。
三、CentralCache
四、大内存分配
Mspan(内存管理器)
MCache
MCentral
MHeap
内存分配有三个基本的概念要清楚,即G-M-P:G代表Goroutine执行的上下文环境;M代表的操作系统线程;P代表Processer(调度器)。
1、初始化
2、分配
3、回收释放
垃圾回收
一、标记清理算法
二、标记实现
三、清理
四、监控