How Does Go’s Scheduler Perform Context Switching? A Deep Dive
This article explains the concept of context switching, compares process, thread, and coroutine switches, and details how Go’s M:N scheduler implements low‑cost coroutine switches with examples, costs, and optimization tips for writing efficient concurrent programs.
Introduction
Multitasking is ubiquitous in modern computer systems, and operating systems must switch between tasks on a single processor. This operation, known as a context switch, is crucial for Go developers to understand in order to write efficient concurrent programs.
What Is a Context Switch?
A context switch is the process by which the OS saves the state of the currently running task (registers, program counter, etc.) and loads the state of the next task.
Save the current task’s context.
Load the next task’s context.
Transfer the processor to the next task.
Types of Context Switches
Process context switch : switches between different processes; highest cost because it requires changing the address space.
Thread context switch : switches between threads within the same process; lower cost as threads share the address space.
Coroutine (goroutine) context switch : switches between lightweight coroutines within a single thread; lowest cost and forms the basis of Go’s concurrency model.
Context Switching in Go
Go’s concurrency model relies on goroutines and a built‑in scheduler. Goroutines are lightweight threads managed by the Go runtime, and the scheduler performs context switches between them.
Go Scheduler Mechanism
The scheduler uses an M:N model, mapping M goroutines onto N OS threads. Its core components are:
G (Goroutine) : a runnable goroutine.
M (Machine) : an OS thread.
P (Processor) : a logical processor that executes goroutines.
Scheduler Work Process
Goroutine creation : a new goroutine is placed in the global queue or a local P queue.
Scheduling loop : each P runs a loop that continuously pulls goroutines from its local queue or the global queue for execution.
Context switch : when a goroutine blocks or yields the CPU, the scheduler saves its context and loads the next goroutine’s context.
Cost of Context Switching
Even though coroutine switches are cheap, they still incur overhead in three main areas:
CPU time : saving and restoring context consumes CPU cycles.
Cache invalidation : switches may flush CPU caches, reducing performance.
Memory overhead : additional memory is needed to store context information.
The Go scheduler mitigates these costs with optimizations such as reducing global lock usage and improving the goroutine scheduling algorithm.
Practical Example: Context Switching in Go
The following program creates two goroutines that print a counter and sleep for one second. The scheduler alternates execution between them, demonstrating a context switch.
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(2) // set maximum CPU cores
go func() {
for i := 0; i < 5; i++ {
fmt.Println("Goroutine 1:", i)
time.Sleep(1 * time.Second)
}
}()
go func() {
for i := 0; i < 5; i++ {
fmt.Println("Goroutine 2:", i)
time.Sleep(1 * time.Second)
}
}()
time.Sleep(6 * time.Second) // wait for goroutines to finish
}Running the program yields interleaved output such as:
Goroutine 1: 0
Goroutine 2: 0
Goroutine 2: 1
Goroutine 1: 1
Goroutine 1: 2
Goroutine 2: 2
Goroutine 2: 3
Goroutine 1: 3
Goroutine 1: 4
Goroutine 2: 4Conclusion
Context switching is a key technology for multitasking. For Go developers, understanding its principles and the scheduler’s implementation is essential for building high‑performance concurrent applications. While Go’s lightweight goroutine switches are inexpensive, developers must still be aware of their potential overhead and apply appropriate optimizations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Development & AI Practice
DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
