Измерение времени выполнения асинхронного кода JavaScript
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Для точного замера времени выполнения операций JavaScript, которые применяют коллбеки, воспользуйтесь методом performance.now()
. Устанавливайте временные метки в момент начала операции и сразу по её завершении, а именно, прямо в коде коллбека. Разница между этими значениями даст вам реальное время выполнения.
const start = performance.now();
asyncFunction(() => {
const duration = performance.now() – start;
console.log(`Время выполнения: ${duration} мс`);
});
Убедитесь, что конечная временная метка устанавливается внутри коллбека, чтобы корректно учесть время, затраченное на асинхронные операции.
Измерение времени с высокой точностью при помощи hrtime
В Node.js для измерения времени с высокой точностью подходит process.hrtime()
. Этот метод предоставляет возможность измерять время до наносекунд. Так можно перевести результаты в миллисекунды:
const start = process.hrtime();
asyncOperation(() => {
const diff = process.hrtime(start);
const durationInMilliseconds = (diff[0] * 1e9 + diff[1]) / 1e6; // Преобразование из наносекунд в миллисекунды
console.log(`Время выполнения: ${durationInMilliseconds} мс`);
});
Не забывайте сбрасывать hrtime
перед проведением повторных замеров и обеспечьте корректную обработку ошибок. Чтобы точно отслеживать асинхронные операции, используйте Performance API.
Измерение времени выполнения итеративных асинхронных операций
Если требуется измерить время выполнения повторяющихся асинхронных операций, например, вставки в базу данных, вы можете воспользоваться следующим кодом:
let completedOps = 0;
const LIMIT = 10;
console.time('dbInsertTimer');
for (let i = 0; i < LIMIT; i++) {
insertIntoDatabaseAsync(data, (err) => {
if (err) {
console.error(`Ошибка при вставке на итерации ${i}:`, err);
} else {
console.log(`Запись ${i} успешно сохранена`);
if (++completedOps === LIMIT) {
console.timeEnd('dbInsertTimer');
}
}
});
}
Значение LIMIT
и инкрементирование completedOps
обеспечивают окончание замера времени только после выполнения всех операций.
Решение проблем с таймерами в сложных сценариях
Некоторые сложности, такие как нестабильность работы коллбеков или большие колебания времени выполнения, могут затруднить процесс измерения. В таких случаях можно использовать переменные для отладки, чтобы контролировать объём ведомой информации о времени выполнения. Также можно измерять время выполнения файловых операций с коллбеками, например, при реализации функции отправки HTML.
Визуализация
Процесс измерения времени выполнения асинхронных JavaScript коллбеков можно сравнить с тем, как хронометрист (⏱️) фиксирует время на эстафете 🏃♂️🔄🏃♀️:
console.time('asyncCodeTimer'); // На старт... внимание... марш!
// Асинхронная функция с коллбеком
asyncFunctionWithCallback(() => {
console.timeEnd('asyncCodeTimer'); // Стоп хронометр!
});
Если провизуализировать процесс, будет чётко видно:
🏁[Начало кода] -> 🏃♂️[Асинхронная функция в процессе] -> 🔄[Ожидание вызова коллбека...] -> 🏃♀️[Выполнение коллбека] -> 🏆[Завершение кода]
⏱️[Измеренное время]
Таким образом, старт и финиш -- это использование методов console.time()
и console.timeEnd()
, которые обозначают начало и конец нашего замера, включая весь жизненный цикл асинхронной операции.
Точное измерение времени с использованием Performance API
Для точного контроля времени используйте Performance API с методами performance.mark()
и performance.measure()
:
// Для Node.js версии 12 и выше
const { performance, PerformanceObserver } = require('perf_hooks');
performance.mark('A'); // Маркируем начало
asyncOperation(() => {
performance.mark('B'); // Маркер конца
performance.measure('A to B', 'A', 'B'); // Считаем разницу
const [measure] = performance.getEntriesByName('A to B');
console.log(`Время выполнения: ${measure.duration} мс`);
performance.clearMarks();
performance.clearMeasures(); // Очищаем записи
});
Класс PerformanceObserver
будет незаменимым инструментом для мониторинга производительности в реальном времени в процессе работы приложения.
Конвертирование hrtime
в секунды для наглядности
Вы можете создать вспомогательную функцию для преобразования результатов из hrtime
в более удобочитаемый формат, например, в секунды:
function hrtimeToSeconds(hrtime) {
return (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
}
const start = process.hrtime();
asyncOperation(() => {
console.log(`Время выполнения: ${hrtimeToSeconds(process.hrtime(start))} сек.`);
});
Применение Async/Await для упрощения измерений
Операторы async/await
упрощают процедуру измерения времени, избавив вас от прямой работы с коллбеками:
const measure = async (operation) => {
const start = performance.now();
await operation();
const duration = performance.now() – start;
console.log(`Время выполнения: ${duration} мс`);
};
measure(asyncOperation);
Полезные материалы
- Performance: now() method – Web APIs | MDN — Детальное руководство MDN по использованию
performance.now
. - Process | Node.js v21.6.1 Documentation — Официальная документация Node.js по
process.hrtime()
. - JavaScript Performance — Руководство W3 Schools по оптимизации производительности JavaScript.
- Measure performance with the RAIL model — Метод оценки производительности RAIL от Google.
- Event Loop and the Big Picture — NodeJS Event Loop Part 1 | by Deepal Jayasekara — Подробный анализ цикла событий в Node.js.
- Microtasks — Учебное руководство о микрозадачах и цикле событий JavaScript.