Linux Context Switching Explained: Voluntary vs Involuntary, vmstat, pidstat, and CPU Performance

Introduction

Because many processes and threads run on Linux, the system performs work by switching the task that executes on the CPU.

When switching tasks, Linux saves execution state such as CPU registers and the program counter so that processing can resume later, then restores the state of the next task. This operation is called a context switch.

Context switching is necessary for multiple tasks to share a CPU, but saving and restoring state also introduces overhead. It is therefore an important mechanism to understand when analyzing CPU performance.

This article explains how context switches work, when they occur, how they affect performance, and how to inspect them on Linux.

What Is a Context Switch?

A context switch is the process of saving the execution state of the current task and switching the CPU to another task so that the next task can resume execution.

Many processes and threads run on Linux, but a single CPU core can generally execute only one task at any given moment. The system must therefore switch between tasks to allow multiple tasks to share a CPU.

Common situations in which a context switch occurs include:

• A task releases the CPU while waiting for I/O
• A task waits because of sleep or a lock
• The scheduler selects another task

For example, suppose the CPU scheduler decides to run Task B next while Task A is executing on the CPU. The general sequence is as follows:

The important point here is the operation of saving and restoring execution state.

What Is a Context?

A context is the execution state a task needs to continue running on the CPU. Typical examples include CPU registers, the program counter, and the stack pointer.

Suppose Task A switches to Task B while performing a calculation on the CPU. If Task A’s execution state were not saved before the switch, the system would not know which instruction to resume from or what values had been stored in its registers when Task A was assigned the CPU again. The Linux kernel therefore saves the state required to execute Task A before restoring the state of Task B.

If Task A later runs on the CPU again, restoring its saved state allows it to resume from where it was interrupted.

Relationship with the CPU Scheduler

The CPU scheduler and context switches are closely related. The CPU scheduler selects which runnable task will execute on the CPU next.

A context switch, on the other hand, is the operation that actually changes the task executing on the CPU after the scheduler changes its selection. In simplified terms:

CPU scheduler: Selects the next task to run
Context switch: Switches execution from the current task to the next task

This mechanism allows processing to continue by switching among tasks even when the number of tasks exceeds the number of CPU cores.

Voluntary and Involuntary Context Switches

Context switches fall into two categories based on why they occur: voluntary context switches and involuntary context switches.

Understanding this distinction makes it easier to analyze the cause of an increase in context switches.

Voluntary Context Switch

A voluntary context switch occurs when a running task voluntarily releases the CPU. Common causes include waiting for I/O, sleeping, and waiting for a lock.

For example, when a task reads data from storage and waits for the operation to complete, it cannot continue processing on the CPU during that time. The task therefore releases the CPU and waits while another task runs.

Run Task A
↓
I/O wait occurs
↓
Task A releases the CPU
↓
Switch to Task B

A context switch caused by a task releasing the CPU for its own reasons is a voluntary context switch.

Involuntary Context Switch

An involuntary context switch occurs when a running task does not release the CPU voluntarily but is switched out by the scheduler in favor of another task.

For example, while Task A is running, the scheduler may decide that another task should run, interrupt Task A, and assign the CPU to the other task.

Run Task A
↓
The scheduler decides to switch tasks
↓
Interrupt Task A
↓
Switch to Task B

An involuntary context switch occurs when the scheduler causes a running task to give up the CPU in this way.

Summary of the Differences Between Voluntary and Involuntary Context Switches

The differences can be summarized as follows:

TypeMain Causes
VoluntaryI/O wait, sleep, lock wait, and similar causes
InvoluntaryPreemption by the scheduler and similar causes

In other words, the easiest way to understand the distinction is to ask whether the task released the CPU itself or the scheduler took the CPU away from it.

The following diagram illustrates the difference.

The Cost of Context Switching

Context switching is necessary for multiple tasks to share a CPU. However, switching tasks requires the system to save the current task’s execution state and restore the next task’s state, which introduces a certain amount of overhead.

Saving and Restoring Execution State

A context switch saves and restores execution state such as CPU registers, the program counter, and the stack pointer.

Because this operation itself requires CPU time, frequent context switches can reduce the CPU time available for actual application processing.

Impact on the CPU Cache

When the running task changes, the instructions and data required by the next task may not be present in the CPU cache. In that case, the CPU must load data from memory, which can reduce processing performance.

The cost of a context switch therefore extends beyond saving and restoring execution state; it can also affect CPU cache efficiency.

Checking Context Switches on Linux

Linux provides various commands and information under /proc for checking context-switch activity.

You can inspect context switches across the entire system or examine those occurring in a specific process.

The following sections introduce common methods.

Checking the Entire System with vmstat

The vmstat command provides a simple way to check context switches across the entire system. To display statistics at one-second intervals, for example, run:

[root@almalinux ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 2266664  11216 287904    0    0     5    20    0    0  0  0 99  0  0
 0  0      0 2266664  11216 287904    0    0     0     0  697 1143  0  0 100  0  0
 0  0      0 2266664  11216 288036    0    0     0     0  676 1159  0  0 99  0  0
 0  0      0 2266664  11216 288036    0    0     0     8  656 1147  0  0 99  0  0
 0  0      0 2265656  11224 288036    0    0     0    16  806 1234  1  1 99  0  0

To check context switches, focus on cs under system. With vmstat 1, the first line generally shows averages since boot, while subsequent lines show statistics for each one-second interval. In the example above, the interval lines show approximately 1,100 to 1,200 context switches per second.

vmstat also displays r, which indicates the run queue, together with CPU utilization. This allows you to combine observations such as “context switches are increasing,” “the number of runnable tasks is also increasing,” and “CPU utilization is high.”

Checking Individual Processes with pidstat

The pidstat command is useful when you want to determine which processes are generating context switches. Run it as follows. The -w option displays context switches for each process.

[root@almalinux ~]# pidstat -w 1
Linux 5.14.0-570.19.1.el9_6.x86_64 (almalinux)  08/10/2026      _x86_64_        (4 CPU)

10:52:03 PM   UID       PID   cswch/s nvcswch/s  Command
10:52:04 PM     0        16      1.00      0.00  ksoftirqd/0
10:52:04 PM     0        17     11.00      0.00  rcu_preempt
10:52:04 PM     0       418      3.00      1.00  jbd2/sda3-8
10:52:04 PM     0    845637      1.00      0.00  httpd
10:52:04 PM     0   3189679    132.00      0.00  kworker/u16:1-events_unbound
10:52:04 PM     0   3189814      1.00      0.00  kworker/0:2-mm_percpu_wq
10:52:04 PM     0   3189918      2.00      0.00  kworker/2:0-events_power_efficient
10:52:04 PM  1000   3189938      2.00      0.00  sshd

The two main fields are:

FieldMeaning
cswch/sVoluntary context switches per second
nvcswch/sInvoluntary context switches per second

A high cswch/s value may indicate that tasks are releasing the CPU because of I/O waits, sleep, lock waits, or similar causes. In the example above, cswch/s is greater than zero for every displayed task, indicating that voluntary context switches are occurring.

A high nvcswch/s value, on the other hand, may indicate frequent scheduler preemption. In the example above, nvcswch/s for jbd2/sda3-8 is 1.00, indicating approximately one involuntary context switch per second.

A practical approach is to use vmstat to identify an increase in system-wide cs, then use pidstat to investigate which processes are generating many context switches.

Checking /proc/PID/status

You can also check cumulative context-switch counts for a specific task in /proc/PID/status.

[root@almalinux ~]# cat /proc/357466/status
~~Truncated~~

voluntary_ctxt_switches:        1467756
nonvoluntary_ctxt_switches:     849
[root@almalinux ~]#

The output includes the following fields:

voluntary_ctxt_switches: Cumulative number of voluntary context switches
nonvoluntary_ctxt_switches: Cumulative number of involuntary context switches

Whereas pidstat is suitable for checking the rate over a given period, /proc/PID/status shows the accumulated counts for that task.

Checking /proc/PID/sched

For more detailed information about CPU scheduling, use /proc/PID/sched.

[root@almalinux ~]# cat /proc/357466/sched
postmaster (357466, #threads: 1)
-------------------------------------------------------------------
se.exec_start                                :   20292058479.997639
se.vruntime                                  :       1993325.511545
se.sum_exec_runtime                          :       1115646.811401
se.nr_migrations                             :               241860
nr_switches                                  :              1468623
nr_voluntary_switches                        :              1467774
nr_involuntary_switches                      :                  849

Three representative fields are:

nr_switches: Total number of context switches
nr_voluntary_switches: Number of voluntary context switches
nr_involuntary_switches: Number of involuntary context switches

You can also inspect the following CPU-scheduling information:

se.vruntime: Weighted virtual runtime based on the task’s CPU execution time
se.sum_exec_runtime: Cumulative time actually spent running on a CPU
se.nr_migrations: Number of times the task has migrated between CPUs

Choose the Inspection Method Based on Your Goal

When investigating context switches, it is important to select tools based on your goal instead of relying on a single command.

• View the entire system: vmstat
• View the rate for each process: pidstat -w
• View cumulative counts for a specific task: /proc/PID/status
• View details together with scheduling information: /proc/PID/sched

For performance investigations in particular, a straightforward method is to begin with vmstat to identify system-wide trends and, if context-switch activity is high, use pidstat and related tools to narrow down the responsible processes.

However, a high number of context switches alone does not establish that a performance problem exists.

The next section explains which factors to consider when investigating a high context-switch rate.

How to Interpret a High Context-Switch Rate

When investigating Linux performance, you may observe a large number of context switches in vmstat or pidstat. However, a high context-switch count by itself does not necessarily indicate a performance problem.

On systems such as web servers and databases where many processes and threads are active, a high number of context switches is not unusual. What matters is evaluating the count together with CPU utilization, the run queue, and other information.

Check CPU Utilization

CPU utilization is the first metric to check. If the system has spare CPU capacity and application performance is acceptable, a high context-switch rate does not necessarily require action.

However, the following combination may indicate that many tasks are competing for CPU time and causing frequent switches:

• A high context-switch rate
• High CPU utilization
• Degraded application response times

Because vmstat displays both cs and CPU utilization, it is useful for examining overall system trends.

Check the Run Queue

When many tasks are runnable, multiple tasks must wait for an opportunity to execute on a CPU. The r field in vmstat shows the number of runnable tasks that are running on a CPU or waiting to run.

For example, if CPU utilization is high, r remains high, and context-switch activity is also high, many tasks may be competing for CPU time.

In particular, if r remains significantly higher than the number of CPU cores, check whether the CPU has become a bottleneck.

Compare Voluntary and Involuntary Switches

When context-switch activity is high, it is also important to determine whether voluntary or involuntary switches are more common.

A high number of voluntary context switches may indicate that tasks are releasing the CPU because of I/O waits, lock waits, sleep, or similar conditions.

A high number of involuntary context switches may indicate that many runnable tasks exist and scheduler preemption is occurring frequently.

You can use pidstat -w to check both values for each process.

Check the Number of Processes and Threads

An increase in the number of processes or threads is one possible cause of increased context switching.

For example, creating far more threads than the number of CPU cores can increase the number of simultaneously runnable threads and cause the CPU to switch frequently among them.

If context-switch activity suddenly increases, check:

• Whether the number of processes has increased
• Whether the number of threads has increased
• Whether cswch/s or nvcswch/s has increased for a specific process

These observations can help narrow down the cause.

Do Not Judge by Context-Switch Count Alone

There is no universal threshold above which a certain number of context switches per second is considered abnormal. Normal values vary greatly depending on the number of CPU cores, the workload, and the number of processes and threads.

It is therefore important to evaluate context switches together with:

• Context-switch count
• CPU utilization
• Run queue
• Voluntary versus involuntary switches
• Application response times

Continuously collecting normal baseline values also makes it easier to notice changes during an incident, such as a sudden increase in context switches compared with typical operation.

Context-switch activity should not be used as a standalone indicator of a performance problem. Instead, treat it as one clue for understanding what is happening on the CPU.

Conclusion

Linux uses context switches to share CPUs among multiple tasks. During a context switch, the kernel saves the execution state of the current task and restores the state of the next task so that execution can continue from the appropriate point.

Context switches can be voluntary, such as when a task waits for I/O, sleeps, or waits for a lock, or involuntary, such as when the scheduler preempts a running task.

Context switching introduces overhead through saving and restoring execution state and through its effects on CPU cache efficiency. However, a high context-switch rate alone does not necessarily indicate a performance problem.

When troubleshooting CPU performance, evaluate context-switch activity together with CPU utilization, the run queue, voluntary and involuntary switch rates, and application response times. Tools such as vmstat, pidstat, /proc/PID/status, and /proc/PID/sched help you move from a system-wide view to individual tasks and scheduler details.

コメント