引言
在Go语言中开发者在写代码时不必关心内存是如何分配和回收,从内存的分配到不再使用后内存的回收等等这些内存管理工作都是由Go
在底层完成的。但是Go语言内存管理是Go语言比较重要的一部分,Go对象在内存中如何存储,Go的内存分配机制是怎么样的,Go的内存分配期是如何设计的等等,我们也是有必要了解其中的原理机制。
为什么要关心内存管理
目前我们单机内存资源还是非常有限的,对于高并发高访问量下的大型系统,内存良好的设计和管理会大大提升系统的性能,所以一门编程语言的内存管理是很重要的。
Go内存分配器设计
内存分配一般都会有一些常见的设计方案,比如线性分配器(Sequential Allocator,Bump Allocator),另一种是空闲链表分配器(Free-List Allocator),这两种分配方法有着不同的实现机制和特性。
1. 线性分配器
线性分配(Bump Allocator)是一种高效的内存分配方法,但是有较大的局限性。当我们在编程语言中使用线性分配器,我们只需要在内存中维护一个指向内存特定位置的指针,当用户程序申请内存时,分配器只需要检查剩余的空闲内存、返回分配的内存区域并修改指针在内存中的位置,即移动下图中的指针:
上图虚线箭头的左侧灰色区块都是已经被分配的内存空间,右侧则是空闲的内存空间,该空间可以被分配给新的对象。根据线性分配器的原理,我们可以推测它有较快的执行速度,以及较低的实现复杂度。但是线性分配器无法在内存被释放时重用内存。如下图所示,如果已经分配的内存被回收,线性分配器是无法重新利用红色的这部分内存的:
Go内存管理
Go运行时的内存分配算法主要源自 Google 为 C 语言开发的TCMalloc(Thread-Caching Malloc)算法。
Go语言中内存分配大致有3种模式:Stack
、Heap
、Fixed Size Segment。
Go内存模型官方文档地址:https://golang.google.cn/ref/mem
参考资料
https://draveness.me/golang/docs/part3-runtime/ch07-memory/golang-memory-allocator/