Измерение производительности функции с помощью Javascript с помощью инструментов браузера или создание собственного теста

¿Зачем беспокоиться о производительности в Javascript?

Измерение влияния времени кода Javascript — это идеальный способ определения «горячих точек», который является первым шагом в поиске способов повышения производительности ваших сценариев.

В этом посте мы покажем вам 3 способа измерить время, затрачиваемое вашими скриптами:

  • Тест, построенный с Date.getTime.
  • Стандартный способ измерения с использованием Javascript с использованием performance.now.
  • Нестандартный способ использования console.time и console.timeEnd.
  • Нестандартный способ использования performance.mark.

Однако помните, что использование профилирования в инструментах Firebug или Chrome Dev часто является гораздо лучшим способом поиска кода, который использует слишком много памяти и поддерживает зависание браузера.

Старый тест

В прошлом вы использовали что-то вроде Date чтобы получить метку времени. DOMTimeStamp возвращает целое число миллисекунд в качестве значения. Это достижение неплохое и работает во всех браузерах, однако не обеспечивает высокой точности. Это решение пригодится, если вы используете Node.js, так как объект Performance недоступен в Node, поскольку в нем нет DOM.

/**
* Measure the time of execution with Date timestamp of a synchronous task
*
* @param {function} toMeasure
* @param {int} repeatTimes
* @return {Object}
*/
function TimeBenchmark(toMeasure,repeatTimes){
if(typeof(repeatTimes) != "number"){
repeatTimes = 1;
}
if(typeof(toMeasure) === "function"){
var start_time = new Date().getTime();
for (var i = 0; i < repeatTimes; ++i) {
toMeasure.call();
}
var end_time = new Date().getTime();
}
return {
start:start_time,
end: end_time,
estimatedMilliseconds: end_time - start_time
};
}

Используя Old Benchmark:

var TimesToBeExecuted = 10;
var TaskToBeExecuted = function(){
// A task that you want to measure
};
var TestResult = new TimeBenchmark(TaskToBeExecuted,TimesToBeExecuted);
console.log(TestResult);

Стандартный эталонный тест

Чтобы обеспечить более высокую точность, необходимую для времени с высоким разрешением, новый тип называется DOMHighResTimeStamp (возвращаемое значение performance.now) был представлен. Этот тип является значением с плавающей запятой, которое также возвращает время в миллисекундах. Но так как это плавающая точка, значение может представлять дробные миллисекунды и, следовательно, может давать точность в одну тысячную миллисекунды.

Эта функция будет измерять среднее время выполнения вашего скрипта на основе времени X выполнения. Это означает, что вы можете установить, сколько раз будет повторяться это задание, и получить среднее время выполнения. Помните, что каждое выполнение вашего скрипта не всегда занимает одно и то же время (разница может составлять пару миллисекунд), поэтому ваше задание будет выполнено X раз, а среднее время будет возвращено вместе с общим временем выполнения.

Эта функция опирается на performance.now работает и работает на следующих браузерах:

  • IE> = 10.
  • FireFox> = 15.
  • Хром> = 24.
  • Safari> = 8.
  • Опера> = 15.
  • Android> = 4.4
/**
* Measure the time of execution in milliseconds of a synchronous task
*
* @param {function} toMeasure
* @param {int} repeatTimes
* @return {Object}
*/
function StandardBenchmark(toMeasure,repeatTimes){
if(typeof(repeatTimes) != "number"){
repeatTimes = 1;
}
if(typeof(toMeasure) === "function"){
var start_status = performance.now();
var total_taken = 0;
for(var i = 0;i < repeatTimes;i++){
var startTimeSubtask = performance.now();
toMeasure.call();
var endTimeSubtask = performance.now();
total_taken += (endTimeSubtask -startTimeSubtask);
}
var final_status = performance.now();
}
return {
totalMilliseconds: (final_status - start_status),
averageMillisecondsPerTask: total_taken / repeatTimes
};
}

Использование StandardBenchmark:

var TimesToBeExecuted = 10;
var TaskToBeExecuted = function(){
// A task that you want to measure
};
var TestResult = new StandardBenchmark(TaskToBeExecuted,TimesToBeExecuted);
console.log(TestResult);

Чтобы протестировать функцию StandardBenchmark, мы собираемся выполнить простой запрос DOM, используя JQuery а также VanillaJS. Задача будет выполнена 10000000 (10M) раз, см. Следующее изображение:

Как вы можете видеть, первый тест использует jQuery и занимает около 113,9 секунд. Каждый запрос имеет в среднем 0,01 миллисекунды на запрос. С другой стороны, второй тест использует VanillaJS и занимает 17,5 секунд. Это примерно в 6 раз быстрее, чем выбор JQuery.

Предыдущий тест был измерен на ноутбуке со следующими характеристиками:

  • Версия Windows 10 Home 64 Bits - Chrome V 50.0.2661.102 m.
  • Intel Core i5-4200U @ 1,60 ГГц (4 процессора).
  • 4096 МБ ОЗУ.

И тот же тест выполняется на настольном компьютере со следующими характеристиками:

  • Версия Windows 7 Ultimate 64 Bits - Chrome V 50.0.2661.102 m.
  • Intel Core i5-4590 @ 3,30 ГГц
  • 8192 МБ ОЗУ

Кинул следующий результат:

Используя jQuery, каждый запрос имеет в среднем 0,001 миллисекунду, а задача достигается за 12 секунд. С другой стороны, второй тест с простым javascript выполняется за 3,5 секунды, а каждый запрос - около 0,0002 миллисекунд.

Использование теста браузера

Если вам нужно получить время выполнения функции на вашем локальном компьютере разработки, вы можете использовать инструменты профилирования вашего браузера:

Инструменты для профилирования Chrome

или консольные команды, такие как console.time() а также console.timeEnd(),

console.time Функция ожидает установки идентификатора, тогда таймер будет запущен и будет завершен только с использованием console.timeEnd с соответствующим идентификатором (предварительно установленным в функции времени консоли). Вы можете иметь до 10000 таймеров, работающих на данной странице, т.е.

var identifier = "SelectingAdomObject";
console.time(identifier);// Start timer
// Do something
for (var i = 0; i < 10000000; ++i) {
document.getElementById("myDomId");
}
console.timeEnd(identifier); // Stop timer and see result in the console

Результат в консоли должен выглядеть так:

Chrome console.time и console.timeEnd

Примечание: console.time не является стандартным и не соответствует стандарту, поэтому не используйте его на производстве. Только для разработки и тестирования.

Следующая функция оборачивает функцию console.time и выполняет задачу X раз. Таймер будет установлен вне цикла и будет определять только, сколько времени потребовалось для выполнения X раз вашей задачи (не каждый раз, иначе ваша консоль взорвется, если X раз слишком высока).

function Benchmark(toMeasure,identifierName,repeatTimes){
if(!identifierName){
identifierName = new Date().getTime().toString();
}
if(typeof(repeatTimes) != "number"){
repeat = 1;
}
if(typeof(toMeasure) === "function"){
console.time(identifierName);
for(var i = 0;i < repeatTimes;i++){
toMeasure.call();
}
console.timeEnd(identifierName);
return true;
}
return false;
}

Использование performance.mark

performance.mark Метод является полезным инструментом анализа времени. Интерфейс User Timing API позволяет вставлять вызовы API в различные части вашего Javascript, а затем извлекать подробные данные синхронизации, которые можно использовать для оптимизации. Mark Функция хранит метку времени внутри браузера. Вы можете назвать временную метку так, как хотите, эта временная метка представляет собой единое целое. Использование performance.mark действительно просто:

performance.mark("StartMyLoop");
var myCounter = 0;
for(var i = 0;i < 10000000;i++){
myCounter++;
document.getElementById("NonExistingDomElement");
}
performance.mark("EndMyLoop");

Эти методы всегда будут возвращать undefined.

Теперь, если вы хотите измерить, сколько времени заняло выполнение вашего цикла, вы должны использовать performance.measure, эта функция ожидает в качестве первого параметра идентификатор (случайное имя), а в качестве второго параметра - имя предыдущего установленного маркера (начальная отметка) и в качестве третьего параметра указывается имя предыдущей установленной отметки (конечная отметка).

var myMeasureId = "MyLoopTakeMilliseconds";
performance.measure(myMeasureId,"StartMyLoop","EndMyLoop");

Метод performance.measure действительно полезен, так как вы можете выполнить сравнение для многих меток и не ограничен ссылками (т. Е. Start1, End1, Start2, End2. Вы можете сравнить Start1 с End2 и т. Д.). Но обратите внимание, что ни performance.measure вернет что-нибудь. Он также вернет неопределенное. Чтобы получить все Метки а также измерения, использовать getEntriesByType() метод, т.е.

var marks = performance.getEntriesByType("mark");
var measurements = performance.getEntriesByType("measure");
console.log(marks,measurements);

Результат StartMyLoop будет (5748.075 - 2298.425 = 3449.6499). Посмотрите на консоль:

Отметить и измерить производительность JavaScript

Вы можете отказаться от любой предыдущей отметки или измерения, используя (соответственно):

performance.clearMarks('TheNameOfMyExistingMark');
performance.clearMeasures('TheNameOfMyExistingMeasurement');

Узнайте больше о User Timing API здесь, повеселись .

Ссылка на основную публикацию
Adblock
detector