PFF로 페이지 부재율에 맞춰 프레임 조정하기
PFF(Page Fault Frequency)의 임계값 기반 프레임 조정 방식과 Working Set, 페이지 교체 알고리즘과의 관계를 정리한다.
2026-08-14 · 최초 발행 2026-01-04
페이지 부재율이 프레임 할당의 신호가 된다
페이지 부재 빈도(Page Fault Frequency, PFF)는 프로세스에서 발생하는 페이지 부재율을 보고 메모리 할당량을 조절하는 방식이다. 프로세스마다 상한과 하한을 두고 현재 부재율을 측정한 뒤, 부족한 프로세스에는 페이지 프레임을 더 주고 여유가 있는 프로세스에서는 프레임을 회수한다. 목적은 트래싱을 막으면서 메모리를 필요한 곳에 배분하는 데 있다.
PFF는 단위 시간 또는 참조 횟수당 페이지 부재가 얼마나 발생했는지를 나타낸다.
- PFF = (페이지 부재 횟수) / (시간 또는 참조 횟수)
- 프로세스의 메모리 부족 정도를 나타내는 지표
- 동적 메모리 할당의 기준으로 활용
상한을 넘는 PFF는 메모리 부족을, 하한보다 낮은 PFF는 과다 할당을 뜻한다. 이 두 경계 사이에서는 프레임 수를 유지한다.
Working Set이 필요한 메모리량을 예측해 미리 대응하는 방식이라면, PFF는 실제 페이지 부재가 발생한 뒤 측정값을 바탕으로 조정한다. 두 기법 모두 트래싱 방지가 목표지만, PFF는 구현과 오버헤드 측면에서 유리하다.
임계값을 넘었을 때 프레임을 재배분하는 흐름
상한선(Upper Bound, U)은 허용 가능한 최대 페이지 부재율이고, 하한선(Lower Bound, L)은 프레임을 과다하게 할당했다고 판단하는 기준이다. 예를 들어 상한은 1000번 참조당 50회 페이지 부재(5%), 하한은 1000번 참조당 10회 페이지 부재(1%)로 둘 수 있다. 실제 값은 시스템 특성과 워크로드에 맞춰 조정해야 한다.
PFF는 일정 시간마다 부재 횟수를 집계하는 시간 기반 방식이나, 일정 페이지 참조 횟수마다 계산하는 참조 기반 방식으로 측정할 수 있다. 최근 N개 샘플의 평균을 쓰는 이동 평균(Moving Average), 최근 값에 더 높은 가중치를 주는 지수 가중 평균(EWMA)도 사용할 수 있다.
현재 시점의 PFF는 다음처럼 계산한다.
PFF(t) = Faults(t) / References(t)
PFF > U이면 메모리가 부족한 상태다. 가용 프레임이 있으면 추가로 할당하고, 없으면 다른 프로세스에서 회수하거나 프로세스를 스왑 아웃한다.L ≤ PFF ≤ U이면 현재 할당을 유지한다.PFF < L이면 일부 프레임을 회수해 가용 풀로 돌려보낸다. 회수된 프레임은 다른 프로세스에 배정할 수 있다.
단순한 측정값으로 얻는 이점과 운영상 제약
PFF는 페이지 부재 카운터와 주기적 비교만으로 동작하므로 Working Set보다 구조가 단순하고 하드웨어 지원도 최소화할 수 있다. 시간 창(Δ)을 설정할 필요가 없으며, 기존 페이지 교체 알고리즘과 독립적으로 사용할 수 있다.
실시간 피드백을 바탕으로 프레임 수를 바꾸므로 프로세스의 지역성이나 워크로드가 바뀌었을 때 자동으로 대응한다. 프로세스별 실제 수요를 기준으로 배정해 자원 독점을 막고, 다중 프로그래밍 수준을 조절하는 데도 활용할 수 있다. 카운터 증가와 주기적 비교만 필요하므로 오버헤드와 CPU 사용률을 낮추면서 메모리 활용도를 높일 수 있다.
반면 PFF는 페이지 부재가 발생한 뒤에야 반응한다. 지역성이 급격히 바뀌면 일시적인 성능 저하가 생길 수 있다. 상한과 하한의 적절한 값을 찾기 어렵고, 워크로드에 맞지 않는 설정은 성능을 오히려 떨어뜨릴 수 있다.
프레임을 자주 할당하고 회수하면 단편화가 발생할 수 있으며, 연속 메모리 할당이 어려워질 수 있다. 시스템 전체 메모리가 부족한 상황에서는 여러 프로세스 중 어느 프로세스에서 프레임을 회수하거나 스왑 아웃할지 우선순위도 결정해야 한다.
Working Set, 고정 할당, 페이지 교체 알고리즘의 역할
| 구분 | PFF | Working Set |
|---|---|---|
| 접근 방식 | 반응적(Reactive) | 예측적(Proactive) |
| 구현 복잡도 | 낮음 | 높음 |
| 오버헤드 | 낮음 | 높음 |
| 정확도 | 실측 기반 | 이론 기반 |
| 파라미터 | 상한/하한 | 시간 창 Δ |
고정 할당과 비교하면 PFF는 프레임 수를 동적으로 조정하므로 메모리 효율성과 적응성이 높다. 대신 구현 복잡도는 중간 수준이며, 고정 할당은 단순하지만 유연성과 적응성이 없다.
PFF는 프로세스에 할당할 프레임 수를 정하고, LRU나 Clock 같은 페이지 교체 알고리즘은 어떤 페이지를 내보낼지 정한다. 두 역할을 결합하면 프레임 수와 교체 대상을 함께 관리할 수 있다.
측정과 조정을 코드로 구성하는 방식
프로세스별로 페이지 부재 횟수, 참조 횟수, 현재 PFF, 프레임 수, 마지막 검사 시각을 관리할 수 있다.
struct pff_info {
unsigned long faults; // 페이지 부재 횟수
unsigned long references; // 총 참조 횟수
double pff_rate; // 현재 PFF
unsigned int frames; // 할당된 프레임 수
unsigned long last_check; // 마지막 검사 시각
};
측정한 PFF가 상한을 초과하면 가용 프레임을 할당하고, 하한 아래라면 최소 프레임을 고려해 일부를 회수한다. 조정이 끝난 뒤에는 다음 측정을 위해 카운터를 초기화한다.
void adjust_frames_by_pff(struct process *proc) {
// PFF 계산
double pff = (double)proc->faults / proc->references;
proc->pff_rate = pff;
// 임계값 비교 및 조정
if (pff > PFF_UPPER_THRESHOLD) {
if (available_frames > 0) {
proc->frames += FRAME_INCREMENT;
available_frames -= FRAME_INCREMENT;
} else {
// 다른 프로세스에서 회수 또는 스왑 아웃
swap_out_victim_process();
}
} else if (pff < PFF_LOWER_THRESHOLD) {
int reclaim = min(FRAME_DECREMENT, proc->frames - MIN_FRAMES);
proc->frames -= reclaim;
available_frames += reclaim;
}
// 카운터 리셋
proc->faults = 0;
proc->references = 0;
}
모니터는 일정 간격으로 모든 프로세스를 순회하며 조정 함수를 호출한다.
void pff_monitor(void) {
while (1) {
sleep(PFF_CHECK_INTERVAL); // 예: 1초마다
for (each_process(proc)) {
adjust_frames_by_pff(proc);
}
}
}
워크로드에 맞춰 임계값과 주기를 조정할 때
일반 대화형 시스템에서는 U=5%, L=1%, 배치 처리 시스템에서는 U=10%, L=2%, 실시간 시스템에서는 U=2%, L=0.5%를 기준으로 둘 수 있다. 실제 환경에서는 시스템 특성에 맞춰 실험적으로 조정해야 한다.
측정 주기가 너무 짧으면 오버헤드가 늘고 조정이 불안정해질 수 있다. 반대로 너무 길면 반응이 늦어져 트래싱 위험이 커진다. 권장 측정 주기는 15초 또는 10005000 페이지 참조다.
프레임 조정량도 균형이 필요하다. 한 번에 너무 많이 조정하면 불안정해지고, 너무 적게 조정하면 대응이 느려진다. 전체 프레임의 5~10% 단위로 조정하는 방식을 사용할 수 있다.