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

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

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

Примерно через 4 минуты я закончил его, и он прошел все тестовые сценарии, чем я очень горжусь, я продолжаю другие тесты, которые пришли мне в голову, что, если они также заботятся о производительности метода?, поэтому я начал рефакторинг и снова запускал тестовые сценарии и снова работал как часы.

Из-за моего нехватки времени я закончил тем, что пошел дальше и закончил остальные тесты. я закончил их вскоре после этого и представил свои ответы.

Но одна вещь продолжала петь мне краем уха: что, если while(true) будет быстрее, и они могут воспринять это как отрицательный момент?

Структура интервью спланирована таким образом, что я выполняю эти тесты, и они бросят мне вызов на следующем собеседовании.

Так что у меня было несколько дней, чтобы подготовиться и поразить их своим лучшим ударом. Я пробовал разные способы бенчмаркинга, и все они оказались мусором, и мне пришлось написать свой собственный инструмент бенчмаркинга.

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

Гипофиз:

While(true) работает лучше, чем for(;;) при выполнении следующего метода:

Сценарии:

#1: Запустите метод добавления с помощью for(;;) и верните время выполнения.

№ 2: Запустите метод добавления с помощью while(true) и верните время выполнения.

Оба приведенных выше сценария выполняются снова во времени, а это означает, что мы пытаемся рассчитать, сколько времени потребуется для выполнения метода add() определенное количество раз, которое в данном случае составляет 1 миллиард раз( циклы).

Метрики (результаты):

Стоит отметить, что мой бенчмаркинг дошел до выполнения сценария 100 раз и вычисления среднего, суммы и минимума (что указывает на самый быстрый результат в каждом сценарии) результатов.

После запуска теста на моем ноутбуке, который представляет собой 13-дюймовый Macbook air 2017 года с двухъядерным процессором Intel Core i5 с тактовой частотой 1,8 ГГц, 8 ГБ оперативной памяти DDR3–1600 и флэш-памятью ~ 250 ГБ,

Я с гордостью пришел к выводу, что for(;;) работает быстрее, чем while(true), основываясь на следующих результатах.

Чтобы разбить результаты, в среднем for(;;) вычислил все за ~725,90 мс, сравните с ~804,94 мс для while(true), из которого делается вывод о том, какой из них быстрее.

Для min, которое вычисляет самое быстрое время для каждой попытки, снова for(;;) оказалось быстрее на ~703,79 мс по сравнению с ~ 704,17 мс.

В целом, for(;;) снова стал быстрее, запустив все за ~75 290,15 мс (~75,2 с) по сравнению с ~80494,78 мс (~80,4 с) , что соответствует сценарию while(true).

Понятно, что for(;;) работает быстрее, чем while(true).

Вы даже можете убедиться в этом, поместив данные в график.

PS: если вам интересно, почему на диаграмме много пиков, это из-за сборки мусора. после запуска nodejs будет период времени, когда весь процесс зависнет, пока GC не очистит память, а затем не переведет процесс в рабочее состояние. этот процесс работает на основе интервалов, которыми вы также можете управлять с помощью атрибута — gc-interval в команде node.

Этот атрибут будет включать двигатель V8. вы можете использовать команду node — v8-options, чтобы просмотреть параметры V8. поверьте мне, как только вы проверите это, вы найдете там много интересного, чтобы занять себя.

Но подождите секунду, я только что провел тесты и вижу разные результаты.

Похоже, я был неправ, и пока быстрее.

но как это вообще возможно?

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

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

Вот где я немного разочаровался и перестал работать над этим.

Используйте второй шанс:

Прошло некоторое время, и я как бы забыл об этом своем маленьком проекте, когда я случайно открыл одно из рекомендованных YouTube видео, связанных с обратным проектированием и работой с такими инструментами, как IDA, и доступом к встроенным системам с помощью UART.

Когда я посмотрел на анализ IDA прошивки устройства, к которому пользователь YouTube получил доступ через UART, я понял, что байт-код может быть ключом к тестированию и посмотреть какой из них быстрее раз и навсегда.

Итак, я начал копать.

Вы помните, что некоторое время назад я упоминал об опциях V8 на nodejs? это пригодилось, когда я запустил grep по байт-коду ключевого слова, и я получил это:

Как говорят французы, и вуаля!!!

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

Теперь мне нужно извлечь байт-код, сгенерированный интерпретатором зажигания для testFor() и testWhile(), и сравнить результаты:

Удивительно, но кроме адресов памяти обе инструкции одинаковы.

Вывод:

Как показали результаты, при выполнении нет разницы между использованием for(;;) и while(;;).

Однако я также должен упомянуть, что этот тест выполнялся при определенных условиях, которые сыграли роль в получении этого результата, таких как архитектура процессора (x86, также известная как CISC), которая может в конечном итоге почтить своих конкурентов, таких как RISC, который был изобретен для встраиваемых чипов компанией arm, конкурентами движка javascript, такими как SpiderMonkey, JavaScriptCore, Chakra или движком facebook hermes.

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

Я разместил свои эксперименты на эту тему на Github.

Хотите подключиться?

Вы всегда можете связаться со мной в Twitter в любое время, и я вернусь к вам как можно скорее.

Я всегда готов больше экспериментировать и проводить исследования, связанные с данными, так что звоните мне, если у вас есть интересные идеи.