3

In the process of learning the memory management part of the Go language, I found a very interesting problem. Today, I use this article:

  • 1. Throwing this question to everyone, I suggest that after seeing this question, you can think about it for yourself 🤔 and then read the following.
  • 2. Further strengthen your understanding of the Go memory architecture

Before starting this article, let's quickly review the core knowledge points related to the "Go memory architecture" and learn from the past .

A quick review of "TCMalloc memory management architecture"

Let's briefly review the "TCMalloc memory management architecture". For a detailed explanation, you can view the previous article "18 Graphs to Decrypt the New Era Memory Allocator TCMalloc"

Pain points

Multi-threading era ---> Thread shared memory ---> Thread application for memory will cause competition ---> Competition lock ---> lock affects performance.

solution

Increase the memory cache on each thread.

The simple architecture diagram is as follows:

http://cdn.tigerb.cn/20210120132244.png

A quick review of "Go Memory Management Architecture"

Then briefly review the "Go Memory Management Architecture". For a detailed explanation, you can view the previous article "Analysis of Go Memory Management Architecture"

Pain points

Ditto.

solution

Same as above, based on "TCMalloc" implementation.

The simple architecture diagram is as follows:

http://cdn.tigerb.cn/20220405224809.png

interesting question

Regarding this interesting question, careful friends may have discovered it, and the question is as follows:

Why is the thread cache of Go's memory manager mcache p , but not by the real system thread m ?

personal thinking time

Isn't it interesting, on this subject. On the opposite side, you might as well stop and think for a few minutes:

Why?

decrypt

According to the original design idea of TCMalloc , the thread cache mcache should indeed be bound to the system thread M .

Then we assume: According to the original idea of TCMalloc mcache , bind ---e2c06fa212d50618ab0044d35ac4bc1f--- to the system thread M . Then we just need to see what's wrong with this assumption .

To demonstrate this assumption, we need to take a brief look at "Go's scheduling model GMP ".

Go's scheduling model GMP

Go directly to the entry-level "Scheduling model of Go GMP " architecture diagram:

http://cdn.tigerb.cn/20220416214452.png

Regarding the principle of "Go's scheduling model GMP ", you should read countless articles, I will not go into details here, if you are not familiar with it, you can search by yourself.

Here is a brief introduction to the entry-level knowledge about GMP . In fact, GMP corresponds only to the logical structure of the Go language itself. The meaning is as follows:

  • M :代表结构体mMachine b7f286dbe435fac47f5033f4942493f9--- ,这个结构体的核心是会和真正的系统线程thread
  • G :代表结构体gGoroutine 51b4c0bf4b0de92ba2c3077733e3003b--- ,这个结构体就是大家协程 ,简单理解其实就是这个结构体Binds a function that needs to be executed concurrently.
  • P :代表结构体pProcessor e1818d41349c7be8c301d690031ac6f8--- ,这个结构体表示逻辑处理器 ,通过这个结构体和计算机的逻辑处理器To establish a corresponding relationship, the number of P is usually consistent with the number of logical processors of the computer through the runtime.GOMAXPROCS(runtime.NumCPU()) setting.

Simple responsibilities and relationships of the three:

  • P

    • and one M bind each other
    • Maintained a queue of executable G
  • M

    • and one P bind each other
    • 负责G e5ffdaecee01fa9fc67f19796db4e452---的调度,通过调度当前M PG队列、 G Queue, to achieve G can be executed concurrently.
    • Responsible for executing P the current scheduled G

此阶段结论以上P的数量M的数量是一一对应的,所以把mcache系统线程M P looks all right. So our assumption above " according to the original idea of --- 7d5d68e34d4b219bcddece85a9e73e9d TCMalloc , put mcache binding system thread M up " does not seem to be a problem at present.

We continue to look down, a special scenario M will be unbound with P .

System calls for I/O operations

When G executes a system call of an I/O operation, such as read , write , because the system call is blocked in the process of The blocking caused by the process of copying data is not in the scope of this article, and the following articles will explain in detail) the problem, and the following operations will occur:

  • 当前G (我们g1 )的M (我们命名为m1 )和当前的P (We named it p1 )Unbind
  • The above p1 will bind an other M ( m2 )
  • m1 After the system call is executed, it will be placed idle M in the linked list

http://cdn.tigerb.cn/20220416223807.png

Since m1 will be put into the idle list, does this mean that the m1 on mcache cannot currently be reused, so it seems right? mcache p1 .

Conclusion: Since M may be blocked by a system call that performs an I/O operation (reason: the process of copying data from the kernel to user mode is blocked), M P be the same as the current- P解绑,当前P新的M ,之前的M M Linked list. The previous M mcache will not be effectively reused, but mcache is bound to P . This problem does not exist , so mcache P .

View more content in the "Go Language Easy and Advanced" series

Link http://tigerb.cn/go/#/kernal/


施展TIGERB
9.5k 声望2.7k 粉丝

// Trying to be the person you want to be.