Guided reading
本文基于Go源码版本1.16、64位Linux平台、1Page=8KB、本文的内存特指虚拟内存
复制代码
Today we start to enter the second part of "Memory and Garbage Collection" in the second chapter of "Go Language Easy Series", "Go Language Memory Management".
About the "Memory and Garbage Collection" chapter, it will be expanded from the following three parts:
- Pre-reading Knowledge Reserve (Completed)
- Go language memory management (current part)
- Go language garbage collection principle (not started)
The first part of "Pre-reading Knowledge Reserve" has been completed. In order to better understand this article, you can click the historical link to view or review it.
content
My thoughts on explaining the "Go language memory management" part are as follows:
- Introduce the overall architecture
- Introduce a very interesting place in architecture design
mspan
Brings out the concepts ofpage
,mspan
,object
,sizeclass
,spanclass
,heaparena
, by introducing key structures in Go memory managementchunk
- Then introduce the allocation of heap memory and stack memory
- Review and Summary
The directory disassembled through this idea:
- Go memory management architecture (the content of this article)
mcache
mcentral
mheap
- Why is the thread cache held
mcache
by logical processorsp
and not system threadsm
? - Go memory management unit
mspan
page
the concept ofmspan
the concept ofobject
the concept ofsizeclass
the concept ofspanclass
the concept ofheaparena
the concept ofchunk
the concept of
- Go heap memory allocation
- Micro object allocation
- Small object allocation
- Large object allocation
- Go stack memory allocation
- stack memory allocation timing
- Stack allocations smaller than 32KB
- Stack allocations greater than or equal to 32KB
Go memory management architecture
Go's memory is managed uniformly by the memory manager. Go's memory manager is TCMalloc
designed and implemented based on Google's own open source memory allocator. For TCMalloc
a detailed introduction to the memory allocator, you can check the previous article.
Let's briefly review TCMalloc
the core design of the memory allocator.
Review the TCMalloc
memory allocator
TCMalloc
Birth background?
在多核以及超线程时代的今天,多线程技术已经被广泛运用到了各个编程语言中。当使用多线程技术时,由于多线程共享内存,线程申在请内存(虚拟内存)时,由于并行问题会产生竞争不安全。
为了保证分配内存的过程足够安全,所以需要在内存分配的过程中加锁,加锁过程会带来阻塞影响性能。之后就诞生了TCMalloc
内存分配器并被开源。
TCMalloc
如何解决这个问题?
TCMalloc
全称Thread Cache Memory alloc
线程缓存内存分配器。顾名思义就是给线程添加内存缓存,减少竞争从而提高性能,当线程内存不足时才会加锁去共享的内存中获取内存。
接着我们来看看TCMalloc
的架构。
TCMalloc
的架构?
TCMalloc
三层逻辑架构
ThreadCache
:线程缓存CentralFreeList
(CentralCache):中央缓存PageHeap
:堆内存
TCMalloc
架构上不同的层是如何协作的?
TCMalloc
把申请的内存对象按大小分为了两类:
- 小对象 <= 256 KB
- 大对象 > 256 KB
我们这里以分配小对象为例,当给小对象分配内存时:
- 先去线程缓存
ThreadCache
中分配 - 当线程缓存
ThreadCache
的内存不足时,从对应SizeClass
的中央缓存CentralFreeList
获取 - 最后,再从对应
SizeClass
的PageHeap
中分配
Go内存分配器的逻辑架构
采用了和TCMalloc
内存分配器一样的三层逻辑架构:
mcache
:线程缓存mcentral
:中央缓存mheap
:堆内存
实际中央缓存central
是一个由136个mcentral
类型元素的数组构成。
除此之外需要特别注意的地方:mcache
被逻辑处理器p
持有,而并不是被真正的系统线程m
持有。(这个设计很有意思,后续会有一篇文章来解释这个问题)
我们更新下架构图如下:
「Go内存分配器」把申请的内存对象按大小分为了三类:
- Micro Object 0 < Micro Object < 16B
- Small Object 16B =< Small Object <= 32KB
- Large Object 32KB < Large Object
In order to clearly see the relationship between these three layers, here is an example of allocating small objects on the heap:
- First go to the thread cache
mcache
to allocate memory - When not found, go to the central cache
central
to allocate memory - Finally, go directly to the heap to
mheap
allocate a block of memory
Architecture Summary
From the above analysis, it can be seen that the design of the Go memory allocator is TCMalloc
basically the same as that of the open source memory allocator. The comparison chart is as follows:
Finally we conclude:
- The Go memory allocator uses the
TCMalloc
same three-tier architecture. Logically:mcache
: thread cachemcentral
: Central cachemheap
: heap memory
- Thread caches
mcache
are held by logical processorsp
, not system threadsm