[后端与go语言内存管理详解 | 青训营笔记]

62 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第4天 课程讲解内容: 1.mheap 程序启动初始,将会一次性从系统申请大块内存作为内存池,这个内存空间将会被放在mheap中进行管理。 mheap是用于做什么的? 负责将申请的一大块内存分割为不同的区域,并将其中的一部内存分割为合适的大小,分配给用户使用。 这其中就会涉及几个概念: 概念 大小/组成 其他 page(页) 8k go与操作系统之间的内存申请和释放都是以page为单位的 span(内存块) 一个或多个连续page组成 / sizeclass(空间规格) / 每个span都带有一个sizeclass的标志,用于标志其中的page如何使用 object(对象) 存储一个变量的数据内存空间 span再进行初始化时会分割为一堆等大的object 所谓的内存分配其实就是分配一个object 2.mcache 在mcentral中有一个lock字段,它是用于避免多个线程同时从mcentral中申请内存所导致的冲突。但锁是低效的,在高并发的服务中,它会使得内存申请成为整个系统的瓶颈,所以在mcentral前增加一层mcache。 每个处理器都有一个mcache成员,两者一一对应,当goroutine申请内存时,首先会从其所在的处理器的mcache中分配,如果mcache没有可用的span,再从mcentral中获取,填充到mcache中。 因为在同一时刻,一个处理器只有一个线程在上面运行,不会出现竞争,所以mcache不需要加锁,这加速了内存分配。 3.mcache 在mcentral中有一个lock字段,它是用于避免多个线程同时从mcentral中申请内存所导致的冲突。但锁是低效的,在高并发的服务中,它会使得内存申请成为整个系统的瓶颈,所以在mcentral前增加一层mcache。 每个处理器都有一个mcache成员,两者一一对应,当goroutine申请内存时,首先会从其所在的处理器的mcache中分配,如果mcache没有可用的span,再从mcentral中获取,填充到mcache中。 因为在同一时刻,一个处理器只有一个线程在上面运行,不会出现竞争,所以mcache不需要加锁,这加速了内存分配。 4.什么是逃逸分析? 在c语言中,局部变量在函数调用时进行定义申请内存,函数调用结束后就会释放空间,这种变量一般就会定义在栈上,自动的分配和释放,对于全局变量就需要在堆上进行初始化,由程序员自己调用malloc和free进行申请和释放。 在go中即使在堆上也不需要主动调用malloc来分配,而是由编译器自动分析找到这个需要在堆上分配空间的变量,编译器分析的过程称为逃逸分析,但是这种分析不一定百分百准确。 go编译器在编译是追踪一个变量的生命周期,如果能确定一个数据只在函数空间中访问,不被外部使用就会使用栈空间,否则使用堆空间。