Как заставить Benchmark. js выполнять настройку / демонтаж каждый раз, когда запускается мой тестовый код (а не только каждый цикл)? - PullRequest
1 голос
/ 29 января 2020

Я пытаюсь сравнить функцию-член объекта, используя Benchmark.js. Тестирование функции затрудняется несколькими факторами:

  • Создание объекта асинхронно (я мог бы посмеяться над этой частью)
  • Функция-член стоит дорого
  • Функция-член достаточно умна, чтобы запускаться только один раз

Допустим, она выглядит следующим образом:

class Something {

  constructor(){
    // async ops
    this.expensiveValue = null;
  }

  expensiveOperation () {

    if (this.expensiveValue === null) {
      // Do expensive operation
      this.expensiveValue = result; // a non-null value
    }

  }

}

Теперь я хочу сравнить expensiveOperation. Но из-за его ограничений мне также нужно «сбрасывать» объект при каждом запуске.

Насколько я могу судить, benchmark не поддерживает настройки для каждого запуска. Я чувствую, что перезагрузка также не лучшая практика, потому что она загрязняет то, что я на самом деле пытаюсь оценить.

Я смотрел на Benchmark.setup, но это выполняется только в соответствии с цикл, а не за цикл.

Я что-то упустил? Есть ли другой вариант benchmark, который я могу использовать? Или я к этому неправильно подхожу?

Ответы [ 2 ]

2 голосов
/ 29 апреля 2020

? Вы не всегда можете получить то, что хотите ... ♩

Бенчмарк. js не выполняет setup / teardown за итерацию вашей функции, но только для каждой benchmark. js cycle, что обычно составляет всего 5 секунд, что может составлять от сотен до тысяч или миллионов вызовов. Это делается по очень веской причине, как объясняют авторы Benchmark. js в Bulletproof JavaScript тестах .

Если вы считаете, что эти причины к вам не относятся, тогда я спросил бы, почему вы даже используете Benchmark. js. Вы можете легко написать oop и измерить длительность каждого звонка и взять среднее значение самостоятельно, используя несколько строк кода. Вам не нужна необычная библиотека.

Вы не всегда можете получить то, что хотите

И если вы попробуете когда-нибудь, вы можете найти

Вы получаете ♫, что вам нужно. 10 ♪

Если честно, да, вы подходите к этому неправильно. Ваш expensiveOperation () разработан, чтобы быть эффективным для всех последующих вызовов, поэтому, конечно, хороший тест должен отражать это. Стоимость первого звонка амортизируется по всем последующим звонкам. Бенчмарк. js попытается измерить эффективность вашего метода , как задумано . В этом суть.

Подумайте о своей основной цели и о том, почему вы хотите сбрасывать ее для каждой итерации. Вы не хотите тестировать expensiveOperation (), а только эту часть метода:

      // Do expensive operation
      this.expensiveValue = result; // a non-null value

Так просто разложите это в метод или функцию и сравните это. :)

1 голос
/ 04 февраля 2020

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

Я думаю причина, по которой это невозможно, из-за того, как Benchmark. js выполняет синхронизацию.

Из того, что я прочитал (как в тексте, так и в коде), Benchmark не рассчитывает время и не суммирует отдельные прогоны, а вместо этого подсчитывает, сколько прогонов завершено за указанный количество времени (по умолчанию = 5 секунд). Это позволяет избежать определенных ошибок, таких как таймеры / временные метки низкой точности, оптимизация времени выполнения и ошибки округления с плавающей запятой.

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

По этим причинам кажется, что Benchmark. js не поддерживает функции настройки для каждого прогона, потому что это приведет к слишком много гаечного ключа в его работах и ​​снижает точность синхронизации.

...