ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Linux I/O 스케줄러(cfq, deadline, noop)
    커널(Kernel) 2022. 12. 26. 21:14

     

    환경 정보

    OS: ubuntu18.04 

     

     

    I/O 발생 흐름

    1. 사용자는 읽기나 쓰기를 통해서 I/O를 발생시킨다.

    2. 발생한 I/O는 가상 파일 시스템이나 로컬 파일시스템 경로를 거친다.  

    3. 파일 시스템을 거친 I/O는 I/O 스케줄러를 통해 가공되고(병합, 정렬) 언제 블록 디바이스에 접근할지 정해진다. 

    4. 블록 디바이스에 접근해서 데이터를 읽거나 쓴다. 

     

     

    I/O 스케줄러가 필요한 이유

    우리가 사용하는 디스크는 크게 HDD와 SSD가 있다. 

    HDD의 경우, 디스크 헤더를 움직여 데이터가 저장되어 있는 섹션에서 데이터를 읽거나 쓴다. 

    여러 데이터를 읽거나 쓰기 위해 헤더를 이리저리 움직이는 것은 시간을 많이 사용하게 되고, 결국은 성능 저하를 만든다.  

    마찬가지로 SSD 또한 한 번에 읽을 수 있는 데이터를 여러 번 접근해서 읽게 되면 성능 저하를 만들 수 있다. 

     

    위와 같은 성능 저하는 I/O 스케줄러를 통해 디스크 헤더의 움직임을 최소화하거나

    여러번 접근할 데이터를 한 번에 접근하는 방식을 사용하여 어느 정도 개선할 수 있다. 

     

    I/O 스케줄러가 I/O 성능을 높이는 방식

    I/O 스케줄러는 병합과 정렬을 이용해서 블록 디바이스 접근 시간을 최소화한다.  

     

    병합은 여러 개의 요청을 하나로 합쳐서 처리하는 방식이고,

    정렬은 여러개의 요청을 섹터 순서대로 재배치하여 처리하는 방식이다. 

     

    참고로 HDD의 경우 정렬을 통해 헤더의 움직임을 줄일 수 있지만,

    플래시 메모리인 SSD는 전기적 동작을 통해서 데이터를 참조하므로 정렬이 큰 의미가 없다. 

     

     

    현재 사용중인 I/O 스케줄러 확인하기 

    /sys/block/[block 장치]/queue/scheduler 경로에서 확인할 수 있다. 

     

    현재 사용중인 scheduler는 cfq이고, 다음은 cfq에 대한 파라미터들이다.

     

    신기하게도 스케줄러를 변경하면 파라미터들 또한 바뀐다. 

     

     

    I/O 스케줄러의 종류 

    1. cfq I/O 스케줄러

    cfq는 completely fair queuing의 약자로, 프로세스들에서 발생하는 I/O 작업들을 균등하게 실행시키는 것을 말한다. 

    cfq I/O 스케줄러는 I/O의 우선순위에 따라 RT(Real Time), BE(Best Effort), IDLE 중 하나로 I/O 요청을 보낸다.  

    참고로 어떤 곳으로 요청을 보낼지는 ionice 명령을 통해서 변경할 수 있다. 

     

    대부분의 I/O 요청들은 BE로 가고, RT는 우선순위가 높은 I/O, IDLE에는 우선순위가 낮은 I/O 요청들이 간다. 

    이렇게 셋 중 하나로 분류된 후, service tree라 불리는 워크로드별로 그룹을 다시 나눈다. 

    서비스 트리는 SYNC, SYNC_NOIDLE, ASYNC로 구성되는데, 

     

    SYNC는 순차적인 동기화로 주로 순차 읽기가 해당된다.

    I/O 요청은 큐에 대기한 후에 가까운 곳의 I/O 요청과 함께 처리하여 성능을 높인다. 

     

    SYNC_NOIDLE는 임의적인 동기화 I/O 작업으로 랜덤 읽기가 해당된다.  

    각각의 큐에 대한 처리를 완료한 후 대기 시간 없이 바로 다음 큐에 대한 I/O 작업을 시작한다. 

    다음 요청을 기다려서 얻게 되는 성능상의 이점이 없기 때문에 대기시간 없이 바로 I/O 작업을 시작한다. 

     

    ASYNC는 비동기화 I/O 작업으로 쓰기가 해당된다. 

    cfq는 프로세스별로 요청 큐를 할당하고 프로세스 별로 타임 슬라이스에 맞게 동기화 I/O 작업을 처리한다.

    반면, 비동기 I/O 작업은 ASYNC 서비스 트리 밑에서 한 번에 모아 놓고 처리한다. 

     

    정리하자면, cfq I/O 스케줄러로 들어오는 I/O 요청들은 각 프로세스들에 대한 queue에 들어가게 된다. 

    그리고 동일한 time slice를 할당한 다음 이 값을 기준으로 큐들을 순차적으로 처리한다. 

     

    이러한 cfq I/O 스케줄러는 모든 프로세스들에게 공평하게 I/O 요청 처리 기회를 주지만,

    I/O를 많이 일으키거나 I/O 우선순위가 높은 프로세스의 경우

    자신의 차례가 오기까지 시간이 걸리기 때문에 성능이 낮아질 수 있다. 

     

     

    2. deadline I/O 스케줄러

    deadline I/O 스케줄러는 I/O 요청 별로 완료되어야 하는 deadline을 가지고 있는 스케줄러다. 

     

    예를 들면 읽기 요청은 500ms안에 완료되어야 하고,

    쓰기 요청은 5s안에 완료되어야 하는 데드라인이 존재하는 것이다. 

    가능한 데드라인이 넘지 않도록 동작하지만, 100%는 데드라인을 맞출 수는 없다. 

     

    deadline I/O 스케줄러의 경우, 읽기와 쓰기에 따라 sorted list와 fifo list가 존재한다.  

    sorted list는 I/O 요청을 섹터 기준으로 정렬하고, fifo list는 요청이 발생한 시간을 기준으로 정렬한다. 

    평상시에는 sorted list에서 정렬되어 상태의 요청을 꺼내서 처리한다. 

    그리고 fifo list에 있는 요청 중 deadline을 넘긴 요청이 있다면, fifo list에서 꺼내 요청을 처리 후, 

    sorted list를 재정렬해서 그 이후의 I/O를 처리한다. 

     

     

    3. noop I/O 스케줄러

    가장 간단한 형태의 I/O 스케줄러로 정렬은 하지 않고, 병합 작업만 한다. 

    헤더의 움직임을 최소화할 필요가 없는 SSD 블록 디바이스에 적합하다. 

    SSD는 deadline I/O 스케줄러이나 cfq I/O 스케줄러를 사용하면 오히려 정렬하는데 시간을 써서 성능이 더 안 좋아질 수 있다. 

    참고로 noop I/O 스케줄러는 파라미터가 존재하지 않는다. 

     

     

    워크로드에 따라 효율적인 I/O 스케줄러

    1. 웹서버

    웹서버에서 가장 많이 발생하는 I/O 요청은 사용자의 요청에 대한 로그 기록이다.  

    그리고 로그 기록은 로그 파일을 덧붙여 나가는 방식이기 때문에 순차접근 방식을 동작한다.  

    순차 접근 자체는 헤드의 움직임이 최소화되어 있기 때문에 I/O 스케줄러 자체가 성능에 큰 영향을 주지는 않는다. 

    따라서 deadline, cfq I/O 스케줄러 둘다 비슷한 효율을 낸다. 

     

    2. 파일 서버

    파일 서버에서는 임의 접근이 많이 일어난다. 

    이때는 프로세스 수가 많아질수록 deadline I/O 스케줄러가 cfq /O 스케줄러보다 더 좋은 성능을 낸다.

    deadline의 경우 여러 프로세스에서 발생한 I/O 요청을 함께 정렬해서 처리하는 반면,

    cfq의 경우 각 프로세스 별로 정렬한 요청을 여러 프로세스에 걸쳐 수행하기 때문에 헤더의 이동이 많이 

    발생할 수 밖에 없다. 

     

    3. 동영상 스트리밍, 인코딩 처리 서버 

    다수의 프로세스가 다수의 사용자로부터 받은 스트리밍 혹은 요청을 처리해야 한다. 

    이러한 워크로드는 프로세스 별로 균등하게 I/O 작업이 필요한 경우다. 

    이때는 deadline보다 cfq I/O 스케줄러가 모든 프로세스에 걸쳐 균등하게 I/O를 처리할 수 있기 때문에 성능이 더 좋다. 

     

    4. DB 서버

    DB처럼 특정 프로세스가 많은 양의 I/O 요청을 하는 경우가 있는데 이러한 케이스는 deadline I/O 스케줄러가 효율적이다. 

    타임 슬라이스에 따라서 특정 프로세스의 I/O 요청이 처리되지 않는 idle 타임이 존재하지 않고,

    I/O 요청 발생 시간을 기준으로 처리되기 때문이다. 

     

     

    Reference

    Devops와 SE를 위한 리눅스 커널 이야기 

    반응형

    댓글

Designed by Tistory.