When Does Thrashing Occur in operating systems, what causes it, how it affects performance, and the best techniques to prevent it.
It was a late evening, and I was working on my laptop with multiple browser tabs, a code editor, and a few background applications running. Suddenly, everything began to lag — the cursor froze, apps stopped responding, and the hard drive light kept blinking continuously. That’s when I realized I was witnessing what operating system experts call thrashing.
So, when does thrashing occur exactly?
Thrashing occurs when an operating system spends more time swapping data between the main memory (RAM) and the disk than executing actual processes. This happens because the system runs too many programs simultaneously, exceeding the available memory, which causes constant page replacements and slows down performance dramatically.
In this guide, we’ll break down why thrashing happens, how it affects performance, and what can be done to prevent it, explained in simple, easy-to-understand language.
Introduction of When Does Thrashing Occur
If you’ve ever noticed your computer suddenly slowing down, even though your processor isn’t fully used, chances are thrashing might be the reason.
In operating systems, thrashing occurs when your system spends more time swapping pages between main memory and disk than executing actual processes. It’s one of the most serious performance issues in virtual memory management.
Let’s dive deeper to understand when and why thrashing occurs, what it does to your system, and how to avoid it effectively.
What Is Thrashing in Operating Systems?
In simple terms, thrashing happens when the CPU is busy handling page faults instead of executing processes.
This means the system is continuously swapping pages in and out of main memory (RAM) because there isn’t enough physical memory to handle the workload.
When this happens, the CPU utilization drops dramatically, and the system appears to “freeze” or “hang.”
When Does Thrashing Occur?
Thrashing typically occurs when the system’s degree of multiprogramming is too high — in other words, when too many processes are running simultaneously and there’s not enough memory to support all their pages.
Here’s the step-by-step sequence of events that lead to thrashing:
- High Degree of Multiprogramming:
The operating system allows too many processes to run at once to maximize CPU utilization. - Insufficient Physical Memory:
Each process requires a certain number of pages to execute efficiently. If the total demand for memory exceeds available RAM, pages must be swapped out frequently. - Frequent Page Faults:
As processes execute, they continuously reference pages not currently in memory, causing repeated page faults. - Increased Page Swapping:
The OS continuously swaps pages between main memory and disk to satisfy these page faults. - System Overhead:
The CPU spends most of its time performing paging operations instead of useful computation. - Performance Collapse:
CPU utilization falls drastically, and overall system performance declines — this state is known as thrashing.
Example of Thrashing
Imagine a system with only 2 GB of RAM and 5 active processes, each needing 1 GB of memory.
- Initially, all processes load some of their pages into memory.
- As they execute, each process needs more pages, causing frequent page faults.
- The OS keeps swapping pages in and out to accommodate them.
The system eventually spends more time paging than processing, leading to thrashing.
Effects of Thrashing
Thrashing can severely impact system performance. Here’s what happens:
- CPU Utilization Drops: Because the processor is mostly waiting for paging operations to complete.
- System Becomes Unresponsive: Programs take too long to respond.
- Disk I/O Increases: Excessive page swapping puts heavy load on disk drives.
- Power Consumption Rises: Due to unnecessary read/write cycles.
- Overall Throughput Decreases: The number of processes completed per unit time falls drastically.
How to Detect Thrashing
Operating systems use monitoring tools to detect thrashing based on the following signs:
- High page fault rate
- Low CPU utilization despite high multiprogramming
- Increased I/O activity (especially disk operations)
- Sluggish system response
Tools like Task Manager (Windows) or top/vmstat (Linux) can help observe these symptoms.
How to Prevent or Control Thrashing
Here are the most effective ways to prevent or control thrashing in an operating system:
1. Reduce Degree of Multiprogramming
Decrease the number of active processes so that each has enough memory to execute efficiently.
2. Use Local Replacement Algorithms
Local page replacement ensures that a process only replaces its own pages, preventing interference from others.
3. Increase Physical Memory (RAM)
Adding more RAM can significantly reduce the chances of thrashing.
4. Implement Working Set Model
The OS tracks the working set (the set of pages a process is actively using). Ensuring all working sets fit in memory minimizes page faults.
5. Use Page Fault Frequency (PFF) Control
The OS monitors the page fault rate and dynamically adjusts the degree of multiprogramming.
Thrashing vs. High Paging
| Parameter | High Paging | Thrashing |
|---|---|---|
| Definition | Occasional page faults occur | Continuous excessive paging |
| CPU Utilization | Slightly affected | Drastically reduced |
| Cause | Moderate memory shortage | Severe memory shortage |
| Solution | Optimize memory allocation | Reduce multiprogramming, add RAM |
Real-World Example
When you open too many browser tabs, run multiple heavy apps, or play games alongside background downloads, your system might run out of RAM.
Your OS then starts using the swap file (virtual memory on disk) to compensate. When this swap activity becomes excessive — your laptop starts lagging — that’s thrashing in action.
Key Takeaways
Thrashing occurs when the system spends more time swapping pages than executing processes.
It happens mainly due to high multiprogramming and insufficient memory.
Prevention techniques: Reduce process load, use the working set model, increase RAM, and monitor page fault rates.
C code for Thrashing
/**
* thrash_demo.c
*
* Demonstrates memory pressure / heavy paging behavior.
* Usage: ./thrash_demo
* - size_in_MB: amount of memory to allocate (in MB)
* - access_iterations: number of page accesses to perform
* - access_pattern: 0 = sequential, 1 = random
*
* Notes:
* - Compile with: gcc -O0 -std=c11 -Wall thrash_demo.c -o thrash_demo
* - Run with caution (may trigger swapping).
*/
#define _POSIX_C_SOURCE 200809L
#include
#include
#include
#include
#include
#include
#include
#include
static long get_page_size(void) {
long ps = sysconf(_SC_PAGESIZE);
if (ps <= 0) ps = 4096;
return ps;
}
static void print_rusage_delta(struct rusage *before, struct rusage *after) {
long minflt = after->ru_minflt - before->ru_minflt;
long majflt = after->ru_majflt - before->ru_majflt;
printf("Page faults during run: minor = %ld, major = %ld\n", minflt, majflt);
}
static double timespec_diff_sec(const struct timespec *a, const struct timespec *b) {
return (b->tv_sec - a->tv_sec) + (b->tv_nsec - a->tv_nsec) / 1e9;
}
int main(int argc, char **argv) {
if (argc < 4) {
fprintf(stderr, "Usage: %s \n", argv[0]);
fprintf(stderr, " access_pattern: 0 = sequential, 1 = random\n");
return 1;
}
size_t size_mb = strtoull(argv[1], NULL, 10);
unsigned long iterations = strtoul(argv[2], NULL, 10);
int pattern = atoi(argv[3]);
long page_size = get_page_size();
size_t buf_bytes = size_mb * 1024ULL * 1024ULL;
size_t pages = (buf_bytes + (page_size - 1)) / page_size;
printf("Allocating %zu MB (%zu bytes), page size = %ld, pages = %zu\n",
size_mb, buf_bytes, page_size, pages);
// Try to allocate
uint8_t *buf = malloc(buf_bytes);
if (!buf) {
perror("malloc");
fprintf(stderr, "Allocation failed. Try smaller size.\n");
return 1;
}
// Touch each page once (warm up) to map into page table (this will still allow swapping later)
printf("Warming up: touching each page once to create mappings...\n");
for (size_t i = 0; i < buf_bytes; i += page_size) {
buf[i] = (uint8_t)(i & 0xFF);
}
// Get initial resource usage
struct rusage ru_before, ru_after;
if (getrusage(RUSAGE_SELF, &ru_before) != 0) {
perror("getrusage");
}
// Prepare random index generator if needed
srand((unsigned int)time(NULL) ^ (unsigned int)getpid());
// Start timer
struct timespec t_start, t_end;
clock_gettime(CLOCK_MONOTONIC, &t_start);
// Access pattern: either sequential over pages or random page accesses
for (unsigned long it = 0; it < iterations; ++it) {
size_t page_index;
if (pattern == 0) {
// sequential: cycle over pages
page_index = it % pages;
} else {
// random: pick a page at random
page_index = (size_t) ( ((uint64_t)rand() << 31 | rand()) % pages );
}
size_t offset = page_index * (size_t)page_size;
// perform read+write to ensure write-back behavior
uint8_t val = buf[offset];
buf[offset] = val + 1;
}
clock_gettime(CLOCK_MONOTONIC, &t_end);
// Collect resource usage after run
if (getrusage(RUSAGE_SELF, &ru_after) != 0) {
perror("getrusage");
}
double elapsed = timespec_diff_sec(&t_start, &t_end);
printf("Accesses performed: %lu\n", iterations);
printf("Elapsed time: %.3f seconds\n", elapsed);
double accesses_per_sec = iterations / (elapsed > 0.0 ? elapsed : 1.0);
printf("Accesses/sec: %.0f\n", accesses_per_sec);
print_rusage_delta(&ru_before, &ru_after);
// Print simple heuristic: if many major faults occurred, likely swap I/O happened
long majfaults = ru_after.ru_majflt - ru_before.ru_majflt;
if (majfaults > 0) {
printf("Major page faults occurred (%ld) — data was loaded from disk (swap) during run.\n", majfaults);
printf("This indicates heavy paging and could be a sign of thrashing if sustained with high CPU waits.\n");
} else {
printf("No major page faults observed during run. (Minor faults may still indicate page-table activity.)\n");
}
free(buf);
return 0;
} What the output means
Page faults during run: minor = X, major = Y- Minor faults: page mapped but not in RAM (lightweight) or copy-on-write type — not from disk.
- Major faults: OS had to read page from disk (swap) — expensive and slows execution.
- If you see many major faults and elapsed time is high, your test caused disk I/O for memory pages — this is the behavior that in extreme, sustained cases leads to thrashing.
- If CPU utilization falls while major faults + I/O is very high on the system, that’s consistent with thrashing: the OS spends more time moving pages than running processes.
How this ties to “When does thrashing occur”
- Use this program to create memory pressure. When the sum of working sets of running processes exceeds available RAM, you’ll observe many major page faults as the OS swaps — that’s when thrashing can occur.
- Real thrashing typically requires multiple processes competing for memory (not just a single test program). You can run multiple instances of this program or other memory-hungry apps simultaneously to reproduce a thrashing-like scenario
FAQ: When Does Thrashing Occur?
Q1. What exactly causes thrashing in an operating system?
Thrashing occurs when the total demand for memory by all active processes exceeds the available physical memory, leading to excessive paging.
Q2. How can you tell if your system is thrashing?
If CPU usage drops while disk usage spikes and applications freeze or respond slowly, your system is likely thrashing.
Q3. What is the main solution to prevent thrashing?
Reduce the degree of multiprogramming or increase the amount of physical memory (RAM).
Q4. Is thrashing common in modern systems?
Modern OSs use smart memory management algorithms to minimize thrashing, but it can still occur during heavy multitasking or with limited RAM.
Q5. What happens to CPU utilization during thrashing?
It decreases sharply because most CPU cycles are wasted handling page faults rather than executing processes.
Common Follow-up Question:
Conclusion
Thrashing is one of the most critical performance problems in operating systems. It happens when the system is overloaded with too many active processes, leading to constant page swapping between RAM and disk.
By understanding when thrashing occurs, you can optimize memory usage, manage processes efficiently, and keep your system running smoothly.
Mr. Raj Kumar is a highly experienced Technical Content Engineer with 7 years of dedicated expertise in the intricate field of embedded systems. At Embedded Prep, Raj is at the forefront of creating and curating high-quality technical content designed to educate and empower aspiring and seasoned professionals in the embedded domain.
Throughout his career, Raj has honed a unique skill set that bridges the gap between deep technical understanding and effective communication. His work encompasses a wide range of educational materials, including in-depth tutorials, practical guides, course modules, and insightful articles focused on embedded hardware and software solutions. He possesses a strong grasp of embedded architectures, microcontrollers, real-time operating systems (RTOS), firmware development, and various communication protocols relevant to the embedded industry.
Raj is adept at collaborating closely with subject matter experts, engineers, and instructional designers to ensure the accuracy, completeness, and pedagogical effectiveness of the content. His meticulous attention to detail and commitment to clarity are instrumental in transforming complex embedded concepts into easily digestible and engaging learning experiences. At Embedded Prep, he plays a crucial role in building a robust knowledge base that helps learners master the complexities of embedded technologies.












