2014-01-13 5 views
29

나는 여기에이 코드를 가지고 : 내 컴퓨터에서JavaScript setTimeout이 너무 정확하지 않은 이유는 무엇입니까?

var date = new Date(); 
setTimeout(function(e) { 
    var currentDate = new Date(); 
    if(currentDate - date >= 1000) { 
     console.log(currentDate, date); 
     console.log(currentDate-date); 
    } 
    else { 
     console.log("It was less than a second!"); 
     console.log(currentDate-date); 
    } 
}, 1000); 

, 그것은 항상 콘솔 출력에서 ​​1000 올바르게 실행됩니다. Interestedly 다른 컴퓨터에서 같은 코드는 제한 시간 콜백 초 미만에서 시작 I (예, ​​Tock에 대한)이 부정확를 해결 라이브러리의 존재를 알고

980 사이 998 currentDate - date의 차이입니다.

기본적으로 내 질문은 : setTimeout이 지정된 지연 시간에 실행되지 않기 때문에 이유가 무엇입니까? 컴퓨터가 너무 느려서 브라우저가 자동으로 느려짐에 적응하려고 시도하고 이전에 이벤트를 발생시킬 수 있습니까?

PS : A에 따라

:이 정보를 잘못 해석하고있는 경우

Enter image description here

+0

1-2 밀리 초 (1000 밀리 초 이상)의 차이는 아마도 지터 때문일 수 있습니다. 그게 왜 틀렸다고 생각하니? 1 %의 1/5입니다. –

+7

John Resig가 다음 기사에 대해 좋은 기사를 썼습니다. http://ejohn.org/blog/accuracy-of-javascript-time/ – rorypicko

+0

@ElliottFrisch "1 초"라고 말하면 정확하지 않기 때문에 정확하지 않습니다. "1 초". 그 이상도 이하도 아닌. –

답변

20

특히 정확하지 않아도됩니다. 브라우저가 코드를 얼마나 빨리 실행할 수 있는지를 제한하는 여러 가지 요인이 있습니다. MDN :

"클램핑"외에도 페이지 (또는 OS/브라우저 자체)가 다른 작업으로 바쁠 때 나중에 시간 초과가 실행될 수도 있습니다. 즉

setTimeout은 일반적으로 구현하는 방법, 바로 브라우저의 스레드를 실행할 무료되면, 지정된 지연 시간 후 을 실행하기위한 것입니다.

그러나 브라우저마다 다른 방식으로 구현할 수 있습니다. 여기에 몇 가지 내가 한 시험이다 :

var date = new Date(); 
setTimeout(function(e) { 
    var currentDate = new Date(); 
    console.log(currentDate-date); 
}, 1000); 

// Browser Test1 Test2 Test3 Test4 
// Chrome 998 1014 998 998 
// Firefox 1000 1001 1047 1000 
// IE 11 1006 1013 1007 1005 

아마 크롬에서 < 1000 배는 Date 유형의 부정확성에 기인 할 수는, 또는 아마도 그것은 코드를 실행할 때 결정하는 크롬은 다른 전략을 사용하는 수 — 시간 초과 지연이 아직 완료되지 않은 경우에도 가장 가까운 시간 슬롯에 맞추려고 시도하는 것일 수 있습니다.

안정적이고 일관된 밀리 초 단위의 타이밍을 원하면 setTimeout을 사용하면 안됩니다.

+2

사실이며 중요하지만 OP가 요청한 시간보다 * 짧은 * 시간을 측정하는 이유를 설명하지 못했습니다. – AmeliaBR

+0

편집되었습니다. 지금은 ... – gbmhunter

7

누군가가 저를 수정하시기 바랍니다 : 여기에 크롬 자바 스크립트 콘솔에서 실행되는 코드의 스크린 샷 결과입니다 플랫폼 간 성능 테스트의 부정확성과 관련하여 post from John Resig (강조 표시)

시스템 시간 c 끊임없이 마지막 쿼리 시간 (약 15  ms 간격으로 떨어져)로 반올림되어 성능 결과의 품질이 심각하게 손상됩니다.

그래서 시스템 시간에 비교할 때 15   MS는 양쪽 끝에 꾸며 낼까지 있다.

+2

그것이 문제의 한 측면입니다. 또 다른 문제는 브라우저의 비동기 특성이므로 대기열에있는 다른 작업에 따라 다른 작업을 처리하기 위해 제한 시간이 보류 될 수 있습니다. – EmptyArsenal

16

일반적으로 컴퓨터 프로그램은 50   ms보다 높은 정밀도로 실행하려고 할 때 매우 신뢰할 수 없습니다. 그 이유는 octacore 하이퍼 스레딩 프로세서에서조차 OS가 대개 수백 개의 프로세스와 스레드, 때로는 수천 또는 그 이상의 스레드를 저글링하기 때문입니다. 운영체제는 모든 CPU가 하나씩 CPU 시간을 갖도록 스케줄링함으로써 모든 멀티 태스킹 작업을 수행합니다. 즉, 최대로 수 밀리 초가 걸릴 수 있습니다.

Implicity 즉, 1000   ms에 대한 시간 제한을 설정하면 현재 브라우저 프로세스가 해당 시점에 실행되지 않을 가능성이 매우 적으므로 브라우저가 예고하지 않는 것이 정상입니다 1005, 1010 또는 심지어 1050 밀리 초까지 주어진 콜백을 실행해야합니다.

일반적으로 이것은 문제가되지 않으며, 거의 발생하지 않으며 거의 ​​중요하지 않습니다. 그렇다면 모든 운영 체제는 이상인보다 정확한 커널 수준 타이머를 제공하며 개발자는 에서 정확하게 코드를 실행할 수 있습니다. 그러나 자바 스크립트는 환경이 까다롭기 때문에 그런 커널 객체에 액세스 할 수 없으며 브라우저는 이론적으로 누군가가 웹 페이지 내부에서 OS 안정성을 공격하도록 허용 할 수 있기 때문에 브라우저를 사용하지 않아도됩니다. 위험한 타이머를 많이 사용하여 스레드를 꼼짝 못하게합니다.

왜 테스트에서 980이 발생하는지 확신 할 수 없습니다. 정확히 어떤 브라우저를 사용하고 어떤 JavaScript 엔진을 사용하는지에 달려 있습니다. 하지만 브라우저가 시스템 부하 및/또는 속도에 대해 수동으로 조금만 수정하면 "평균적으로 지연이 여전히 정확한 시간"이라는 것을 알 수 있습니다. 이는 샌드 박스 원리에서 많은 부분을 이해할 수 있습니다. 잠재적으로 시스템의 나머지 부분에 부담을주지 않고 필요한 시간을 대략적으로 계산하십시오.

+0

실제로이 문제는 JavaScript에만 해당되는 것이 아닙니다. 그리고 해석 된 언어를 실행하는 브라우저에 대해 50ms 이하의 정확도가 있습니다. 저는 우리가 이미 꽤 잘 알고 있다고 생각합니다. –

관련 문제