After understanding the last article Google TCMalloc memory principle juejin.cn/post/691900… Golang memory management is much easier to understand
The core idea of Golang’s memory management is to perform operations such as pre-allocation and memory pooling to avoid the performance problems caused by system calls and prevent the need for system calls every time memory is allocated.
PS: If there is anything wrong with this picture, please correct it
Explain some terms in the picture
page
The smallest unit of virtual memory that the Mheap requests. As a general rule, be 8 KB
span
Go The basic unit of memory allocation, consisting of N pages
class size
To reduce memory fragmentation, the span size is graded. Currently, there are 67 grades from 0 to 66. You can see that class=0 is not used (also in grey)
The 66 spans are as follows :(v.14.13)
// 1 8 8192 1024 0 87.50% // 2 16 8192 512 0 43.75% // 3 32 8192 256 0 46.88% // 4 48 8192 170 32 31.52% // 5 64 8192 128 0 23.44% // 6 80 8192 102 32 19.07% // 7 96 8192 85 32 15.95% // 8 112 8192 73 16 13.56% // 9 128 8192 64 0 11.72% // 10 144 8192 56 128 11.82% // 11 160 8192 51 32 9.73% // 12 176 8192 46 96 9.59% // 13 192 8192 42 128 9.25% // 14 208 8192 39 80 8.12% // 15 224 8192 36 128 8.15% // 16 240 8192 34 32 6.62% // 17 256 8192 320 5.86% // 18 288 8192 28 128 12.16% // 19 320 8192 25 192 11.80% // 20 352 8192 23 96 9.88% // 21 384 8192 21 128 9.51% // 22 416 8192 19 288 10.71% // 23 448 8192 18 128 8.37% // 24 480 8192 17 32 6.82% // 25 512 8192 16 0 6.05% // 26 576 8192 14 128 12.33% // 27 640 8192 12 512 15.48% // 28 704 8192 11 448 13.93% // 29 768 8192 10 512 13.94% // 30 896 8192 9 128 15.52% // 31 1024 8192 80 12.40% // 32 1152 8192 7 128 12.41% // 33 1280 8192 6 512 15.55% // 34 1408 16384 11 896 14.00% // 35 1536 8192 5 512 14.00% // 36 1792 16384 9 256 15.57% // 37 2048 8192 40 12.45% // 38 2304 16384 7 256 12.46% // 39 2688 8192 3 128 15.59% // 40 3072 24576 8 0 12.47% // 41 3200 16384 5 384 6.22% // 42 3456 24576 7 384 8.83% // 43 4096 8192 2 0 15.60% // 44 4864 24576 5 256 16.65% // 45 5376 16384 3 256 10.92% // 46 6144 24576 40 12.48% // 47 6528 32768 5 128 6.23% // 48 6784 40960 6 256 4.36% // 49 6912 49152 7 768 3.37% // 50 8192 8192 10 15.61% // 51 9472 57344 6 512 14.28% // 52 9728 49152 5 512 3.64% // 53 10240 40960 40 4.99% // 54 10880 32768 3 128 6.24% // 55 12288 24576 2 0 11.45% // 56 13568 40960 3 256 9.99% // 57 14336 57344 40 5.35% // 58 16384 16384 1 0 12.49% // 59 18432 73728 40 11.11% // 60 19072 57344 3 128 3.57% // 61 20480 40960 20 6.87% // 62 21760 65536 3 256 6.25% // 63 24576 24576 10 11.45% // 64 27264 81920 3 128 10.00% // 65 28672 57344 20 4.91% // 66 32768 32768 1 0 12.50%Copy the code
Bytes /obj indicates the size of the span, which ranges from 8B to 32KB. Bytes /span indicates the number of bytes occupied by the heap. Number of pages * page size (eg:8192= 1x8K) number of objects (eg: 1024=8192/8)
mcache
The McAche is allocated to the goroutine in M running, which is the coroutine level and therefore does not need to be locked. There is only one goroutine running on M, so there is no need to lock it.
As you can see from the figure above, Mache allocates memory for two types of objects. One is a microobject [1B,16B] and one is a small object [16B,32KB].
As shown in the figure, McAche provides a special Tiny Allocator to allocate memory for microobjects. The specific allocation process will be introduced later.
Small objects are allocated by choosing the span that best suits their size. As can be seen from the figure, the span of the same level is divided into two categories. One is the span that can be scanned by GC, which contains objects containing Pointers. Another span, similar to one that cannot be scanned by GC, does not contain Pointers to objects. You can see that memory is allocated with different spans depending on whether there are pointer objects for subsequent GC garbage collection.
Each level of the SPAN list is a bidirectional list, with each span pointing to the previous and the next span. Each level of size class can have one or more spans
When there is not enough MACHE in the small object application, the application will continue to McEntral
mcentral
McEntral is a sharded span for McAche. McEntral is global, that is, multiple MSS share McEntral, which can cause concurrency problems, so all applications need to be locked.
McEntral stores 67 levels of size span, where size=0 is not used (marked in gray). The span at each level is divided into two types. One type of empty indicates that the MSPAN of this chain has been allocated an object, or has been used by McAche and occupied by the corresponding thread. Nonempty represents an MSPAN list with free objects
Note that McEntral lists are maintained in Mheap
If the allocated memory is a list with no free spans, it needs to be applied as mHEAP.
mheap
The Mheap is the entire heap space held by the GO program and is a global variable of GO, so it requires a global lock when used.
Large objects (larger than 32KB) are allocated directly through the Mheap. In addition, McEntrals are stored in the MHeap, and the Mheap knows everything about McEntral.
If the MHEAP does not have enough memory, pages are requested from virtual memory and then assembled into spans for use by the program.
Mheap also stores multiple HeapArenas, which store contiguous spans, primarily for mHeap to manage spans and GC garbage collection
Micro object [1 b, 16 b)
The memory allocation of Tiny objects is specially allocated by The Special Tiny Allocator provided by McAche. The allocated objects do not contain Pointers, such as some small strings and independent escape variables that do not contain Pointers.
Small objects [16 b, 32 KB]
If mache does not have a span available, mache will apply to McEntral, lock it, find an available span, delete it from NonEmpty, place it in the empty list, return the span to the worker thread, and unlock it. If there is not enough memory, McEntral will continue to apply to the Mheap.
When returned, lock, remove span from empty list, and then add it to NonEmpty list to unlock.
Large objects (32 KB, + up)
Large objects are allocated directly using the MHEAP. If the Mheap does not have enough memory, the Mheap applies for several Pages from virtual memory. As you can see, the cost of memory is getting higher and higher
Looking back, what are the advantages of such memory management
1. It can be seen that the unit of memory application is SPAN, which is divided into different sizes. From the rule of size, it can be seen that the span is not simply increased by the power of 2, but is classified according to the minimum fragmentation caused by calculation, which will reduce memory fragmentation during application. For example, if the request size is 47B, the power of 2 will provide 64B memory supply, but if the request size is span, it will provide 48B span, obviously, the latter will cause less fragmentation.
2. Apply for a large chunk of memory from the operating system each time, and let Go do the allocation, reducing the system call
3. The memory algorithm of GO uses Google’s TCMalloc memory management algorithm to divide the memory into very fine and multi-level management to reduce the granularity of locks. When object memory is reclaimed, it is not actually freed, but simply put back into a pre-allocated chunk of memory for reuse. Only when there is too much idle memory, it tries to return some memory to the operating system to reduce the overall overhead
By the end of this article, you should have a clear idea of Golang’s memory management. In the next article we will see how the source code is implemented.
reference
The illustration Golang memory allocation www.cnblogs.com/shijingxian…
Go distribution on segmentfault.com/a/119000002…
The memory allocation lessisbetter those things. The site / 2019/07/06 /…
Graphic memory allocator tonybai.com/2020/02/20/…