Goodbye Go interviewer: GMP model, why is there P?
Today’s protagonist is an extension question (question) of the all-purpose GMP model question in the Go interview, that is "GMP model, why is there P ? "
Further deliberation behind the question, in fact, the essence of this interview question is to ask: "GMP model, why can't G and M be directly bound? There is also an additional P. It's so troublesome, why is it, what problem is it trying to solve? "
In this article, Jianyu will take you to explore the reasons for the changes in GM and GMP models.Before Go1.1, Go’s scheduling model was actually the GM model, that is, there was no P. Today I will take you to review past designs.
One of the ways we can understand something is to look at the source code, and look at Go1.0.1 with Jianyu The core key steps of the scheduler source code:
static void schedule(G *gp) { ... schedlock(); if(gp != nil) { ... switch(gp->status){ case Grunnable: case Gdead: // Shouldn't have been running! runtime·throw("bad gp->status in sched"); case Grunning: gp->status = Grunnable; gput(gp); break; } gp = nextgandunlock(); gp->readyonstop = 0; gp->status = Grunning; m->curg = gp; gp->m = m; ... runtime·gogo(&gp->sched, 0); }
Call the schedlock
method to obtain the global lock.After successfully acquiring the global lock, change the current Goroutine state from Running (being scheduled) to Runnable (can be scheduled). Call the gput
method to save the current Goroutine running status and other information for subsequent use.Call the nextgandunlock
method to find the next runnable Goroutine and release the global lock for other schedulers to use.After obtaining the next Goroutine to be run, change its running status to Running. Call the runtime·gogo
method to run the next Goroutine to be executed just obtained and enter the next round of scheduling.
Thinking about the GM model
By analyzing the scheduler source code of Go1.0.1, we can find a more interesting point. That is the scheduler itself (schedule method). Under normal processes, it will not return, that is, it will not end the main process.

He will continuously run the scheduling process. After GoroutineA is completed, it will start looking for GoroutineB. When B is found, it will The completed scheduling right of A is handed over to B, allowing GoroutineB to start being scheduled, that is, running.
Of course, there are also Gs that are blocked (Blocked). Suppose G is making some system or network calls, which will cause G to stall. At this time, M (system thread) will be put back in the kernel queue, waiting for a new round of wake-up.
Disadvantages of the GM model
On the surface, the GM model seems to be indestructible and flawless. But why change it?
In 2012, Dmitry Vyukov published the article "Scalable Go Scheduler Design Doc", which is still the main target of major research articles on the Go scheduler. He described the overall reasons and considerations in the article. The following content refers to this article.
The current Goroutine scheduler (referring to the GM model of Go1.0) limits the scalability of concurrent programs written in Go, especially high-throughput servers and parallel computing programs.
The implementation has the following problems:
There is a single global mutex (Sched.Lock) and centralized state management: mutex needs to protect all goroutine-related operations (creation, completion, reordering, etc.), resulting in serious lock competition. Goroutine passing problem: goroutine (G) handover (G.nextg): worker thread ( Runnable goroutines are frequently handed over between M's). The above may result in increased latency and additional overhead. Every M must be able to execute any runnable G, especially the M that just created G. Each M needs to do memory caching (M.mcache): will lead to excessive resource consumption (Each mcache can absorb 2M of memory cache and other caches), data locality is poor. Frequent thread blocking/unblocking: In the presence of syscalls, threads are often blocked and unblocked block. This adds a lot of extra performance overhead.
GMP model
In order to solve the above many problems of the GM model, in Go1.1, Dmitry Vyukov worked on the GM model Based on this, a new P (Processor) component is added. And implemented the Work Stealing algorithm to solve some newly generated problems.

GMP model, in the previous article "Go group friends asked: What is the appropriate number of Goroutines to control, will it affect GC and scheduling? has been explained in ".
# Friends who think it’s good can pay attention to it, I won’t repeat it here.
What changes will it bring
What changes will it bring after adding P? Let’s talk about it more explicitly.
Each P has its own local queue, which greatly reduces the direct dependence on the global queue. The result is a reduction in lock competition. The bulk of the performance overhead of the GM model is lock competition.
On the relative balance of each P, the Work Stealing algorithm is also implemented in the GMP model. If the local queue of P is empty, it will be removed from the global queue. Or steal the runnable G from the local queue of other P to run, reducing idling and improving resource utilization.
Why is there P
At this time, some friends may be confused. If you want To implement the local queue and Work Stealing algorithm, why not add it directly to M? M can still achieve similar functions. Why add another P component?
Combined with the positioning of M (system thread), if you do this, there are the following problems.
- Generally speaking, the number of M will be more than P. Like in Go, the maximum limit of the number of M is 10000, and the default number of P is the number of CPU cores. In addition, due to the properties of M, that is, if there is a system blocking call that blocks M and is not enough, M will continue to increase.
- If M continues to increase, if the local queue is mounted on M, it means that the local queue will also increase accordingly. This is obviously unreasonable, because the management of local queues will become complicated and Work Stealing performance will be significantly reduced.
- #After M is blocked by a system call, we hope to allocate its unexecuted tasks to others to continue running, rather than causing everything to stop as soon as it is blocked.
- Therefore, it is unreasonable to use M. Then introducing a new component P and associating the local queue with P can solve this problem well.
SummaryToday’s article combines some historical situations, cause analysis and solution description of the entire Go language scheduler.
"GMP model, why is there P?" This question is like a system design understanding, because now many people will memorize the GMP model or go through it in an instant style in order to cope with the interview. And understanding the real reasons behind it is what we need to learn and understand.
Only by knowing what is happening and why is it happening can we break the situation.
The above is the detailed content of Goodbye Go interviewer: GMP model, why is there P?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



How to use PHP and GMP to perform RSA encryption and decryption algorithm for large integers. The RSA encryption algorithm is an asymmetric encryption algorithm that is widely used in the field of data security. It implements the process of public key encryption and private key decryption based on two particularly large prime numbers and some simple mathematical operations. In the PHP language, the calculation of large integers can be realized through the GMP (GNUMultiplePrecision) library, and the encryption and decryption functions can be realized by combining the RSA algorithm. This article will introduce how to use PHP and GMP libraries to

"Why is there P in GMP model?" This question is like a system design understanding, because now many people will memorize the GMP model or go through it in an instant style in order to cope with the interview. And understanding the real reasons behind it is what we need to learn and understand.

How to compile and install php gmp: 1. Decompress the php package through "bzip2 -d gcc-4.1.0.tar.bz2"; 2. Execute "tar -xvf gcc-4.1.0.tar" or "tar -xvf *. tar" command; 3. Install gmp through "make install".

How to use PHP and GMP to implement fast multiplication of large numbers Introduction: In computer science, integer arithmetic is one of the most basic and commonly used operations. However, when large integers are involved, traditional arithmetic methods become inefficient. This article will introduce how to use the GMP (GNUMultiplePrecision) library in PHP to implement fast multiplication of large numbers and provide corresponding code examples. Introduction to the GMP library The GMP library is a high-precision calculation library that provides functions such as addition, subtraction, multiplication, division, and exponentiation of large integers.

How to use PHP and GMP to implement RSA encryption and decryption algorithm RSA encryption algorithm is an asymmetric encryption algorithm that is widely used in the field of information security. In practical applications, it is often necessary to use programming languages to implement RSA encryption and decryption algorithms. PHP is a commonly used server-side scripting language, and GMP (GNUMultiplePrecision) is a high-precision mathematical calculation library that can help us perform large number operations required in the RSA algorithm. This article will introduce how to use PHP and GMP

How to generate large prime numbers using PHP and GMP Introduction: In the field of cryptography and security, randomly generating large prime numbers is very important. PHP's GMP (GNUMultiplePrecision) extension provides high-precision calculation functions, which we can use to generate the large prime numbers we need. This article will introduce how to generate large prime numbers using PHP and GMP, and provide corresponding code examples. Step 1: Install the GMP extension First, we need to ensure that the GMP extension is installed and enabled on the server. This can be done via the following

From start to finish: How to use PHP to extend GMP for big number operations. With the development of the Internet, big data processing has become an indispensable part of our daily development. In many scenarios, we need to operate on numbers larger than PHP's integer range (-2^31-1 to 2^31-1). In this case, PHP's GMP extension comes in handy. GMP (GNUMultiplePrecisionArithmeticLibrary) is a

PHP and GMP Tutorial: How to Calculate the Least Common Multiple of Large Numbers Introduction: In computers, we often need to deal with large number operations. However, due to computer storage limitations, traditional integer types cannot handle numbers beyond a certain range. In order to solve this problem, we can use PHP's GMP (GNUMultiplePrecision) library to perform large number operations. This article will introduce how to use PHP and the GMP library to calculate the least common multiple of any two large numbers. What is the least common multiple? youngest male
