2012-02-15 1 views
9

타이밍에 민감한 프로젝트를 작업하면서 아래 코드를 사용하여 Firefox의 데스크톱 컴퓨터에서 처음 사용 가능한 타이밍 이벤트의 세분성을 테스트 한 다음 Linux 서버의 node.js 코드로 테스트합니다. 파이어 폭스 실행은 1ms 타임 아웃에서 평균 200fps의 예측 가능한 결과를 산출했으며 5ms 단위의 타이밍 이벤트가 있음을 나타냅니다.node.js가 setTimeout (func, 1.0)을 잘못 처리하는 이유는 무엇입니까?

시간 초과 값 0을 사용하면 Chrome V8 엔진 Node.js가 실제로 타임 아웃을 이벤트에 위임하지 않고 즉시 처리한다는 사실을 알고 있습니다. 예상대로이 숫자는 평균 60,000fps로 CPU 용량을 지속적으로 정확하게 처리합니다 (상단에서 확인). 그러나 1ms의 타임 아웃으로 숫자는 여전히 초당 3.5-4000 사이클이었으며, Node.js는 이론상 최대 초당 1000 사이클을 생성하는 1ms 타임 아웃을 존중할 수 없음을 의미합니다. 숫자의 범위와 재생

, 내가 얻을 :

  • 2ms의 : ~ 100 FPS (사실 시간 제한, 리눅스에 타이밍 이벤트의 10ms 단위 표시)
  • 1.5 :
  • 1.0001 같은 : 동일
  • 1.0 3,500 - 4,500 FPS
  • 0.99 : 2,800 - 3,600 FPS
  • 0.5 : 1,100 - 2,800 FPS
  • ,536,913,632 10
  • 0.0001 : 1,800 - 3,300 FPS
  • 0.0 ~ 60,000 FPS

ECMA 스크립트 사양은 아마도 실제에 전화를 위임 setTimout의 어떤 약속도하지 않습니다 때문에의 setTimeout의 동작은 (FUNC, 0), 용서할 것 OS 수준의 인터럽트. 하지만 0 < x < = 1.0에 대한 결과는 분명히 터무니 없습니다. 지연 시간을 명시 적으로 주었고 x 지연에 대한 n 번의 호출에 대한 이론상의 최소 시간은 (n-1) * x 여야합니다. V8/Node.js가하는 일은 무엇입니까? node.js api docs for setTimeout(cb, ms) (강조 광산)에서

var timer, counter = 0, time = new Date().getTime(); 

function cycle() { 
    counter++; 
    var curT = new Date().getTime(); 
    if(curT - time > 1000) { 
     console.log(counter+" fps"); 
     time += 1000; 
     counter = 0; 
    } 
    timer = setTimeout(cycle, 1); 
} 

function stop() { 
    clearTimeout(timer); 
} 

setTimeout(stop, 10000); 
cycle(); 
+0

내가 같은데요하면 Node.js를 팀은 '최대한 빨리'을 의미하는 타임 아웃 값으로 1''사용 야생에서 코드를 관찰한다는 것입니다. 나는'setTimeout (someFunc, 0)'을 쓰는 것을 망설이는 프로그래머가 많다는 것을 알고있다. 왜냐하면'0'은 어떻게 든 '틀렸다고 느껴진다.'... 시간 제한은 0이다. '1'은 그러한 코드에서 가능한 빨리 의미하는 다음 논리적 가치로 보입니다. 그래서 Node.js 코드는 아마도'if (timeout> 1) {scheduleTimeout (someFunc, timeout);} else {scheduleNextTick (someFunc);}' –

+0

과 같은 체크를 가지고있을 것입니다. 나는 이런 종류의 연구를 좋아합니다! –

답변

1

완성도를 들어 나는 nodeJS 구현을 지적하고 싶습니다

https://github.com/nodejs/node-v0.x-archive/blob/master/lib/timers.js#L214

어느 :

IDLE이

을 제한 시간 :

// Timeout values > TIMEOUT_MAX are set to 1. 
var TIMEOUT_MAX = 2147483647; // 2^31-1 
... 
exports.setTimeout = function(callback, after) { 
    var timer; 

    after *= 1; // coalesce to number or NaN 

    if (!(after >= 1 && after <= TIMEOUT_MAX)) { 
     after = 1; // schedule on next tick, follows browser behaviour 
    } 

    timer = new Timeout(after); 
    ... 
} 

이 문을 기억

많은 소켓은 동일한 유휴 시간 제한을 갖기 때문에 항목 당 하나의 제한 시간 감시자를 사용하지 않습니다. 오버 헤드가 너무 많습니다.
대신 동일한 타임 아웃 값과 링크 된 목록을 가진 모든 소켓에 단일 관찰자를 사용합니다.

이 기술은 libev 설명서에 설명되어 있습니다 : http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts

그리고 우리는 여기에 same timeout value (1)을 전달합니다.

Timer의 구현

은 여기에 있습니다 :
https://github.com/nodejs/node-v0.x-archive/blob/master/src/timer_wrap.cc

+0

다시 돌아 보면, 0 HonoredMule

5

:

그것은 정확히 밀리 초를 지연에 콜백이 아마 호출되지 않습니다 것이 중요합니다 - Node.js를가에 대해 보증하지 않습니다 정확한 타이밍은 콜백이 시작될 것이고 주문하는 것들은 시작되지 않을 것입니다. 콜백은 지정된 시간에 최대한 가깝게 호출됩니다.

"최대한 가깝게"는 구현 팀과 다른 것을 의미한다고 생각합니다.

[편집]은 또한, setTimeout() function은 (apparently part of the HTML5 draft 있지만) 임의의 규격에서 요구되지 않는 것으로 보인다. 게다가 사실상 최소 4 ~ 10 밀리 초의 세분화 수준이있는 것처럼 보입니다. 따라서 이것이 "어떻게 그럴 수 있는지"나타납니다.

오픈 소스 소프트웨어의 큰 장점은 필요에 따라 더 높은 해상도를 포함하도록 패치를 제공 할 수 있다는 것입니다.

+0

@HonoredMule : 귀하의 기대 또는 소프트웨어 구현 방법의 특성으로 인해 그러한 수치가 "이해가되지 않습니다"? – maerics

+0

덧붙여서 setInterval은 interval이 node.js에서> = 1.0 일 때만 실행되며 Linux에서는 항상 5ms 단위로, Firefox에서는 4ms 단위로 항상 인터럽트를 사용합니다. 우리가 OS 수준의 인터럽트 세분성을 가지고있을 때 "보증이 없다"는 것이 예상되지만 초당 4,000 회의 인터럽트는 발생하지 않습니다. 내가 찾고있는 것은 API 레벨 (즉, 0 => 즉시 호출, 노드의 이벤트 대기열에 똑바로 <= 1.0 =>,> 1.0 => 참 인터럽트)에서/what/Node.js가 수행중인 작업에 대한 설명입니다. 설명서에는 아무런 언급이 없습니다. – HonoredMule

+0

죄송합니다. 첫 번째 덧글을 게시하지 않으려했습니다 (단락 휴식을 원했습니다). 편집 시간이 다 된 후에 삭제했습니다. 어쨌든 더 자세한 설명서가 없으면 내 기대치를 설정하기가 어렵습니다 ... 따라서 질문입니다. – HonoredMule