디스크 하나를 두고 열 개 프로세스가 동시에 파일을 읽으면 무슨 일이 벌어질까요. 2012년 이탈리아 모데나-레조에밀리아 대학의 Paolo Valente와 Mauro Andreolini가 ACM SYSTOR 학회에 발표한 논문(“Improving Application Responsiveness with the BFQ Disk I/O Scheduler”)은 이 질문에 디스크마다 “예산”이라는 개념을 도입해 답했어요. 그 결과로 나온 스케줄러가 지금도 리눅스 커널에 남아있는 BFQ인데, 도대체 이 “예산 기반 스케줄링”이라는 게 정확히 어떻게 동작하는 걸까요?
BFQ는 무엇인가
BFQ는 Budget Fair Queueing의 약자로, 디스크 처리량 중 일정 비율을 각 애플리케이션에 보장하는 비례-공유(proportional-share) 디스크 스케줄러예요. 논문 원문은 BFQ를 “각 애플리케이션이 원하는 만큼의 디스크 처리량 비율을 보장받으면서도, 전체 처리량이 요동치는 상황에서도 그 보장을 유지하는 스케줄러”라고 정의해요. 흥미로운 건 BFQ가 이미 리눅스 커널에 Checconi와 Valente에 의해 구현되어 실제로 배포되고 있었다는 점이에요. 덕분에 사용자는 영화를 재생하면서 동시에 다른 파일을 다운로드해도 끊김 없이 영상을 볼 수 있는데, 논문은 여기서 한 걸음 더 나아가 “그렇다면 앱을 새로 실행할 때 걸리는 시간, 즉 반응성은 어떨까”라는 문제를 파고들어요.
왜 굳이 “예산”이라는 단위를 쓰는가
BFQ가 예산이라는 단위를 쓰는 이유는 디스크 사용 시간이 아니라 처리한 섹터 수를 기준으로 공정성을 계산하기 위해서예요. BFQ는 각 애플리케이션에 디스크 접근권을 얼마간 독점적으로 부여하는 방식으로 서비스 모델을 구현하는데, 이때 애플리케이션마다 섹터 수 단위로 측정되는 예산을 하나씩 배정해요. 어떤 애플리케이션이 서비스 대상으로 선택되면 그 요청들이 디스크로 하나씩 전달되고, 전달된 요청 크기만큼 예산이 차감돼요.
애플리케이션이 서비스를 멈추는 경우는 논문에서 딱 세 가지로 정리돼요. 첫째는 예산을 다 소진한 경우, 둘째는 유휴 상태가 되면서 마지막 요청이 비동기 요청이었던 경우, 셋째는 예산 타임아웃이 발동한 경우예요. 이 세 조건 중 하나라도 발생하면 BFQ는 새 예산을 계산해서 배정하고, B-WF²Q+라는 내부 페어 큐잉 스케줄러로 다음 순번을 정해요.
디스크를 잠깐 놀리는 “유휴(idling)” 전략이 오히려 이득인 이유
애플리케이션이 유휴 상태가 됐지만 마지막 요청이 동기 요청이었다면, BFQ는 그 애플리케이션을 곧바로 비활성화하지 않아요. 대신 디스크를 잠깐 대기시키면서 같은 애플리케이션이 곧 새 요청을 보낼지 지켜봐요. 이 대기 시간은 탐색(seek) 및 회전 지연 수준으로 짧게 잡히는데, 목적은 뒤이어 올 수 있는 순차적 동기 요청을 놓치지 않고 바로 디스크에 전달하기 위해서예요. 회전형 디스크에서는 이 짧은 대기가 오히려 처리량을 끌어올리는 효과를 내고, 동기 요청에 대한 서비스 보장을 지키는 데도 핵심적인 역할을 해요.
플래시 기반 장치는 랜덤 I/O 처리량 자체가 높아서 얼핏 유휴 대기가 손해처럼 보일 수 있어요. 하지만 대부분의 운영체제가 리드어헤드를 수행하기 때문에 이런 장치에서도 유휴 대기는 여전히 효과를 발휘한다고 논문은 밝혀요. 반대로 랜덤 요청이 이어질 걸 기다리며 디스크를 놀리는 건 회전형이든 비회전형이든 거의 이득이 없어서, BFQ는 랜덤 패턴을 보이는 애플리케이션에는 이 유휴 대기를 자동으로 꺼버려요.
예산 기반 설계가 남긴 숙제
이렇게 예산을 섹터 단위로 배정하는 방식은 처리량과 지연 시간 사이에서 균형을 잡기 위한 설계였지만, 논문은 원래 버전의 BFQ가 로드된 디스크에서 애플리케이션을 새로 실행할 때 걸리는 시간, 즉 반응성 면에서는 약점을 보였다고 짚어요. 큰 애플리케이션을 로딩할 때 다른 프로세스와 똑같은 비율로 디스크 처리량을 나눠 받으면, 필요한 섹터를 전부 읽어들이는 데 시간이 오래 걸릴 수 있기 때문이에요. 이 반응성 문제를 풀기 위해 논문이 실제로 어떤 알고리즘을 손댔는지는, 애플리케이션 순서를 정하는 B-WF²Q+ 스케줄러와 예산을 계산하는 피드백-루프 알고리즘을 각각 뜯어봐야 정확히 이해할 수 있어요.
BFQ의 예산 개념은 결국 “디스크 사용 시간”이 아니라 “실제로 옮긴 섹터 수”를 공정성의 잣대로 삼겠다는 설계 철학에서 출발해요. 이 기본 골격 위에 논문이 추가한 다섯 가지 휴리스틱이 쌓이면서, 최종적으로 BFQ vs CFQ 벤치마크에서 최대 30%에 달하는 처리량 차이로 이어지게 돼요.
자주 묻는 질문
Q1. BFQ는 무슨 뜻인가요?
BFQ는 Budget Fair Queueing의 약자로, 각 애플리케이션에 디스크 사용 '예산'을 섹터 단위로 배분해 공정하게 순서를 정하는 리눅스 디스크 I/O 스케줄러예요.
Q2. BFQ의 예산(budget)은 정확히 무엇을 의미하나요?
예산은 한 애플리케이션이 한 번 디스크 사용권을 받았을 때 처리할 수 있는 섹터 수의 한도예요. 요청이 처리될 때마다 예산이 그만큼 깎이고, 예산을 다 쓰면 다음 애플리케이션 차례로 넘어가요.
Q3. 애플리케이션은 언제 디스크 사용을 멈추나요?
논문 기준으로 예산을 다 소진했을 때, 유휴 상태가 되면서 마지막 요청이 비동기 요청이었을 때, 또는 예산 타임아웃이 발생했을 때 이 세 가지 경우 중 하나면 서비스가 중단돼요.
Q4. 디스크 유휴(idling)는 왜 필요한가요?
동기 요청을 보낸 애플리케이션이 잠시 멈췄을 때 곧바로 다음 애플리케이션으로 넘기지 않고 짧게 기다려주면, 같은 애플리케이션이 이어서 보내는 순차 요청을 놓치지 않아 회전형 디스크의 처리량이 오히려 높아져요.
Q5. BFQ는 SSD에서도 유휴 대기가 도움이 되나요?
SSD는 랜덤 I/O 처리량 자체가 높아서 얼핏 유휴 대기가 손해처럼 보이지만, 대부분의 운영체제가 리드어헤드를 수행하기 때문에 SSD에서도 유휴 대기가 여전히 효과가 있다고 논문은 밝히고 있어요.
Q6. BFQ는 지금도 리눅스 커널 기본 스케줄러인가요?
BFQ는 일부 배포판과 안드로이드 변형판에서 기본 I/O 스케줄러로 채택되어 있고, 현재도 리눅스 커널 공식 소스(block/bfq-iosched.c)에 포함되어 유지보수되고 있어요.
BFQ 비디오 재생 벤치마크: 반응성을 높인 대가로 프레임이 얼마나 떨어졌나
BFQ+의 low-latency 휴리스틱이 반응성을 높이는 대신 소프트 실시간 애플리케이션에 어떤 지연 시간 대가를 요구하는지 논문의 비디오 재생 벤치마크로 확인합니다.
NCQ가 켜지면 디스크 스케줄러 보장이 무너지는 이유 (BFQ 논문 실측)
Native Command Queueing이 활성화되면 BFQ, CFQ 같은 OS 스케줄러의 공정성·지연 보장이 어떻게 무력화되는지 논문의 실측 데이터로 설명합니다.
BFQ+ vs BFQ vs CFQ 실측 벤치마크: 처리량과 앱 기동 시간 비교
BFQ 논문이 세 대의 리눅스 시스템에서 실측한 집계 처리량과 bash·konsole 기동 시간 벤치마크 결과를 수치 그대로 정리합니다.