A brief analysis of Golang goroutine MPG mode

Coroutines are implemented by calling (or executing) a function or method using the keyword go (it can also be an anonymous function).

 Go language supports concurrency at the language level. Goroutine is a user-mode thread provided by Go language. Sometimes we also call it coroutine.

The so-called coroutine can also be called a lightweight thread to a certain extent. It is not created and managed by the OS but by the application, so the usage overhead is low (generally 4K).

We can create many goroutines, and when they run on the same kernel thread, a scheduler is needed to maintain these goroutines to ensure that all goroutines can use the CPU and use CPU resources as fairly as possible.

There are four important parts of the scheduler, namely M, G, P, and Sched. The first three are defined in runtime.h, and Sched is defined in proc.c.

  • M (work thread) represents the system thread OS Thread, which is managed by the operating system.

  • P (processor) connects the scheduling context of M and G. It is responsible for connecting G and M waiting for execution . The number of P can be set through GOMAXPROCS(), which actually represents the real concurrency , that is, how many goroutines can run at the same time.

  • G (goroutine) The entity of goroutine, including call stack, important scheduling information, such as channel, etc.

There are actually three thread correspondence models between the OS Thread of the operating system and the User Thread of the programming language, namely: 1:1, 1:N, and M:N.

  • N:1 Multiple (N) user threads always run on one kernel thread. Context switching is fast, but it cannot truly utilize multiple cores.
  • 1:1 A user thread only runs on one kernel thread. At this time, multiple cores can be used, but context switching is very slow and the switching efficiency is very low.
  • M:N      Multiple goroutines run on multiple kernel threads . This can combine the advantages of the above two, but it undoubtedly increases the difficulty of scheduling.

M:N combines the advantages of two methods (N:1, 1:1). Multiple goroutines can be processed on multiple OS threads. It can quickly switch contexts and take advantage of multi-core, and Go chose this implementation method.

 

 

MPG is its scheduling model


M can be understood as the main thread, which is a physical level thread. It is relatively resource intensive.

p can be understood as the context during the entire execution process. The context environment can be simply understood as the resources required at runtime or a state of the operating system at that time.

During the running of the main thread, a coroutine is started, and a context environment is required when the coroutine is started. The context is whether the CPU can be allocated. The resources required and the current running status.

G is coroutine

Multiple ms act on one CPU, then it is concurrency. It works in parallel on multiple CPUs. You can see that M can start multiple coroutines to form a queue.

Goroutine in the Go language runs on a multi-core CPU (the number of CPU cores is set through runtime.GOMAXPROCS(1)). The actual number of CPU cores running may not match the actual number of physical CPUs.

Each goroutine will be selected and maintained by a specific P (a certain CPU), and M (physical computing resource) selects a valid P each time, and then executes the goroutine in P.

Each P will put the goroutine it maintains into a G queue, which includes goroutine stack information, executable information, etc.

The M1 thread created here may be on other CPUs, a bit like parallelism.

Coroutines can run between multiple threads of the operating system or within threads , allowing you to process a large number of tasks with a small memory footprint. Thanks to coroutine time slicing on operating system threads, you can have as many coroutines providing services using a small number of operating system threads, and the Go runtime can smartly realize which coroutines are blocked and temporarily shelve them and handle other coroutines.

 

 

Summarize:


M represents the downward execution of the main thread, and the p context can start the coroutine to work according to the system conditions. There may be many M, and they may all be on one CPU, or each M may be on a different CPU. This is called parallelism.

When a coroutine is blocked, it has a mechanism to switch back and forth. It can guarantee the execution of the main thread and also give the queued G coroutine a chance to execute.

Guess you like

Origin blog.csdn.net/qq_34556414/article/details/132885357