Performance.now: примеры (JAVASCRIPT)

Работа с функцией performance.now для измерения времени выполнения кода
Раздел: Производительность, Таймеры
performance.now: Number

Описание функции performance.now()

Метод performance.now() возвращает значение DOMHighResTimeStamp, измеряемое в миллисекундах. Это значение представляет собой время, прошедшее с момента начала навигации страницы или с момента запуска текущего рабочего процесса в Node.js.

Основное применение — точные измерения производительности участков кода. Отличительная черта — монотонное увеличение значения, что защищает от корректировок системного времени. В браузерах значение имеет микросекундную точность, но округляется до 5 микросекунд для защиты от fingerprinting.

Функция не принимает аргументов. Возвращаемое значение — число с плавающей запятой, выражающее время в миллисекундах.

Короткие примеры использования

Базовый пример замера времени выполнения операции.

const start = performance.now();
for (let i = 0; i < 1000000; i++) { Math.sqrt(i); }
const end = performance.now();
console.log(`Время выполнения: ${end - start} мс`);
Время выполнения: 12.345678901234567 мс

Измерение времени асинхронной операции.

async function fetchData() {
    const start = performance.now();
    await fetch('https://jsonplaceholder.typicode.com/posts/1');
    const end = performance.now();
    console.log(`Запрос занял: ${(end - start).toFixed(2)} мс`);
}
fetchData();
Запрос занял: 156.78 мс

Похожие функции в JavaScript

Date.now() возвращает количество миллисекунд, прошедших с 1 января 1970 года. Менее точна, не монотонна, подвержена корректировкам системного времени.

console.time() / console.timeEnd() предоставляет простой способ замера с помощью меток. Удобен для отладки, но менее гибок по сравнению с performance.now().

performance.mark() и performance.measure() являются частью Performance Timeline API. Позволяют создавать именованные метки и измерять интервалы между ними, интегрируясь с инструментами разработчика.

Для большинства задач точного замера производительности performance.now() является предпочтительным выбором.

Альтернативы в других языках

Python (time.perf_counter): Возвращает время с максимальной доступной точностью для измерения коротких интервалов.

import time
start = time.perf_counter()
# Код
end = time.perf_counter()
print(f'Время: {end - start} секунд')
Время: 0.123456789 секунд

PHP (microtime): Возвращает текущую метку времени в микросекундах. Требует парсинга строки или использования параметра true для получения float.

$start = microtime(true);
// Код
$end = microtime(true);
echo 'Время: ' . ($end - $start) . ' секунд';
Время: 0.000123 секунд

C (clock()): Возвращает процессорное время, затраченное на выполнение программы. В отличие от performance.now(), измеряет именно использование CPU.

#include 
#include 
int main() {
    clock_t start = clock();
    // Код
    clock_t end = clock();
    double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
    printf("Время: %f секунд\n", time_spent);
    return 0;
}
Время: 0.123000 секунд

Типичные ошибки

Неправильное вычисление разницы: использование только одного вызова функции.

// ОШИБКА: Замер без вычисления разницы
const t = performance.now();
someOperation();
console.log(`Время: ${t} мс`); // Выводит начальное время, а не интервал
Время: 12345.678 мс

Попытка использовать возвращаемое значение как абсолютную временную метку, например, для сравнения с Date.now().

// ОШИБКА: Смешивание разных систем времени
const perfTime = performance.now();
const dateTime = Date.now();
// Не имеет смысла, так как точки отсчета разные
console.log(perfTime - dateTime);
-1691234567890.123 (пример отрицательного значения)

Использование для измерения интервалов больше допустимой точности, что может привести к переполнению или потере точности, хотя это маловероятно для практических задач.

Изменения в последних версиях

В спецификации High Resolution Time Level 2 изменился источник времени для performance.now() в браузерах. Теперь используется монотонный时钟, не привязанный к системному времени, что повышает надежность.

В Node.js метод performance.now() появился в версии 8.5.0 как экспериментальный, а в версии 16.0.0 стал стабильным. В Node.js 19.0.0 была увеличена точность до наносекунд (1e-9) в некоторых системах.

Для кросс-браузерной совместимости стоит учитывать, что в очень старых браузерах (IE9) метод мог отсутствовать или иметь префикс (msPerformance.now()).

Расширенные примеры

Измерение продолжительности нескольких операций с агрегацией.

Пример javascript
const measurements = [];
for (let i = 0; i < 10; i++) {
    const start = performance.now();
    // Имитация работы
    for (let j = 0; j < 10000; j++) {}
    const end = performance.now();
    measurements.push(end - start);
}
const avg = measurements.reduce((a, b) => a + b) / measurements.length;
console.log(`Среднее время: ${avg.toFixed(3)} мс`);
console.log(`Все замеры:`, measurements);
Среднее время: 0.045 мс
Все замеры: [0.04, 0.05, 0.04, ...]

Использование в Web Worker для замера производительности в отдельном потоке.

Пример javascript
// main.js
const worker = new Worker('worker.js');
worker.postMessage('start');

// worker.js
self.onmessage = function(e) {
    const start = performance.now();
    // Интенсивные вычисления
    let sum = 0;
    for (let i = 0; i < 1e7; i++) sum += i;
    const end = performance.now();
    self.postMessage(`Вычисления заняли ${end - start} мс`);
};
Вычисления заняли 120.5 мс

Интеграция с PerformanceObserver для наблюдения за метками.

Пример javascript
const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        console.log(`${entry.name}: ${entry.duration}`);
    }
});
observer.observe({ entryTypes: ['measure'] });

performance.mark('start-mark');
// ... код
performance.mark('end-mark');
performance.measure('my-measure', 'start-mark', 'end-mark');
my-measure: 15.678

Сравнение производительности разных алгоритмов.

Пример javascript
function algorithmA(n) { /* ... */ }
function algorithmB(n) { /* ... */ }

function benchmark(func, input) {
    const start = performance.now();
    func(input);
    const end = performance.now();
    return end - start;
}

const timeA = benchmark(algorithmA, 1000);
const timeB = benchmark(algorithmB, 1000);
console.log(`Алгоритм A: ${timeA} мс, Алгоритм B: ${timeB} мс`);
Алгоритм A: 5.123 мс, Алгоритм B: 3.456 мс

JS performance.now function comments

En
Performance.now Returns a high-resolution timestamp measured in milliseconds