(멀티태스킹 개념을 아셔야 이해하실 수 있습니다)
👉 컴공 맛집 백엔드 전문 채널 쉬운코드 유튭 구경 가기
멀티태스킹이란?
멀티태스킹 방식은 CPU 사용 시간을 아주 짧게 쪼개서 time slice 단위로 여러 스레드들이 번갈아 CPU에서 실행될 수 있도록 하는 방식이다
(스레드들은 같은 프로세스 소속일 수도 있고 다른 프로세스 소속일 수도 있다)
time slice가 '고정'값일까?
결론부터 얘기하면 OS 마다 다르겠지만 적어도 리눅스에서는 고정이 아니다
time slice가 '고정'값이면 어떤 문제가 생길까?
아래 그림을 보자
멀티태스킹 방식으로 동작하는 세 가지 경우를 묘사한 그림이다
(1)번
스레드 t1, t2가 CPU에서 멀티태스킹으로 동작하는 방식이다
(2)번
time slice가 고정된 값일 때, t1, t2, t3가 CPU에서 멀티태스킹으로 동작하는 방식이다
즉, 한 스레드가 실행되고 다시 자기 차례가 올 때까지의 시간이 (1)에 비해 꽤 길어진다
만약 동시에 실행돼야 하는 스레드 수가 계속 늘어난다면, 스레드가 실행되고 다시 자기 차례가 올 때 까지 기다리는 시간 또한 점점 더 길어지게 될 것이다
그리고 그만큼 스레드의 응답성도 떨어지게 된다
(3)번
동시에 실행되는 스레드 수에 따라 time slice를 조정하는 방식이다
(1)번에 비해 스레드 수가 하나 늘었기 때문에 더 짧은 시간 간격으로 스레드들이 CPU에서 교체될 수 있도록 time slice가 조정됐다
만약 스레드 수가 계속 늘어난다면, time slice도 더 짧아지면서 스레드가 다시 자기 차례가 올 때까지 기다리는 시간이 (2)번에 비해 현저히 짧아지게 될 것이다
그리고 그만큼 스레드의 응답성도 좋게 유지된다
리눅스의 CFS는 time slice를 조정한다
(다른 OS는 모르겠지만) 리눅스에서는 time slice가 유동적으로 바뀐다
리눅스에서는 프로세스/스레드 개념은 추상화된 개념이고
실제로는 태스크(task)라는 구조체를 기반으로 메모리가 할당되고 CPU에 디스패치(dispatch) 된다
즉, 리눅스에서는 CPU 스케줄링의 기본 단위는 태스크인데,
이 태스크들을 스케줄링하는 스케줄러 중에 CFS(ccompletely fair scheduler)라는 스케줄러가 있다
이 CFS 스케줄러는 리눅스의 디폴트 스케줄러인데 time slice를 유동적으로 조정한다
리눅스의 CFS가 time slice를 조정하는 방식
리눅스에는 target scheduling latency(TSL)라는 파라미터가 있다
이 파라미터를 바탕으로 실제 time slice가 정해진다
예를 들어 TSL이 20ms고,
CPU에서 실행되길 기다리는 같은 우선순위를 가지는 태스크가 두 개 있다면,
이 때 각 태스크의 time slice는 10ms가 된다
만약 CPU에서 실행되길 기다리는 같은 우선순위를 가지는 태스크가 다섯 개 있다면,
이때는 각 태스크의 time slice는 4ms가 된다
그런데 이런 방식이면 스레드가 늘어날수록 time slice가 계속 작아져서 점점 0으로 수렴하게 될 것이다
그렇게 되면 잦은 컨텍스트 스위칭로 인한 오버헤드가 CPU에서 차지하는 비중이 너무 커지기 때문에
이를 방지하기 위해 존재하는 파라미터가 minimum granularity이다
minimum granularity는 time slice의 최소값을 지정할 때 사용된다
만약 minimum granularity가 2ms라면, CPU에서 실행되길 기다리는 스레드 수가 아무리 많아져도 time slice는 2ms 아래로 떨어지지 않는다
컨텍스트 스위칭과의 관계
적어도 리눅스에서는 스레드 수가 많아질수록 time slice가 줄어들어서 컨텍스트 스위칭이 더 빈번하게 일어날 거라고 예상할 수 있다
그리고 그만큼 스위칭으로 인한 CPU 오버헤드도 더 많아질 것이다
그러므로 스레드를 너무 많이 만들면 좋지 않다
쉬운코드는 본질에 충실합니다
👉 " 프로세스와 스레드의 관계를 바라보는 두 가지 세계관 " 글 보러 가자