[javascript] JavaScript의 마이크로 초 타이밍

마이크로 초 해상도의 JavaScript에 타이밍 기능이 있습니까?

Chrome 용 timer.js 를 알고 있으며 Firefox, Safari, Opera, Epiphany, Konqueror 등과 같은 다른 친숙한 브라우저에 대한 솔루션이 있기를 바랍니다. IE 지원에는 관심이 없지만 IE를 포함한 답변 환영합니다.

(JS에서 밀리 초 타이밍의 정확도가 낮다는 점을 감안할 때, 나는 이것에 숨을 참을 수 없습니다!)

업데이트 : timer.js는 마이크로 초 해상도를 광고하지만 단순히 밀리 초 판독 값에 1,000을 곱합니다. 테스트 및 코드 검사를 통해 확인되었습니다. 실망한. : [



답변

: 마크 Rejhon의 대답에 언급 된 바와 같이, 스크립트로 서브 밀리 초 고해상도 타이밍 데이터를 노출 최신 브라우저에서 사용할 수있는 API가 W3C 고해상도 타이머는 일명, window.performance.now().

now()Date.getTime()두 가지 중요한 측면에서 기존보다 낫습니다 .

  1. now()페이지 탐색이 시작된 이후의 밀리 초 수를 나타내는 밀리 초 미만 해상도의 double입니다. 분수 단위로 마이크로 초 수를 반환합니다 (예 : 1000.123 값은 1 초 및 123 마이크로 초).

  2. now()단조롭게 증가합니다. 이것은 중요하다 Date.getTime()가능성이 후속 호출에 뒤로 앞으로 또는 이동. 특히 OS의 시스템 시간이 업데이트되면 (예 : 원자 시계 동기화) Date.getTime()업데이트됩니다. now()항상 단조롭게 증가하므로 OS의 시스템 시간에 영향을받지 않습니다. 항상 벽시계 시간입니다 (벽시계가 원 자성이 아니라고 가정하면 …)

now()에서 사용되는 거의 모든 장소가 될 수있다 new Date.getTime(), + new Date하고 Date.now()있습니다. 예외는 점이다 Datenow()같은 시간, 혼합하지 마십시오 Date기반으로 유닉스 시대 (1970 년 이후 밀리 초 단위) 동안, now()(그것보다 훨씬 작은 될 것입니다 귀하의 페이지 탐색이 시작된 이후의 밀리 초 수입니다 Date).

now()Chrome 안정, Firefox 15 이상 및 IE10에서 지원됩니다. 사용 가능한 여러 polyfill도 있습니다.


답변

이제 자바 스크립트에서 마이크로 초를 측정하는 새로운 방법이 있습니다.
http://gent.ilcore.com/2012/06/better-timer-for-javascript.html

그러나 과거에는 밀리 초 타이머에서 JavaScript에서 0.1 밀리 초 정밀도를 얻는 조잡한 방법을 발견했습니다. 불가능한? 아니. 계속 읽으세요:

자체 점검 된 타이머 정확도가 필요한 몇 가지 고정밀 실험을 수행 중이며 특정 시스템의 특정 브라우저에서 0.1 밀리 초의 정밀도를 안정적으로 얻을 수 있음을 발견했습니다.

빠른 시스템의 최신 GPU 가속 웹 브라우저 (예 : 여러 코어가 유휴 상태 인 i7 쿼드 코어, 브라우저 창만 있음)에서 타이머가 밀리 초 단위로 정확하다고 믿을 수 있습니다. 실제로 유휴 i7 시스템에서는 매우 정확 해져서 1,000 회 이상의 시도에서 정확히 동일한 밀리 초를 안정적으로 얻을 수있었습니다. 추가 웹 페이지를로드하는 등의 작업을 시도 할 때만 밀리 초 정확도가 저하됩니다 (그리고 전후 시간 확인을 수행하여 저하 된 정확도를 성공적으로 파악하여 처리 시간이 갑자기 1 밀리 초 이상으로 늘어났습니다. 이는 CPU 변동으로 인해 너무 악영향을받은 결과를 무효화하는 데 도움이됩니다.)

i7 쿼드 코어 시스템 (브라우저 창이 유일한 창일 때)의 일부 GPU 가속 브라우저에서 너무 정확 해 졌기 때문에 정확도가 마침내 이제는 JavaScript에서 0.1ms 정밀 타이머에 액세스 할 수 있기를 바랐습니다. 고정밀이 필요한 특정 유형의 틈새 애플리케이션과 애플리케이션이 정확도 편차를 자체 검증 할 수있는 특정 유형의 틈새 애플리케이션에 대해 이러한 타이머 정밀도를 가치있게 만들기 위해 일부 고급 브라우징 시스템에 있습니다.

분명히 여러 패스를 수행하는 경우 여러 패스 (예 : 10 패스)를 실행 한 다음 10으로 나누어 0.1 밀리 초 정밀도를 얻을 수 있습니다. 이는 더 나은 정밀도를 얻는 일반적인 방법입니다. 여러 번 통과하고 총 시간을 통과 횟수로 나눕니다.

그러나 … 비정상적으로 고유 한 상황으로 인해 특정 테스트의 단일 벤치 마크 통과 만 수행 할 수 있다면 다음을 수행하여 0.1 (때로는 0.01ms) 정밀도를 얻을 수 있다는 것을 알았습니다.

초기화 / 보정 :

  1. 타이머가 다음 밀리 초까지 증가 할 때까지 기다리려면 사용 중 루프를 실행합니다 (타이머를 다음 밀리 초 간격의 시작 부분에 정렬).이 사용중인 루프는 1 밀리 초 미만으로 지속됩니다.
  2. 타이머가 증가 할 때까지 기다리는 동안 카운터를 증가시키기 위해 다른 바쁜 루프를 실행합니다. 카운터는 1 밀리 초 동안 발생한 카운터 증가 횟수를 알려줍니다. 이 바쁜 루프는 1 밀리 초 동안 지속됩니다.
  3. 숫자가 매우 안정적이 될 때까지 (로드 시간, JIT 컴파일러 등) 위의 과정을 반복합니다. 4. 참고: 숫자의 안정성은 유휴 시스템에서 달성 가능한 정밀도를 제공합니다. 정밀도를 자체 확인해야하는 경우 분산을 계산할 수 있습니다. 차이는 일부 브라우저에서는 더 크고 다른 브라우저에서는 더 작습니다. 빠른 시스템에서는 더 크고 느린 시스템에서는 더 느립니다. 일관성도 다양합니다. 어떤 브라우저가 다른 브라우저보다 일관성 / 정확한지 알 수 있습니다. 느린 시스템과 바쁜 시스템은 초기화 단계 사이에 더 큰 차이로 이어집니다. 이렇게하면 브라우저가 0.1ms 또는 0.01ms 측정을 허용하기에 충분한 정밀도를 제공하지 않는 경우 경고 메시지를 표시 할 수 있습니다. 타이머 왜곡이 문제가 될 수 있지만 일부 시스템의 일부 정수 밀리 초 타이머는 매우 정확하게 증가하므로 (점에서 거의) 신뢰할 수있는 매우 일관된 보정 값을 얻을 수 있습니다.
  4. 최종 카운터 값 (또는 마지막 몇 번의 보정 통과 평균)을 저장합니다.

1 회 통과를 밀리 초 미만의 정밀도로 벤치마킹 :

  1. 타이머가 다음 밀리 초로 증가 할 때까지 기다리려면 사용중인 루프를 실행합니다 (타이머를 다음 밀리 초 간격의 시작에 맞 춥니 다). 이 바쁜 루프는 1 밀리 초 미만으로 지속됩니다.
  2. 시간을 정확하게 벤치마킹하려는 작업을 실행하십시오.
  3. 타이머를 확인하십시오. 이것은 정수 밀리 초를 제공합니다.
  4. 타이머가 증가 할 때까지 기다리는 동안 카운터를 증가시키기 위해 마지막 사용중 루프를 실행합니다. 이 바쁜 루프는 1 밀리 초 미만으로 지속됩니다.
  5. 이 카운터 값을 초기화에서 원래 카운터 값으로 나눕니다.
  6. 이제 밀리 초의 소수 부분을 얻었습니다 !!!!!!!!

경고 : 바쁜 루프는 웹 브라우저에서 권장되지 않지만 다행스럽게도 이러한 바쁜 루프는 각각 1 밀리 초 미만으로 실행되며 몇 번만 실행됩니다.

JIT 컴파일 및 CPU 변동과 같은 변수는 엄청난 부정확성을 추가하지만 여러 초기화 패스를 실행하면 완전한 동적 재 컴파일이 발생하고 결국 카운터가 매우 정확한 것으로 정착됩니다. 사용중인 루프의 차이가 차이로 이어지지 않도록 모든 사용중인 루프가 모든 경우에 대해 정확히 동일한 기능인지 확인하십시오. 결과를 신뢰하기 전에 모든 코드 줄이 여러 번 실행되었는지 확인하여 JIT 컴파일러가 이미 완전한 동적 재 컴파일 (dynarec)로 안정화되도록합니다.

사실 특정 시스템에서 마이크로 초에 근접하는 정밀도를 목격 했지만 아직은 믿을 수 없었습니다. 그러나 0.1 밀리 초의 정밀도는 내가 유일한 브라우저 페이지 인 유휴 쿼드 코어 시스템에서 매우 안정적으로 작동하는 것으로 보입니다. 나는 일회성 패스 (고유 변수 발생으로 인해) 만 수행 할 수 있고 여러 번의 반복 패스를 평균화하는 대신 각 패스의 시간을 정확하게 측정해야하는 과학적 테스트 케이스에 도달했습니다. 그래서 이렇게했습니다.

나는 여러 번의 프리 패스와 더미 패스 (다이나 렉을 고정하기 위해)를 수행하고 0.1ms 정밀도 (몇 초 동안 견고하게 유지됨)의 신뢰성을 확인한 다음 벤치 마크가 발생하는 동안 키보드 / 마우스에서 손을 떼고 여러 번 수행했습니다. 0.1ms 정밀도의 신뢰성을 확인하기위한 포스트 패스 (다시 견고 함 유지). 이는 또한 전원 상태 변경 또는 기타 사항과 같은 일이 전후 사이에 발생하지 않아 결과를 방해하는지 확인합니다. 모든 단일 벤치 마크 통과 사이에 사전 테스트 및 사후 테스트를 반복합니다. 이것에 대해 나는 그 사이의 결과가 정확하다는 것을 거의 확신했습니다. 이 보장은 물론 없지만 정확한 <0.1ms입니다 정밀도에 가능하다는 것을 보여 간다 일부 웹 브라우저의 경우.

이 방법은 매우 틈새 시장 에서만 유용합니다 . 그렇다하더라도 말 그대로 100 % 무한 보장이 가능하지 않으며, 여러 계층의 내부 및 외부 검증과 결합하면 매우 신뢰할 수있는 정확도를 얻을 수 있으며 과학적 정확도까지 얻을 수 있습니다.


답변

대답은 일반적으로 “아니오”입니다. 일부 서버 측 환경 (즉, 브라우저가 아님)에서 JavaScript를 사용하는 경우 모든 베팅이 해제되고 원하는 모든 작업을 시도 할 수 있습니다.

편집 —이 답변은 오래되었습니다. 표준이 발전했으며 정확한 시간 문제에 대한 해결책으로 새로운 시설을 사용할 수 있습니다. 그럼에도 불구하고 진정한 실시간 운영 체제의 도메인 외부에서는 일반 비 특권 코드가 컴퓨팅 리소스에 대한 액세스를 제한적으로 제어한다는 점을 기억해야합니다. 성능 측정은 성능 예측 과 (필수적으로) 동일하지 않습니다 .


답변

다음은 node.js의 고해상도 타이머를 보여주는 예입니다 .

 function startTimer() {
   const time = process.hrtime();
   return time;
 }

 function endTimer(time) {
   function roundTo(decimalPlaces, numberToRound) {
     return +(Math.round(numberToRound + `e+${decimalPlaces}`)  + `e-${decimalPlaces}`);
   }
   const diff = process.hrtime(time);
   const NS_PER_SEC = 1e9;
   const result = (diff[0] * NS_PER_SEC + diff[1]); // Result in Nanoseconds
   const elapsed = result * 0.0000010;
   return roundTo(6, elapsed); // Result in milliseconds
 }

용법:

 const start = startTimer();

 console.log('test');

 console.log(`Time since start: ${endTimer(start)} ms`);

일반적으로 다음을 사용할 수 있습니다.

 console.time('Time since start');

 console.log('test');

 console.timeEnd('Time since start');

루핑을 포함하는 코드의 타이밍 섹션 인 경우 console.timeEnd()타이머 결과를 함께 추가하기 위해 의 값에 액세스 할 수 없습니다 . 할 수는 있지만,와 같은 반복 변수의 값을 주입 i하고 루프가 완료되었는지 감지하는 조건을 설정 해야하기 때문에 불쾌 해 집니다.

다음은 유용 할 수있는 예입니다.

 const num = 10;

 console.time(`Time til ${num}`);

 for (let i = 0; i < num; i++) {
   console.log('test');
   if ((i+1) === num) { console.timeEnd(`Time til ${num}`); }
   console.log('...additional steps');
 }

인용 : https://nodejs.org/api/process.html#process_process_hrtime_time


답변