2013-08-19 3 views
3

setTimeout의 해상도에 문제가 있습니다. 50ms로 설정하면 51에서 80ms까지 다양합니다. 절전 모드 모듈을 사용할 때 50μs와 같은 해상도를 얻을 수 있으므로 setTimeout 함수 문제는 적어도 1ms 가량 걸릴 수 있습니까? 그걸 고치거나 피할 방법이 있습니까? 수면 문제는 콜백 함수가 슛을해야 할 때라도 모든 것을 지연 시킨다는 것입니다 ... 정확히 50ms의 지연으로 어떤 이벤트를 쏘는 대안의 해결책이 있습니까? 슬립 모듈 예컨대 node.js setTimeout 해상도가 매우 낮고 불안정합니다

:

var start = new Date().getTime(); 
sleep.usleep(50); 
console.log(new Date().getTime() - start);` 

결과이다 : 0 그리고 microtime는 51 내지 57 μS 말한다. 대체 도대체 뭐야? 에서

+1

John Resig의 "[JavaScript 타이머 작동 방법] (http://ejohn.org/blog/how-javascript-timers-work/)"을 참조하십시오. –

+0

하지만,'setTimeout'의 함수가'new Date(). getTime()'만 쓸 때에도 여전히 완전히 신뢰할 수 없습니다! –

+1

게시물은 얼마나 자주 이벤트 루프가 유휴 상태인지에 따라 안정성을 설명합니다. 다른 작업으로 바쁜 경우 타이머는 해당 작업이 완료 될 때까지 기다려야합니다. 'timeout' 값은 단지 * 최소 * 일 뿐이며 보장은 아닙니다. –

답변

2

setTimeout docs :

당신의 콜백이 아마 어떻게 작은 코드 블록에 의해 결정된다 정확히 밀리 초를

지연의 정밀도를 지연에 호출되지 않습니다 것이 중요합니다 즉, 코드에있는 단일 스레드에서 많은 작업을 수행하는 경우 많은 지연으로 setTimeout이 트리거 될 수 있습니다. 반대로, 그것은 거의 정확할 것입니다.

당신이

var start = Date.now(); 
setTimeout(function() { console.log(Date.now() - start); }, 500); 
for(var i=0; i<999999999; ++i){} 

// 1237ms 

을 실행, 자신에 대한 차이를 볼이와 차이를 느낄 수

:

var start = Date.now(); 
setTimeout(function() { console.log(Date.now() - start); }, 500); 

// 507ms 
+0

두 번째 예제에서는 여전히 507ms입니다 !!!! 보십시오 ...'var start = Date.now();'sleep.usleep (50); console.log (Date.now() - start);''0' ZERO! 마이크로 타이머는 약 57 마이크로 초를 보여줍니다. –

+1

이 디자인은 "제한"이라고 생각합니다. –

+1

'setTimeout을 호출하면 두 번째 인수로 전달 된 시간 이후에 대기열에 메시지가 추가됩니다. 대기열에 다른 메시지가 없으면 즉시 메시지가 처리됩니다. 그러나 메시지가있는 경우 setTimeout 메시지는 다른 메시지가 처리 될 때까지 기다려야합니다. 그 이유 때문에 두 번째 인수는 최소 시간을 나타내며 보증 된 시간은 아닙니다. '- [Mozilla docs] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop) – user568109

0

따라서에서는 setTimeout 같은위한 최적의 시간 속도를 acheive하기 위해 우리는 주어진 모듈에 대한 이벤트 루프를 가능한 작게 유지하려고합니다. 이렇게하면 V8 엔진이 루프 작업에 소비하는 시간을 최소화 할 수 있습니다. 최상의 경우 시나리오 :

setInterval(function(){}, 50); 

이 파일의 유일한 경우 정확성은 매우 높습니다. 그 밖의 일은 일어나지 않기 때문입니다. 그래서 우리가하는 일은 우리가이 구간에서하고 싶은 일만하는 특정 모듈에 대한 프로세스를 포크하는 것입니다. 함수 내의 유일한 것이 비동기 요청 인 경우 위와 같습니다. 따라서 우리는 setInterval 함수에서 매우 높은 정밀도를 얻습니다.

하나의 파일에서 다음 내용을 원한다면이 파일을 호출 할 것입니다 .js.

var http = require('http'); 

var options = { 
    hostname: 'localhost', 
    port: 8888, 
    path:'/', 
    method: 'GET' 
} 

setInterval(function(){ 
    console.log('File:' + (new Date).getTime() % 50); 
    //The Modulus of the time in MS should change by no more than 1 MS on consecutive runs, I confirmed this works just dandy on my system(though the first couple intervals were slower in some instances, worse I saw was a 3 MS delay) 
    var req = http.request(options, function (res) { 
     res.on('data', function (data) { 
      console.log(data.toString()); 
     }); 
    }); 

    req.end(); 
}, 50); 

두 번째 파일에서 우리는 실제로 원하는 모든 작업을 수행 할 수 있습니다. 중요한 것은 위의 작업을 수행하는 프로세스를 생성하여 해당 프로세스에 포함시키는 것입니다. 이를 통해 프로세스 V8 프로세서는이 이벤트 루프를 매우 작게 유지할 수 있습니다. 우리는 여전히 CPU상의 주어진 프로세스의 운영체제 관리의 희생자이지만, 우리는 file1.js 모듈이 적어도 밀리 초마다 한 번씩주의를 기울일 것을 기대할 수 있습니다. 왜냐하면 모든 것이 비동기 호출이기 때문에 찾고 있습니다. 다음 번 비동기 호출을 시작해야 할 때 호출간에 가장 많이 지연되는 시간은 1ms입니다 (최소한 시스템에서 본 것 모두입니다). 따라서 다른 파일에는 많은 양의 작업과 하나의 매우 중요한 행이 포함될 수 있습니다.

file2.JS :

var http = require('http'); 
var child_process = require('child_process'); 


http.createServer(function (req, res) { 
    res.write('Hi There'); 
    res.end(); 
}).listen(8888); 

///Do whatever else you need to do 

child_process.fork('file1.js');//Add in this line!!!! 

예상 출력 :

File:29 
Hi There 
File:29 
Hi There 
File:30//Notice these values only increase by 0 or 1. 
Hi There 
File:31 
Hi There 
File:31 
Hi There 
File:32 
Hi There 
File:34//Uh oh, one went up by 2... not terrible 
Hi There 
File:35 
Hi There 
File:35 
+0

방법은 "콜백을 찾고"기능의 효율성을 높이기 위해? –

+0

콜백을 찾고 계십니까? – ChrisCM

+0

위의 예를 확인하십시오. 것이 가능하다. 이 기능은 망친 것입니다. –

0

예, 나는 그것이 더 정확한 것 내 재미 waitSort이 일할 수 :

를이 노드

여기에 있지만 작동하지만 바랍니다

const posInts = [5,2,7,9,4,6,1,3] 
 

 
const waitSort = arr => new Promise(done => { 
 
    const ret = [] 
 
    const last = Math.max(...arr) 
 
    arr.forEach(i => { 
 
    setTimeout(() => { 
 
     ret.push(i) 
 
     if(i === last){ 
 
     done(ret) 
 
     } 
 
    }, i) 
 
    }) 
 
}) 
 

 
waitSort(posInts).then(console.log) 
 
console.log(posInts)

관련 문제