가상메모리 스래싱의 징후와 페이지 부재 제어 전략
가상메모리 스래싱의 발생 원인과 증상을 짚고, Working-Set Model·PFF를 활용한 프레임 할당 및 회피 전략을 정리한다.
2026-08-14 · 최초 발행 2025-12-28
CPU는 쉬는데 디스크만 바쁜 상태
스래싱(Thrashing)은 프로세스가 실제 작업보다 페이지 교체에 더 많은 시간을 쓰는 현상이다. 페이지 부재(Page Fault)가 계속 발생하면 CPU는 페이징 작업을 기다리게 되고, CPU 이용률은 낮은데 디스크 I/O는 과도하게 높아진다. 이 상태에서는 시스템 전체 처리량(Throughput)이 급격히 감소한다.
다중 프로그래밍 정도를 높이는 과정이 오히려 스래싱을 키우기도 한다. 프로세스가 늘어나면 개별 프로세스에 돌아가는 프레임 수가 줄고, 페이지 부재가 증가한다. CPU 이용률 저하를 보고 운영체제가 다시 다중 프로그래밍 정도를 높이면 같은 순환이 반복된다.
프레임이 부족해지는 경로
물리 메모리가 작업 부하에 비해 부족하면 필요한 페이지를 계속 교체해야 한다. 낮은 CPU 사양은 페이지 교체 처리 자체를 지연시키고, 느린 스왑 디스크는 I/O 병목을 더한다.
페이지 교체 정책도 영향을 준다. FIFO에서는 Belady's Anomaly 문제가 생길 수 있고, LRU는 높은 오버헤드를 가질 수 있다. Clock 알고리즘의 파라미터를 부적절하게 설정하는 경우도 마찬가지다. 메모리 용량을 넘는 수의 프로세스를 동시에 실행하거나, 각 프로세스의 실제 워킹셋 크기를 잘못 판단했을 때도 위험이 커진다.
프로세스의 접근 특성도 봐야 한다. 메모리 참조가 불규칙해 지역성(Locality)이 약하거나, 필요한 페이지 집합이 지나치게 크면 프레임 부족이 빠르게 드러난다. 실행 단계가 바뀌며 워킹셋이 급격히 변하는 경우도 같은 문제를 일으킨다.
워킹셋을 기준으로 다중도를 제어하는 방식
Working Set은 프로세스가 특정 시간 동안 집중적으로 참조하는 페이지 집합이다. 프로그램이 특정 시점에는 일부 페이지만 집중적으로 사용한다는 지역성 원리를 바탕으로, 각 프로세스의 워킹셋을 메모리에 남겨 페이지 부재를 줄이는 접근이다.
최근 Δ 시간 동안 참조된 페이지들의 집합을 워킹셋으로 보고, 프로세스 실행 변화에 따라 이를 계속 갱신한다. 모든 프로세스의 워킹셋 크기 합은 다음과 같이 나타낸다.
D = Σ WSS(i)
D가 물리 메모리 m보다 크면 스래싱 위험이 있고, D가 m 이하라면 안정적으로 실행할 수 있다. D > m인 경우에는 일부 프로세스를 일시 중단하거나 스왑하고, 각 프로세스에는 워킹셋 크기만큼 프레임을 동적으로 할당한다. 중단 대상은 중요도가 낮은 프로세스부터 정할 수 있으며, 워킹셋 변화를 예측해 미리 조정하는 방식도 사용한다.
페이지 부재 빈도로 프레임을 조절하는 방식
Page-Fault Frequency(PFF)는 단위 시간당 발생하는 페이지 부재 횟수다. 워킹셋을 직접 계산하는 방식보다 구현이 간단하고 직관적이어서, 페이지 부재 빈도를 상한과 하한 사이에 유지하도록 프레임을 배분한다.
PFF가 상한을 넘으면 해당 프로세스에 프레임을 추가로 할당한다. 여유 프레임이 없다면 다른 프로세스를 중단해야 한다. 반대로 PFF가 하한보다 낮으면 현재 프로세스의 프레임 일부를 회수해 다른 프로세스에 재할당할 수 있다.
메모리 압박을 줄이는 운영 선택
프로세스를 처음 실행하거나 스왑 뒤에 재개할 때 워킹셋 전체를 미리 적재하는 Prepaging을 적용할 수 있다. 초기 페이지 부재를 대폭 줄일 수 있지만, 예측이 어긋나면 불필요한 페이지를 불러와 자원을 낭비한다.
페이지 크기도 트레이드오프가 있다. 큰 페이지는 페이지 테이블 크기를 줄이고 TLB 효율을 높이지만 내부 단편화가 늘고 필요 없는 데이터까지 적재할 수 있다. 작은 페이지는 세밀한 메모리 관리와 내부 단편화 최소화에 유리한 대신 페이지 테이블과 관리 오버헤드가 커진다. 시스템 특성과 애플리케이션의 접근 패턴에 맞춰 선택해야 한다.
Inverted Page Table은 프로세스마다 별도 페이지 테이블을 두는 대신, 물리 프레임마다 하나의 엔트리를 유지한다. 페이지 테이블 크기와 메모리 오버헤드를 줄일 수 있지만 검색 시간이 늘어나며, 해시 테이블로 이를 보완할 수 있다. 공유 메모리 구현은 더 복잡해진다.
애플리케이션은 관련 데이터를 메모리에서 인접하게 배치하고, 루프를 최적화해 순차 접근 패턴을 만들 수 있다. 불필요한 전역 변수 사용을 줄이고 함수 호출 깊이를 조정해 워킹셋을 작게 유지하는 것도 방법이다. 배열은 행 우선(Row-major)으로 순회하고 캐시 친화적인 자료구조를 쓰는 편이 낫다.
중요한 페이지는 메모리에 고정해 스왑을 막을 수 있다. 커널 코드와 주요 시스템 데이터, 실시간 프로세스의 핵심 페이지, I/O 버퍼와 인터럽트 핸들러가 대상이 된다. 다만 과도한 페이지 로킹은 가용 메모리를 줄이므로 우선순위가 높은 페이지에만 선별적으로 적용한다.
경고 신호를 보고 복구까지 연결하기
CPU 이용률과 디스크 I/O 비율, 평균 페이지 부재 빈도, 프로세스별 워킹셋 크기를 함께 본다. CPU 이용률 < 30% + 디스크 I/O > 80% 상태, 페이지 부재율 급증, 평균 응답 시간의 급격한 증가는 경고 신호다.
예방 단계에서는 적절한 다중 프로그래밍 정도를 유지하고, 프로세스별 최소 프레임을 보장하며, 효율적인 페이지 교체 알고리즘을 선택한다. 조기 감지 단계에서는 PFF와 워킹셋 크기를 추적하고 자원 사용률을 실시간으로 분석한다.
스래싱이 감지되면 일부 프로세스를 일시 중단하고 프레임을 재분배하며 스왑 공간을 확보한다. 시스템이 안정화된 뒤에는 중단했던 프로세스를 다시 실행하고, 장기적인 시스템 튜닝과 물리 메모리 증설을 검토한다.