liveBook · Manning

Scheduler

As explained in 100 Go Mistakes and How to Avoid Them

A scheduler is a runtime or operating-system component that selects executable threads or goroutines and assigns them processing resources.

A scheduler selects runnable execution units and assigns processing resources. In Go, the runtime schedules goroutines (G) onto OS threads (M), while the OS schedules those threads onto CPU cores (P). GOMAXPROCS limits the number of Ms executing user-level code simultaneously, although blocked system calls can cause the runtime to create more Ms. section 8.2.1

Avoid assuming that creating several goroutines immediately uses several cores:

  • Classify goroutines as executing, runnable, or waiting; waiting can result from system calls or synchronization operations. section 8.2.1
  • Expect runnable goroutines to wait in a local queue associated with a P or in the global runnable queue. section 8.2.1
  • Account for work stealing: an idle P may take goroutines from another P, but the timing and final thread assignment are not guaranteed. section 8.5
  • Match worker-pool sizing to CPU-bound work and GOMAXPROCS rather than expecting runtime.NumCPU alone to determine execution. section 8.5

A fixed worker pool does not guarantee immediate parallelism

A pool can start several goroutines that receive jobs from one channel, wait for them with a sync.WaitGroup, and size the pool from runtime.GOMAXPROCS(0). Initially, however, multiple workers may remain runnable while only one executes; later, work stealing and OS thread placement can distribute them across cores. Treat that distribution as an eventual scheduling outcome, not a controllable layout. section 8.5

runtime.schedule() {
    // Only 1/61 of the time, check the global runnable queue for a G.
    // If not found, check the local queue.
    // If not found,
    //     Try to steal from other Ps.
    //     If not, check the global runnable queue.
    //     If not found, poll network.
}

Inspect the scheduler’s simplified selection order: sample the global queue, consult a local queue, attempt work stealing, recheck globally, and poll the network. section 8.2.1

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Traces goroutine states, queues, work stealing, and workload effects without specifying deterministic thread or core assignment.
Examples
Uses fixed worker pools, shared channels, GOMAXPROCS, runnable-state diagrams, and a simplified runtime.schedule selection listing.
What it assumes
Assumes familiarity with goroutines, OS threads, CPU cores, channels, synchronization, and system calls.
What you can do after
Diagnose concurrency behavior by separating goroutine readiness from actual execution and by relating worker-pool sizing to CPU-bound workloads.
How it connects
Connects goroutines with OS threads, CPU cores, GOMAXPROCS, work stealing, worker pools, channels, and synchronization.

Also explained in

Compare how 12 books explain scheduler →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.