Есть ли в JavaScript какие-либо функции синхронизации с разрешением в микросекунды?
Мне известно о timer.js для Chrome, и я надеюсь, что будет решение для других дружественных браузеров, таких как Firefox, Safari, Opera, Epiphany, Konqueror и т. Д. Я не заинтересован в поддержке какого-либо IE, но ответы, включая IE приветствуются.
(Учитывая низкую точность миллисекундного времени в JS, я не затаил дыхание на этом!)
Обновление: timer.js рекламирует разрешение в микросекундах, но просто умножает показание миллисекунды на 1000. Проверено тестированием и проверкой кода. Разочарованный. : [
javascript
mwcz
источник
источник
Ответы:
Как упоминалось в ответе Марка Рейхона, в современных браузерах есть API-интерфейс, который предоставляет скрипту данные о времени с субмиллисекундным разрешением: таймер высокого разрешения W3C , также известный как
window.performance.now()
.now()
лучше традиционногоDate.getTime()
по двум важным причинам:now()
представляет собой двойное значение с субмиллисекундным разрешением, которое представляет количество миллисекунд с начала навигации по странице. Он возвращает количество микросекунд в дробной части (например, значение 1000,123 составляет 1 секунду и 123 микросекунды).now()
монотонно возрастает. Это важно , так какDate.getTime()
может , возможно , прыгать вперед или назад даже при последующих вызовах. Примечательно, что если обновляется системное время ОС (например, синхронизация атомных часов),Date.getTime()
оно также обновляется.now()
всегда будет монотонно увеличиваться, поэтому на него не влияет системное время ОС - это всегда будет время настенных часов (при условии, что ваши настенные часы не атомные ...).now()
можно использовать практически вездеnew Date.getTime()
, где+ new Date
иDate.now()
есть. Исключением является то, чтоDate
иnow()
времена не смешиваются, посколькуDate
основано на unix-epoch (количество миллисекунд с 1970 года), аnow()
это количество миллисекунд с момента начала навигации по вашей странице (поэтому оно будет намного меньшеDate
).now()
поддерживается в стабильной версии Chrome, Firefox 15+ и IE10. Также доступно несколько полифиллов .источник
new Date.getTime()
не вещь.new Date().getTime()
является.console.log
на каждом прогоне) Трудно разобрать, но скопируйте весь выделенный код здесь:last=-11; same=0; runs=100; for(let i=0;i<runs;i++) { let now = performance.now(); console.log('.'); if (now === last) { same++; } last = now; } console.log(same, 'were the same');
Теперь есть новый метод измерения микросекунд в javascript: http://gent.ilcore.com/2012/06/better-timer-for-javascript.html
Однако в прошлом я нашел грубый метод получения точности 0,1 миллисекунды в JavaScript из миллисекундного таймера. Невозможно? Нет. Продолжай читать:
Я провожу несколько высокоточных экспериментов, которые требуют точности таймера с самопроверкой, и обнаружил, что могу надежно получить точность 0,1 миллисекунды с определенными браузерами на определенных системах.
Я обнаружил, что в современных веб-браузерах с ускорением на GPU в быстрых системах (например, четырехъядерный i7, где несколько ядер простаивают, только окно браузера) - теперь я могу доверять таймерам с точностью до миллисекунд. Фактически, это стало настолько точным на простаивающей системе i7, что я смог надежно получить ту же самую миллисекунду после более чем 1000 попыток. Только когда я пытаюсь сделать что-то вроде загрузки дополнительной веб-страницы или чего-то другого, точность в миллисекундах ухудшается (и я могу успешно определить свою собственную ухудшенную точность, выполнив временную проверку до и после, чтобы увидеть, не мое время обработки внезапно увеличилось до 1 или более миллисекунд - это помогает мне аннулировать результаты, на которые, вероятно, слишком отрицательно повлияли колебания ЦП).
Он стал настолько точным в некоторых браузерах с ускорением на GPU в четырехъядерных системах i7 (когда окно браузера является единственным окном), что я обнаружил, что мне хотелось бы получить доступ к таймеру с точностью 0,1 мс в JavaScript, поскольку точность наконец-то достигла в некоторых высокопроизводительных системах просмотра, чтобы сделать такую точность таймера целесообразной для определенных типов нишевых приложений, которые требуют высокой точности и где приложения могут самостоятельно проверять отклонения точности.
Очевидно, что если вы выполняете несколько проходов, вы можете просто выполнить несколько проходов (например, 10 проходов), а затем разделить их на 10, чтобы получить точность 0,1 миллисекунды. Это распространенный метод повышения точности - выполнить несколько проходов и разделить общее время на количество проходов.
ОДНАКО ... Если я могу выполнить только один проход определенного теста из-за необычно уникальной ситуации, я обнаружил, что могу получить точность 0,1 (а иногда и 0,01 мс), выполнив следующие действия:
Инициализация / калибровка:
Тестирование одного прохода с точностью до миллисекунды:
ПРЕДУПРЕЖДЕНИЕ. Циклы занятости НЕ рекомендуются в веб-браузерах, но, к счастью, эти циклы занятости выполняются менее 1 миллисекунды каждый и выполняются всего несколько раз.
Такие переменные, как JIT-компиляция и колебания ЦП, добавляют огромные неточности, но если вы выполните несколько проходов инициализации, у вас будет полная динамическая перекомпиляция, и в конечном итоге счетчик установится на что-то очень точное. Убедитесь, что все циклы занятости - это одна и та же функция для всех случаев, чтобы различия в циклах занятости не приводили к различиям. Убедитесь, что все строки кода выполняются несколько раз, прежде чем вы начнете доверять результатам, чтобы позволить JIT-компиляторам уже стабилизироваться для полной динамической перекомпиляции (dynarec).
Фактически, я был свидетелем точности, приближающейся к микросекундам, на некоторых системах, но я пока не доверял этому. Но точность в 0,1 миллисекунды, похоже, работает достаточно надежно в простаивающей четырехъядерной системе, где я единственный браузер. Я пришел к научному тесту, в котором я мог выполнять только одноразовые проходы (из-за наличия уникальных переменных), и мне нужно было точно рассчитывать время каждого прохода, а не усреднять несколько повторных проходов, поэтому я и сделал это.
Я сделал несколько предварительных проходов и фиктивных проходов (также для урегулирования dynarec), чтобы проверить надежность точности 0,1 мс (оставалась стабильной в течение нескольких секунд), затем убрал руки с клавиатуры / мыши, пока выполнялся тест, затем сделал несколько пост-проходы для проверки надежности с точностью 0,1 мс (снова осталась стабильной). Это также подтверждает, что такие вещи, как изменения состояния питания или другие вещи, не происходили между до и после, что мешало результатам. Повторяйте предварительное и последующее тестирование между каждым тестом. После этого я был практически уверен, что промежуточные результаты были точными. Конечно, нет никаких гарантий, но это показывает, что в некоторых случаях в веб-браузере возможна точность <0,1 мс .
Этот метод полезен только в очень и очень нишевых случаях. Тем не менее, это буквально не будет на 100% бесконечно гарантировано, вы можете получить весьма надежную и даже научную точность в сочетании с несколькими уровнями внутренних и внешних проверок.
источник
Date.now()
или+new Date()
. Но теперь у нас естьperformance.now()
. Хотя ясно, что вы нашли несколько классных способов расширить возможности, этот ответ по сути устарел. Кроме того, не рекомендуется ничего, связанного с занятыми циклами. Только не делай этого. Нам этого больше не нужно.В общем, ответ - «нет». Если вы используете JavaScript в некоторой серверной среде (то есть не в браузере), тогда все ставки отключены, и вы можете пытаться делать все, что захотите.
изменить - это старый ответ; стандарты прогрессируют, и новые средства доступны как решения проблемы точного времени. Тем не менее, следует помнить, что за пределами домена настоящей операционной системы реального времени обычный непривилегированный код имеет ограниченный контроль над своим доступом к вычислительным ресурсам. Измерение производительности - это не то же самое (обязательно), что прогнозирование производительности.
источник
Вот пример, показывающий мой таймер с высоким разрешением для node.js :
Использование:
Обычно вы можете использовать:
Если вы синхронизируете разделы кода, которые включают цикл, вы не можете получить доступ к значению
console.timeEnd()
, чтобы сложить результаты таймера вместе. Вы можете, но это становится неприятно, потому что вам нужно ввести значение вашей повторяющейся переменной, напримерi
, и установить условие, чтобы определить, завершен ли цикл.Вот пример, потому что это может быть полезно:
Цитируйте: https://nodejs.org/api/process.html#process_process_hrtime_time.
источник