图解Go内存管理器的内存分配策略-腾讯云开发者社区-腾讯云

Go内存管理和分配策略-腾讯云开发者社区-腾讯云

虚拟内存技术

物理内存:实际通过物理内存而获得的内存空间

虚拟内存:与物理内存相反,是指根据系统需要从硬盘中虚拟的划出一部分存储空间

而虚拟内存技术就是对内存的一种抽象,有了这层抽象之后,程序运行进程的总大小可以超过实际可用的物理内存大小,每个进程都有自己的独立虚拟地址空间,然后通过CPU和MMU把虚拟内存地址转换为实际物理地址。

TCMalloc内存分配算法简述

TCMalloc全称是Thread Cache Malloc,是google为C语言开发的内存分配算法,是Go内存分配的起源。我们对它做个简单的了解,看看它的核心思想和几个重要概念,更能帮助我们理解Go内存分配和TCMalloc的相似和不同的地方。

核心思想

TCMalloc内存分配算法的核心思想是把内存分为多级管理,从而降低锁的粒度,它将可用的堆内存采用二级分配的方式进行管理,每个线程都会自行维护一个独立的线程内存池,进行内存分配时优先从该线程内存池中分配, 当线程内存池不足时才会向全局内存池申请,以避免不同线程对全局内存池的频繁竞争 ,进一步的降低了内存并发访问的粒度。

TCMalloc重要概念

  1. Page: 操作系统对内存的管理同样是以页为单位,但TCMalloc中的Page和操作系统的中页是倍数关系,x64下Page大小为8KB
  2. Span: 一组连续的Page被叫做Span,是TCMalloc内存管理的基本单位,有不同大小的Span,比如2个Page大的Span,16个Page大的Span
  3. ThreadCache: 每个线程各自的Cache,每个ThreadCache包含多个不同规格的Span链表,叫做SpanList, 内存分配的时候,可以根据要分配的内存大小,快速选择不同大小的SpanList,在SpanList上选择合适的Span,每个线程都有自己的ThreadCache,所以ThreadCache是无锁访问的
  4. CentralCache: 中心Cache,所有线程共享的Cache,也是保存的SpanList,数量和ThreadCache中数量相同 当ThreadCache中内存不足时,可以从CentralCache中获取 当ThreadCache中内存太多时,可以放回CentralCache 由于CentralCache是线程共享的,所以它的访问需要加锁
  5. PageHeap: 堆内存的抽象,同样当CentealCache中内存太多或太少时,都可从PageHeap中放回或获取,同样,PageHeap的访问也是需要加锁的

Go的内存分配算法是基于TCMalloc(Thread Cache malloc,线程缓存分配器)内存分配算法实现的,通过借鉴了TCmalloc的思想,开发出Go的内存分配器,核心实现在内置运行时(就是runtime)。

Go内存分配

核心思想

Go在程序启动的时候,会分配一块连续的内存(注意这时还只是一段虚拟的地址空间,并不会真正地分配内存),切成小块后自己进行管理,对内存的分配遵循以下思想。