[Today’s little go classmates are going to take out the trash (2)]


Learning a language well is about perseverance!


The blogger is 👦a handsome boy, you can call me Shanyujun
🖱 ⌨personal homepage: Anyuge [‘s personal homepage]
💖💖If it is helpful to you, I hope you can support the blogger with three consecutive ⭐⭐⭐support 🌊

Insert picture description here

precise garbage collection

For languages ​​like C that do not support garbage collection, there are still some garbage collection libraries that can be used. Such libraries are also generally implemented using the mark-sweep algorithm, but they are all conservatively garbage collected. They are called "conservative" because they don't have access to object type information, so they can only conservatively assume that every word in the address range is a pointer.

What is the problem of not being able to get the type information of an object? Here is an example to illustrate.

Assuming that a structure does not contain pointer members, it is actually unnecessary to recursively mark the members of the structure when the structure members are garbage collected. But since there is no type information, we don't know that this structure member does not contain pointers, so we can only recursively mark each byte of the structure, which obviously wastes a lot of time. This example shows that accurate garbage collection can reduce unnecessary scans and increase the speed of the marking process.

This example shows that in some cases with conservative garbage collection, garbage cannot be collected. Although it won't cause a big problem, it's always annoying, and it's all because of lack of type information.

Well now, precise garbage collection is supported in version 1.1 of the Go language . The first thing that accurate garbage collection needs is type information. The MSpan structure was mentioned in the previous section, and the type information is stored in MSpan . Calculate from an address the MSpan it belongs to , the formula is as follows:

page number = (address – mheap.arena_start) >> page size
MSpan = mheap->map[page number]

1. Next, the type of the allocation block can be obtained through MSpan->type. Here is an MType struct:

struct  MTypes
    byte         compression;         //  one  of  MTypes_*
    bool         sysalloc;            //  whether  (void*)data  is  from  runtime·SysAlloc uintptr         data;


MTypes describe the types of blocks allocated in MSpan, where the compression field describes the layout of the data. Its value is one of MTypes_Empty, MTypes_Single, MTypes_Words, and MTypes_Bytes:
MTypes_Empty: All blocks are free, or the type information of this allocated block is not available. The data field is meaningless in this case.
MTypes_Single: This MSpan contains only one block, the data field stores type information, and the sysalloc field is meaningless.
MTypes_Words: This MSpan contains multiple blocks (more than 7 types of blocks). At this time, data points to an array [NumBlocks]uintptr, and each element index in the array stores the type information of the corresponding block.
MTypes_Bytes: This MSpan contains up to 7 different types of blocks. At this time, the data field refers to the following structure

struct  {
    type    [8]uintptr               //  type[0]  is  always  0
    index   [NumBlocks]byte

The type of the i-th block is data.type[data.index[i]]

On the surface, MTypes_Bytes seems to be the most complicated. In fact, the complexity here is that MTypes_Empty is smaller than MTypes_Single, MTypes_Bytes is smaller than MTypes_Words. MTypes_Bytes is just complicated for optimization.

As mentioned in the previous section, the size of the blocks stored in each MSpan is the same, but they are not necessarily the same type. If not used, the type of this MSpan is MTypes_Empty. If a large chunk is stored, larger than half the size of the MSpan, and therefore nothing else can be stored, then the type of the MSpan is MTypes_Single.

Assuming that there are many kinds of blocks, each block uses a pointer, which could have been stored directly with MTypes_Words. But when there are not many types, you can put the pointers of these types together in an array, and then store the array index. This is a small optimization that saves memory space.

The resulting type information is actually a structure like this:

struct  Type
    uintptr  size;
    uint32  hash;
    uint8  _unused;
    uint8  align;
    uint8  fieldAlign;
    uint8  kind;
    Alg  *alg;
    void  *gc;
    String  *string;
    UncommonType  *x;
    Type  *ptrto;

Different types of type information structures are slightly different, this is the general part. It can be seen that there is a gc field in this structure, and the precise garbage collection is realized by using this gc field in the type information.

write at the end


Leave a Comment

Your email address will not be published. Required fields are marked *