해당 글은 Chromium을 기준으로 작성된 글 입니다.
Microtask는 비동기적으로 실행되는 작은 작업을 의미합니다. 예를 들어, Promise의 then()이나 catch() 콜백, queueMicrotask() 등이 이에 해당합니다.
Macrotask는 큰 작업 단위를 말합니다. 대표적으로 이벤트 처리, setTimeout, setInterval, KeyEvent I/O 작업등이 이에 해당합니다.
VSync는 수직동기화 라고도 하며, 화면 주사율에 맞춰 화면 갱신을 조정합니다. 예를 들어 60Hz 모니터는 1초에 60번 화면을 갱신합니다. 브라우저는 vsync에 맞춰 신호를 보내어 화면을 갱신하라고 명령을 내립니다.
0.0ms:BeginFrame 시작
vsync가 일어나면 프레임을 시작하라는 신호를 보냅니다.
macrotask queue에 있는 macrotask들을 하나씩 꺼내어 실행합니다.
이 과정은 아래 두 조건 중 하나를 만족할 때까지 지속됩니다:
macrotask queue가 비워졌을 때Now() ≥ frameDeadline이 되었을 때참고:
frameDeadline은 다음 vsync보다 약 1ms 빠른 시각으로 설정됩니다.
60fps기준 (약 15.67ms)이는 브라우저가 렌더링을 제시간에 마치고 화면에 표시할 수 있도록
약간의 여유 시간을 두기 위해서입니다.
각 macrotask가 끝날 때마다 microtask queue의 작업을 모두 수행합니다.
microtask queue 내부에서 새로운 microtask 를 큐에 넣는다면, 해당 microtask 는 다음 태스크가 실행되기 전에 실행됩니다
macrotask queue가 모두 비워지면, rAF 작업(rAF step)이 시작됩니다.
rAF 작업은 다음의 세 단계로 구성됩니다:
requestAnimationFrame 콜백 실행requestIdleCallback 실행
requestAnimationFrame,requestIdleCallback콜백이 실행될 때마다microtask queue에있는 작업은 모두 실행됩니다.
requestAnimationFrame 콜백들이 모두 실행된 후, 브라우저는 다음 렌더링 파이프라인을 수행합니다:
Style → Layout → Paint → Composite → Raster → GPU → Display
해당 렌더링 작업이 모두 완료되었으면
다시 한번 macrotask queue에 있는 macrotask들을 하나씩 꺼내어 실행합니다.
만약 rAF 콜백 실행이 너무 길어져 frameDeadline을 초과하게 되면, Composite 단계가 지연되어 해당 프레임은 드랍됩니다.
이 경우 브라우저는 이전 프레임을 그대로 다시 사용하고, 화면이 끊기는 현상이 발생할 수 있습니다.
렌더링이 모두 끝난 후, 브라우저는 다시한번 macrotask queue에 남아있는 작업들을 처리합니다.
할 일이 없을 때 현재 시각 Now()가 frameDeadline보다 빠르다면,
브라우저는 requestIdleCallback 을 실행합니다.
밀린 requestIdleCallback은 다음 프레임으로 연기됩니다.
다음 vsync가 오기 전까지 macrotask queue에 작업이 들어오면 macrotask를 실행합니다.
출처:
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#microtask-queuing
https://github.com/chromium/chromium/blob/main/cc/scheduler/scheduler.cc
https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide
https://chromium.googlesource.com/chromium/src/%2B/112.0.5615.165/docs/life_of_a_frame.md