GMP — Goroutine (G), Machine (M), Processor (P). Go's three-tier scheduler that enables efficient concurrency by multiplexing goroutines onto OS threads.
G (Goroutine): Represents a unit of work. Contains stack, instruction pointer, and scheduling state. Goroutines transition between states: _Grunnable (ready to run), _Grunning (actively executing), _Gwaiting (blocked on I/O/channel/syscall), _Gsyscall (in system call).
M (Machine): An OS thread managed by the runtime. M threads execute goroutine code. Limited to 10,000 by default. When an M blocks, its P is handed off to another M.
P (Processor): A logical processor with a local run queue (capacity 256). Number controlled by GOMAXPROCS (defaults to runtime.NumCPU()). P is the scheduling entity — it binds goroutines to machines.
Scheduling algorithm:
1// Check current GOMAXPROCS2fmt.Println("Processors:", runtime.GOMAXPROCS(0))34// Runtime scheduler hints5runtime.Gosched() // Yield to scheduler6runtime.LockOSThread() // Pin to current OS thread7runtime.UnlockOSThread() // Unpin from OS thread
Work stealing: When a P's local queue is empty, it tries to steal half of another P's queue. This prevents load imbalance without a global lock.
Handoff: When an M makes a blocking syscall, its P is detached and given to another M so goroutines keep running.
When to tune GMP:
Common mistakes:
runtime.GOMAXPROCS(0) returns the max value (it returns current setting).runtime.LockOSThread() unnecessarily (pins goroutine, reduces scheduling flexibility).