Just learned the golang GMP model, now I understand how goroutines, operating system threads and golang context/processors cooperate with each other. But I still don't understand when M and P will be generated?
For example, I have a test code to run some operations on the database, and there are two test cases (two batches of goroutines):
func Test_GMP(t *testing.T) { for _ = range []struct { name string }{ {"first batch"}, {"second batch"}, } { goroutineSize := 50 done := make(chan error, goroutineSize) for i := 0; i < goroutineSize; i++ { go func() { // do some databases operations... // each goroutine should be blocked here for some time... // propogate the result done <- nil }() } for i := 0; i < goroutineSize; i++ { select { case err := <-done: assert.NoError(t, err) case <-time.After(10 * time.Second): t.Fatal("timeout waiting for txFunc goroutine") } } close(done) } }
From my understanding, if M is created when needed. In the first batch of goroutines, 8 (number of virtual cores on my computer) operating system threads will be created, the second batch will only reuse these 8 operating system threads without creating new threads. Is this correct?
We would be grateful if you could provide more material or blogs on this topic.
M can be reused only if your process is not blocked or does not make any system calls. In your case, you have blocking tasks in your go func()
. Therefore, the number of M is not limited to 8 (the number of virtual cores on my machine). The first batch will block and remove from P and wait for the blocking process to complete while a new M is created associated with P.
See below for more details,
The above is the detailed content of When does the Go scheduler create new M and P?. For more information, please follow other related articles on the PHP Chinese website!