Точно измерить производительность функции Javascript при отображении вывода для пользователя - PullRequest
0 голосов
/ 29 августа 2018

Как видно из кода ниже, когда я увеличиваю размер строки, это приводит к разнице в 0 миллисекунд. Более того, существует несоответствие, так как число строк продолжает увеличиваться.

Я что-то здесь не так делаю?

let stringIn = document.getElementById('str');
let button = document.querySelector('button');

button.addEventListener('click', () => {
  let t1 = performance.now();
  functionToTest(stringIn.value);
  let t2 = performance.now();
  console.log(`time taken is ${t2 - t1}`);
});

function functionToTest(str) {
  let total = 0;
  for(i of str) {
   total ++;
  }
  return total;
}
<input id="str">
<button type="button">Test string</button>

Я тоже пытался использовать await, но результат тот же (см. Фрагмент кода ниже). Функция, включающая приведенный ниже код: async:

let stringArr = this.inputString.split(' ');
let longest = '';
const t1 = performance.now();
let length = await new Promise(resolve => {
  stringArr.map((item, i) => {
    longest = longest.length < item.length ? longest : item;
    i === stringArr.length - 1 ? resolve(longest) : '';
  });
});
const diff = performance.now() - t1;
console.log(diff);
this.result = `The time taken in mili seconds is ${diff}`;

Я также пытался ответить на этот вопрос как , но он также противоречив.

В качестве обходного пути я попытался использовать функцию console.time, но она не позволяет отображать время и также не точна.


Обновление : Я хочу создать интерфейс, подобный jsPerf , который будет очень похож на него, но для другой цели. В основном я хотел бы сравнить различные функции, которые будут зависеть от пользовательского ввода.

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Есть 3 вещи, которые могут помочь вам понять, что происходит:

  1. Браузеры уменьшают точность performance.now(), чтобы предотвратить атаки Meltdown и Spectre, поэтому Chrome дает максимальную точность 0,1 мс, FF 1 мс и т. Д. Это делает невозможным измерение небольших таймфреймов. Если функция очень быстрая - 0 мс - понятный результат. (Спасибо @kaiido) Источник: бумага , дополнительные ссылки здесь

  2. Любой код (включая JS) в многопоточной среде не будет выполняться с постоянной производительностью (по крайней мере, из-за переключения потоков ОС). Поэтому получение согласованных значений для нескольких отдельных прогонов - недостижимая цель. Чтобы получить какое-то точное число - функция должна выполняться несколько раз, а среднее значение принимается . Это будет работать даже с низкой точностью performance.now(). (Скучное объяснение: если функция намного быстрее, чем 0,1 мс, и браузер часто выдает результат 0 мс, но время от времени при запуске какой-либо функции выигрывается лотерея, а браузер возвращает 0,1 мс ... более длинные функции чаще выигрывают в этой лотерее)

  3. В большинстве движков JS есть "оптимизирующий компилятор". Оптимизирует часто используемые функции. Оптимизация стоит дорого, поэтому движки JS оптимизируют только часто используемые функции. Это объясняет увеличение производительности после нескольких прогонов. Сначала функция выполняется самым медленным способом. После нескольких выполнений он оптимизируется, а производительность увеличивается. ( следует добавить прогрев прогонов? )


Мне удалось получить ненулевые числа в вашем фрагменте кода - скопировав файл 70 КБ во входные данные. После 3-го запуска функция была оптимизирована, но даже после этого - производительность не постоянна

time taken is 11.49999990593642
time taken is 5.100000067614019
time taken is 2.3999999975785613
time taken is 2.199999988079071
time taken is 2.199999988079071
time taken is 2.099999925121665
time taken is 2.3999999975785613
time taken is 1.7999999690800905
time taken is 1.3000000035390258
time taken is 2.099999925121665
time taken is 1.9000000320374966
time taken is 2.300000051036477

Объяснение 1-й точки

Допустим, произошли два события, и цель состоит в том, чтобы найти время между ними. Первое событие произошло во время A, а второе произошло во время B. Браузер округляет точные значения A и B и возвращает их.

Несколько случаев, чтобы посмотреть:

A       B       A-B         floor(A)    floor(B)    Ar-Br      
12.001  12.003  0.002       12          12          0
11.999  12.001  0.002       11          12          1
0 голосов
/ 15 сентября 2018

Браузеры умнее, чем мы думаем, есть много улучшений и методов кэширования для выделения памяти, повторяющегося выполнения кода, выделения ЦП по требованию и так далее. Например, V8, механизм JavaScript, который поддерживает Chrome и Node.js , кэширует циклы выполнения кода и результаты . Кроме того, ваши результаты могут зависеть от ресурсов, которые ваш браузер использует при выполнении кода, поэтому ваши результаты даже при нескольких циклах выполнения могут отличаться.

Поскольку вы упомянули, что пытаетесь создать клон jsPerf, взгляните на Benchmark.js , эта библиотека используется командой разработчиков jsPerf.

Выполнение тестов анализа производительности действительно сложно, и я бы предложил запустить их в среде Node.js с предопределенными и предварительно выделенными ресурсами для получения ваших результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...