Lab 01: Go Scheduler — GMP Model

Time: 60 minutes | Level: Architect | Docker: golang:1.22-alpine

Overview

Deep dive into the Go runtime scheduler: GMP model (Goroutine/Machine/Processor), GOMAXPROCS tuning, runtime.LockOSThread(), work stealing algorithm, runtime/trace for profiling, and goroutine lifecycle states.


Step 1: The GMP Model

GMP (Goroutine / Machine / Processor):

  G (Goroutine)  — lightweight thread, ~2KB initial stack, grows as needed
  M (Machine)    — OS thread, usually GOMAXPROCS threads active
  P (Processor)  — scheduling context, has a run queue of goroutines

  Run Queue:
    Global queue (fallback)
    Per-P local queue (max 256 goroutines)

  States (goroutine):
    Runnable   — ready to run, waiting for P
    Running    — executing on an M
    Syscall    — blocked in OS syscall (M detaches from P)
    Waiting    — blocked on channel/mutex/timer/IO
    Dead       — finished

Step 2: GOMAXPROCS Tuning


Step 3: runtime.LockOSThread()


Step 4: Work Stealing Algorithm


Step 5: runtime/trace


Step 6: Goroutine Leak Detection

💡 Use goleak (go.uber.org/goleak) in tests to automatically detect goroutine leaks: defer goleak.VerifyNone(t).


Step 7: MemStats and GC Tuning


Step 8: Capstone — Scheduler Demo

📸 Verified Output:


Summary

Component
Role
Tuning

G (Goroutine)

~2KB stack, grows

Keep short-lived

M (Machine)

OS thread

Limited by GOMAXPROCS

P (Processor)

Run queue (max 256)

= GOMAXPROCS

Work stealing

Balance load across Ps

Automatic

GOMAXPROCS

Parallelism degree

= NumCPU default

LockOSThread

Thread affinity

CGO/TLS only

runtime/trace

Profiling

go tool trace

GOGC

GC frequency

100 default, tune for latency

Last updated