2023100220344747 Go Scheduler
# Go Scheduler
2023092816485959 OS Scheduler runtime.NumCPU() returns the number of virtual cores are available for executing in parallel. When your Go program starts up, it’s given a Logical Processor (P) for every virtual core. Every P is assigned an OS Thread (“M”). Every go program is given an initial Goroutine(G). Goroutine is a lightweight application-level thread. Goroutines are context-switched on and off an M(thread).
Queues in go scheduller: - Global Run Queue (GRQ) - Local Run Queue (LRQ)
Goroutine states¶
- wainting. For example, waiting for disk, network, the os system calls or synchronization calls (atomic, mutexes).
- runnable. The Goroutine wants time on an M so it can execute its assigned instructions
- executing. This means the Goroutine has been placed on an M and is executing its instructions.
Context switching¶
There are four classes of events that occur in your Go programs that allow the scheduler to make scheduling decisions:
- The use of the keyword go
- Garbage collection
- GC runs its own goroutines, that needs time on an M to run.
- System calls
- when goroutine makes a system call sometime Scheduler can switch to another goroutine from LRQ.
- Synchronization and Orchestration
- If an atomic, mutex, or channel operation call will cause the Goroutine to block, the scheduler can context-switch a new Goroutine to run.
Asynchronous System Calls¶
With Asynchronous System Calls network poller can be used to process the system call more efficiently. This is accomplished by using kqueue (MacOS), epoll (Linux) or iocp (Windows) within these respective OS’s. With Asynchronous System Calls go scheduler can context switch goroutine.
Synchronous System Calls¶
With Synchronous System Calls go scheduler can't context switch goroutine. For example, file-based system calls. In this case scheduler creates new thread and move goroutines to this thread.
Work stealing¶
Algorithm:
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.
}