How Javascript Timer Work

making web/javascript 2011.06.11 14:36

초짜일 때 javascript timer가 어떻게 작동하는지 잘 이해해둬야 한다. 종종 예상치 못하게 동작할 때가 있는데 이게 다 single thread이기 때문이다. timer를 생성하고 조작하는 세 개의 함수를 예제를 통해 살펴보자.

  • var id = setTimeout(fn, delay);
    delay 이후에 fn이 한 번만 실행되는 타이머 생성. 반환되는 timer id값은 timer 중단시에 사용된다.
  • var id = setInterval(fn, delay);
    매 delay마다 fn이 실행되는 timer 생성. timer가 중단될 때까지 계속 실행됨
  • clearInterval(id); clearTimeout(id); 
    timer 생성시에 반환된 timer id로 timer 중단시킴.

timer에 대해 파들어가기 전에 기억해야 할 것은, timer는 의도한대로 동작한다는 걸 보장하지 않는다는 것이다. 브라우저에서 javascript는 single thread로 실행되기 때문에 비동기 이벤트(마우스 클릭이나 timer)는 실행 가능한 상황에서만 동작한다. 아래 좋은 예제 그림이 있다.

이 그림을 제대로 이해한다면, javascript 비동기 실행이 어떻게 작동하는지 느낌이 올 것이다. 단순한 1차원 그림이다. 세로축은 밀리초 단위의 시간이고, 파란 박스들은 실행된 javascript를 나타낸다.보면, 첫 번째 Javascript 블럭은 18ms 정도 실행되었고, mouse click callback 블럭은 11ms 쯤 실행되었다.

Javascript는 한 번에 하나의 코드 조각이 실행될 수 있기 때문에(single thread니까) 각각의 블럭들은 다른 비동기 이벤트(마우스 클릭, timer, ajax 요청이 끝났을 때 등...) 진행을 "blocking"한다. queue에 쌓여서 실행 대기 상태가 된다.(브라우저마다 다르지만, 단순하게~)

첫 번째 Javascript 블럭을 보면 두 개의 timer가 생성되었다. 10ms setTimeout, 10ms setInterval! 10ms 후에 timer가 실행되나 한 번 보자. 보시다시피, 실행되지 않는다! 실행되어야 할 fn은 실행 가능할 때 실행되겠다며 queue에 들어가셨다.

첫 번째 javascript block에는 8ms쯤에 mouse click도 발생했다. mouse click의 callback 함수 역시 바로 실행되지 못하고 나중에 실행하시겠다며 queue로 들어가셨을 테다.

javascript block이 끝나면 브라우저가 물어본다. 실행 대기하고 계신 분 있냐고? mouse click handler와 timer callback이 손을 들지만 먼저 들어와계셨던 mouse click callback를 실행하게 된다(그림에서 약 11ms 동안 실행됨). 그럼 timer callback은? 실행 가능한 다음 기회를 노린다.

mouse click handler가 실행되는 동안 10ms interval이 발생했지만 역시 queue로 들어가게 된다. 그 다음 10ms interval이 발생하면? 또 queue에 들어갈까? 큰 블럭의 코드가 실행 중이라고 했을 때 그 간의 모든 interval callback이 queue에서 실행을 기다리고 있을까? 그렇진 않다. 큰 블럭의 코드의 실행이 끝났을 때 모든 interval callback들이 다다다다~~ 실행될테니까. interval callback인 경우에 브라우저는 한 놈만 queue에 유지한다고 생각하면 되겠다. 그래서 30ms쯤에 10ms interval이 발생해도 그냥 dropped된 것이다. 이미 실행대기 queue에는 interval callback이 있으니까.

세 번째 10ms interval이 발생했을 때를 보면, interval callback이 실행 중임을 확인할 수 있다. interval은 지금 뭐이가 실행되고 있는지 전혀 상관치 않는다. 지금 실행 안되면 일단 queue에 들어가신다. 이렇게 되면, 중간에 끼어드는 일이 없을 경우에 interval callback 실행이 끝난 뒤에 또 interval callback이 실행될 것이다. (callback의 기능에 따라서 사용자에게 나쁜 경험을 줄 수도 있을 듯)

두 번째 interval callback까지 실행이 끝나고 나면 javascript 엔진이 실행할 것이 없어 텅 빈 것을 볼 수 있다. 브라우저가 다음 비동기 이벤트를 기다리고 있다는 의미이다. 50ms에 네 번째 10ms interval이 발생하고 callback이 실행될 것이다. 이 때에는 'blocking' 요소가 없기 때문에 제 시간에 바로 실행된다. 네 번째만에 처음으로 제 시간에 실행이 된 셈.

setTimeout과 setInterval의 차이첨을 아래 예제를 통해 살펴보자.

 setTimeout(function() {
  /* Some long block of code... */
  setTimeout(arguments.callee, 10);
}, 10);

setInterval(function() {
  /* Some long block of code... */
}, 10);

두 개의 문장은 같아 보이지만 그렇지 않다. setTimeout 코드는 callback이 실행된 후 10ms 후에 다음 callback이 실행된다. 하지만 setInterval의 경우, 앞에서 설명했던 것처럼 이전 callback이 언제 실행되었는지 상관없이 매 10ms마다 callback을 실행하려고 할 것이다.

요약해봅시다!

  • javascript 엔진은 single thread이다. 비동기 이벤트는 실행 대기를 위에 queue에 쌓인다.
  • setTimeout과 setInterval은 비동기 코드의 실행 방법 자체가 다르다.
  • timer는 바로 실행되지 못할 경우 다음 실행 가능할 때까지 blocking된다(생성 당시 선언했던 delay보다 더 흐른 뒤에 callback이 실행됨).
  • interval은 delay가 없을 경우 선언해둔 지연 시간마다 실행된다.


저작자 표시 비영리 변경 금지
신고

'making web > javascript' 카테고리의 다른 글

The Call Object  (0) 2011.06.12
How Javascript Timer Work  (0) 2011.06.11
setTimeout with a shorter delay  (0) 2010.03.29
이런 잡스런... - -;  (0) 2010.01.25
Enjoying the Observer pattern with custom events  (0) 2010.01.17
Stuart Langridge: Secrets of Javascript Closures, part 1  (1) 2010.01.14

setTimeout with a shorter delay

making web/javascript 2010.03.29 12:22
reference URL: http://dbaron.org/log/20100309-faster-timeouts(Wednesday, 2010-03-09, 13:45-0800)

On Sunday, somebody with the nickname {g} was on irc.mozilla.org asking about the behavior of setTimeout. In particular, he wanted to divide up work into a bunch of pieces in a way that allowed the user to interact with the page while the work was happening, and was doing this by doing a piece of the work, and then making a setTimeout call to continue the work. (In some cases, this could also be done using workers.) Unfortunately for him, setTimeout in most browsers doesn't allow a delay less than about 10 milliseconds (it forces any smaller delays to be longer), so the work wasn't finishing as fast as it could. (Chrome has changed this to 2 milliseconds, though, and apparently had some problems with it.)

A while ago, Jeff Walden suggested to me that Web pages could get the equivalent of setTimeout, with a real zero delay, using postMessage. This turns out to be relatively straightforward:

    
// Only add setZeroTimeout to the window object, and hide everything
// else in a closure.
(function() {
var timeouts = [];
var messageName = "zero-timeout-message";

// Like setTimeout, but only takes a function argument. There's
// no time argument (always zero) and no arguments (you have to
// use a closure).
function setZeroTimeout(fn) {
timeouts.push(fn);
window.postMessage(messageName, "*");
}

function handleMessage(event) {
if (event.source == window && event.data == messageName) {
event.stopPropagation();
if (timeouts.length > 0) {
var fn = timeouts.shift();
fn();
}
}
}

window.addEventListener("message", handleMessage, true);

// Add the one thing we want added to the window object.
window.setZeroTimeout = setZeroTimeout;
})();

I wrote a demo page that demonstrates that this is significantly faster than setTimeout(0). On a Firefox nightly 100 iterations of setZeroTimeout take about 10-20 milliseconds most of the time, but occasionally longer; on a WebKit build I have it takes about 4-6 milliseconds, but occasionally a bit longer. (We should probably investigate the performance difference here.) In comparison, in Firefox and on non-Chromium-based WebKit, the setTimeout version takes about a second (though perhaps even longer on Windows).

Update (2010-03-12): My numbers were on Linux. Boris tells me that on Mac, it's the opposite: Gecko is faster than Safari or Chrome.


저작자 표시 비영리 변경 금지
신고

'making web > javascript' 카테고리의 다른 글

The Call Object  (0) 2011.06.12
How Javascript Timer Work  (0) 2011.06.11
setTimeout with a shorter delay  (0) 2010.03.29
이런 잡스런... - -;  (0) 2010.01.25
Enjoying the Observer pattern with custom events  (0) 2010.01.17
Stuart Langridge: Secrets of Javascript Closures, part 1  (1) 2010.01.14

이런 잡스런... - -;

making web/javascript 2010.01.25 01:02
http://www.quirksmode.org/dom/getstyles.html

꼭 이래야대냐...
id도 모르는데... - -;
저작자 표시 비영리 변경 금지
신고

Enjoying the Observer pattern with custom events

making web/javascript 2010.01.17 11:36
저작자 표시 비영리 변경 금지
신고

Stuart Langridge: Secrets of Javascript Closures, part 1

making web/javascript 2010.01.14 02:56

Stuart Langridge: Secrets of JavaScript Closures, part 1 from YoungProfessionals-ICT.nl on Vimeo.

download pdf

저작자 표시 비영리 변경 금지
신고


티스토리 툴바