Context Switch on Linux
This post collects some info regarding thread-level context switch and how to estimate/measure its cost.
In computing, a context switch is the process of storing the state of a process or thread, so that it can be restored and resume execution at a later point, and then restoring a different, previously saved, state.
In C/C++, one can use getrusage
to retrieve #context switches a process/thread has gone through. The two metrics on
context switches are:
- voluntary switch: the current thread becomes blocked from calling some special methods, e.g.
this_thread::sleep_for
- involuntary switch: the kernel decides that the current thread should be paused, in favor of another thread, possibly because the current thread has used up its CPU quota or another thread has higher priority
Some works involved inside a context switch:
- user to kernel mode transition
- save CPU registers (e.g. stack pointer) for current thread
- if the current thread becomes blocked (e.g. in voluntary switch), update the thread state and remove it from the runnable threads queue
- load CPU registers for next thread
(Here I am focusing only on things inside a single process, ignoring context switches between processes.)
§Measurement
The following is a simple ping-pong example using mutex + condition variable.
1 |
|
1 | $ clang++ -O -std=c++20 context_switch.cpp && taskset -c 0 ./a.out |
As a crude approximation, one can assume both kinds of switches have the same cost and each context-switch takes ~1.3
microseconds. Additionally, the elapsed time includes also use-mode operations (for-loop, accessing flag
, etc), so
this is an overestimate.
One can use perf
to get a quick glance at the user/kernel-mode distribution, reported by user
, and sys
,
respectively.
1 | $ clang++ -O -std=c++20 context_switch.cpp && perf stat taskset -c 0 ./a.out |
We can see that user
time is ~10% of sys
time. Therefore, the overestimate is roughly off by ~10%, 0.1 microseconds.
Note that “Elapsed time” has increased to 132ms, so the overhead of perf
could have skewed those statistics a bit.
Nonetheless, one can use 1 microsecond as the latency of context switch for a back-of-the-envelope calculation.
§ENV
1 | Clang : 14 |
§References
https://medium.com/geekculture/linux-cpu-context-switch-deep-dive-764bfdae4f01