Действительно ли node.js работает медленнее в Windows? Как использование пряжи вместо npm влияет на ваш рабочий процесс? Влияет ли антивирус в реальном времени на время вашего строительства? Позвольте мне попытаться ответить на эти вопросы с помощью быстрого теста и реальных, экспериментально собранных чисел.

Я всегда считал себя далеким от религиозности в области операционных систем, платформ и браузеров. Очевидно, что у меня есть некоторые предпочтения, но я стараюсь не вовлекать их в обсуждение. Кто-то использует Linux? Круто, если им это хорошо. Windows? Отлично, может им просто нравится этот опыт. MacOS? Я не против. Fire Fox? Опера? Хром? Все нормально.

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

Поскольку я работаю с различными проектами и инструментами для решения проблем моих коллег по команде, я часто меняю рабочую среду: часть моей работы выполняется с использованием MacBook с macOS, некоторые части выполняются в Windows, время от времени перескакиваю на линукс. И обычно существенной разницы не замечал.

Однако несколько месяцев назад я начал чувствовать легкий… зуд. У меня возникло ощущение, что производительность интерфейсных инструментов разработки на основе node.js ограничивается средой Windows. Работать было нормально, но я не мог избавиться от ощущения, что npm, node, yarn и подобные инструменты работают… медленнее, чем в системах linux / macOS. Очевидно я был не один - было несколько сообщений о подобных переживаниях, но без надлежащих выводов.

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

Результаты были однозначными. Просмотрите эту статью, чтобы узнать, что я обнаружил.

Метод

Основная цель заключалась в том, чтобы сравнить производительность Windows и Linux, протестировать их на наиболее распространенных сценариях:

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

Планировалось включить macOS в тесты, но у меня не было возможности запустить Windows и macOS на одном и том же оборудовании. В итоге мы сравнили производительность двух популярных систем:

  • Windows 10 Pro (сборка 1809, обновление за октябрь 2018 г.)
  • Ubuntu 18.04.2 LTS с ядром Linux 5.0.0–23

Выбирая технологии, которые будут служить наилучшим эталоном, я обратился к React с помощью TypeScript и Webpack (из пакета create-react-app). Кроме того, я решил протестировать и NPM, и yarn с точки зрения управления зависимостями. Время сборки проверялось не только на небольшом количестве файлов, но и на сотнях. Я закончил разработку схемы теста, состоящей из следующих шагов:

  1. Создайте шаблон приложения с помощью create-response-app с включенным TypeScript (тест №1)
  2. Сбросьте зависимости (удалите node_modules) и извлеките конфигурацию
  3. Установите зависимости:
  • с помощью npm install с сохранением package-lock.json (контрольный показатель 2)
  • с помощью npm install при удалении package-lock.json при каждом запуске (тест № 3)
  • используя пряжу с сохранением yarn.lock (эталон №4)
  • использование yarn install при удалении yarn.lock при каждом запуске (тест № 5)

4. Создайте приложение с шаблоном:

  • небольшое количество (3) исходных файлов (тест №6)
  • наличие большого количества (300+) исходных файлов (тест №7)

Чтобы результаты теста были максимально достоверными и правдивыми, были применены следующие правила:

  • Обе протестированные системы изначально работали на одной машине без виртуализации (Asus P25P20L с процессором i5–5200U и 16 ГБ ОЗУ).
  • Обе системы были недавно установлены. Во время тестирования не было других запущенных приложений.
  • Каждый тест проводился не менее 5 раз, чтобы свести к минимуму случайность. Окончательный результат - это средний результат тестовых прогонов.
  • Машина была подключена к стабильному интернет-каналу на основе оптоволокна с пропускной способностью 300/300 Мбит / с. В обеих системах заранее был проведен тест на подключение к Интернету.
  • Перед первым запуском каждого теста в серии выполнялся предварительный запуск, чтобы подготовить и прогреть кеш приложения.

Кроме того, одни и те же версии node.js и других инструментов использовались на двух платформах:

  • узел 12.7.0
  • npm 6.10.0
  • create-react-app 3.0.1
  • пряжа 1.17.3

Очевидно, что время было основным измеряемым показателем. Конечно, я не использовал для этого ручной секундомер - чтобы получить точный результат, я создал небольшое приложение node.js, которое выполняло за меня запуск теста и измерения. Вот как это выглядело в случае разработки приложений:

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

В случае тестов Windows был еще один существенный фактор - в версии 10 по умолчанию установлен антивирус, который сканирует всю файловую активность в режиме реального времени. Поскольку я думал, что это может сильно повлиять (и мальчик, я был прав!) На производительность npm и yarn, тесты Windows проводились независимо с упомянутым антивирусом, как включенным, так и отключенным.

Результаты

Тест №1: создание экземпляра приложения с помощью приложения create response

Описание:

Во время каждого тестового запуска вызывалась команда create-response-app, чтобы вывести приложение React и TypeScript в новый каталог.

Результаты:

Комментарий:

Ubuntu - явный победитель с приростом более чем на 25% по сравнению с Windows! Кроме того, мы можем видеть, насколько сильно антивирус влияет на производительность - ему потребовалось почти вдвое больше времени для создания каркаса приложения, когда оно было включено.

Тест №2: установка зависимостей с помощью npm install с сохранением package-lock.json

Описание:

Во время каждого тестового запуска вызывалась команда npm install для восстановления зависимостей. Ранее каталог `node_modules` был удален, но файл package-lock.json остался на месте.

Результаты:

Комментарий:

Между Ubuntu и Windows огромная пропасть - разница почти в три раза. Кроме того, антивирус в Windows добавляет дополнительные 100% накладных расходов.

Тест №3: установка зависимостей с помощью npm install при удалении package-lock.json при каждом запуске

Описание:

Во время каждого тестового запуска вызывалась команда npm install для восстановления зависимостей. Предварительно были удалены и `node_modules`, и package-lock.json.

Результаты:

Комментарий:

Опять же, разрыв между Ubuntu и Windows довольно велик, однако соотношение уменьшилось. Обратите внимание, что удаление package-lock.json привело к увеличению объема необходимых вычислений по сравнению с изменением дисковых операций.

Тест №4: установка зависимостей с помощью yarn при сохранении yarn.lock

Описание:

Во время каждого тестового прогона вызывалась команда `yarn` для восстановления зависимостей. Ранее каталог `node_modules` был удален, но файл yarn.lock остался на месте.

Результаты:

Комментарий:

Использование Yarn продемонстрировало значительное улучшение по сравнению с npm в обеих системах, но все же выявило слабые места версии для Windows. Разница между включенным и отключенным антивирусом значительно меньше, что указывает на меньшее количество операций с диском по сравнению с npm.

Тест №5: установка зависимостей с помощью yarn install при удалении yarn.lock при каждом запуске

Описание:

Во время каждого тестового прогона вызывалась команда `yarn` для восстановления зависимостей. Предварительно были удалены и `node_modules`, и yarn.lock.

Результаты:

Комментарий:

Отсутствие использования файла блокировки при установке зависимостей с помощью yarn привело к значительному снижению производительности. Кроме того, умеренно уменьшились различия между двумя операционными системами.

Контрольный тест № 6. Создание приложения-шаблона с небольшим количеством (3) исходных файлов

Описание:

Во время каждого запуска теста Webpack и транспилятор машинописного текста вызывались с помощью команды npm run build. Исходный код состоит из трех файлов кода TypeScript среднего размера. Перед каждым тестом удалялась директория с выходом бандла.

Результаты:

Комментарий:

Наконец, узел, работающий в Windows, догоняет и показывает производительность, аналогичную той, что работает в Ubuntu. Это указывает на то, что, хотя мы имеем дело с большим количеством вычислений по сравнению с дисковыми / сетевыми операциями, Windows существенно не отстает - пока у нас не включен антивирус в реальном времени.

Контрольный тест № 7. Создайте приложение с шаблоном, содержащее большое количество (более 300) исходных файлов

Описание:

Во время каждого запуска теста Webpack и транспилятор Typescript вызывались с помощью команды npm run build. Исходный код состоит из более чем 300 файлов кода TypeScript среднего размера. Каждый из файлов кода включал 10 экспортируемых переменных и экспорт по умолчанию (см. Прикрепленный тестовый репозиторий). Они были объединены с использованием древовидной структуры с несколькими уровнями файлов. В итоге все постепенно было импортировано в основной файл index.ts. Как и раньше, перед каждым запуском теста каталог с бандлом удалялся.

Результаты:

Комментарий:

По сравнению с версией с меньшим количеством файлов, этот тест показывает более заметную разницу между узлом, работающим в Ubuntu, и узлом в Windows. Что интересно, в отличие от предыдущего - на этот раз антивирус не сильно повлиял на результат. Имея в виду, что мы не выводим много файлов (результат объединяется Wepack), это означает, что антивирус имеет значение только количество запускаемых исполняемых файлов.

Выводы и выводы

Пришло время подвести итоги! В среднем задачи, выполняемые в Ubuntu, имели примерно на 41% более высокую производительность, чем в Windows. Чем больше было задействовано дисковых операций, тем значительнее разница.

Говоря о Windows, оказывается, что включение антивируса приводит к снижению производительности на 44%, что указывает на то, что разработчик не должен забывать занести узел и npm в белый список - в противном случае это серьезно снизит время обработки.

Случайно оказывается, что эксперимент - чертовски хорошая реклама использования пряжи. Во всех тестах он работал значительно быстрее, чем npm - в среднем он работал примерно на 32% быстрее.

И, возвращаясь к основному вопросу, цифры довольно ясны - инструменты на основе node.js дают значительно худшую производительность при работе в Windows. В чем может быть причина? Проблема может заключаться не в Windows или самом node.js - в конце концов, в обоих сценариях это собственный исполняемый файл, который обрабатывается на ЦП.

Я считаю, что проблема в том, как они взаимодействуют на уровне ввода-вывода.

Обратите внимание, что наиболее существенные различия возникают в тестах на основе npm - в этих сценариях тысячи небольших дисковых операций выполняются с небольшими файлами. И именно здесь файловая система NTFS может отставать от системы Ubuntu ext4 - просто она менее оптимизирована для множества небольших операций. Обратите внимание, что этот процесс также сильно использует сеть - когда кеш пуст, npm Mush-запрос для каждого пакета отдельно. Это может указывать на то, что сетевой уровень Windows недостаточно отзывчив, чтобы обеспечить максимальную потенциальную производительность, когда сотни HTTP-запросов необходимо обрабатывать и быстро переключать. Тема не нова - погуглив, можно найти статьи, описывающие прямое измерение производительности файловых систем.

Что это значит для нас, фронтенд-разработчиков? Конечно, в большинстве сценариев работа в Windows приводит к потере всего нескольких секунд в день по сравнению с Linux, что для многих не является платой за отказ от своей любимой среды. Использование NPM в Windows может быть медленнее, но, в конце концов, мы не переустанавливаем все зависимости несколько раз в день. Однако, если ваш проект тяжелый (сотни исходных файлов), включает в себя более сложный процесс транспиляции (например, несколько загрузчиков и TypeScript) и требует, чтобы вы собирали его очень часто (например, частые выпуски в разных средах), вы можете потерять значительную часть времени. и переход на Linux можно было бы рассмотреть в целях экономии времени. То же самое относится к интенсивно используемым конвейерам CI / CD - если вы используете конвейер на базе Windows (например, в Azure DevOps), помимо затрат на лицензирование, это может быть дороже только из-за затраченного времени на сборку.

Означает ли это, что вам следует отказаться от Windows? Неа. Но теперь вы знаете цену.

Если вы хотите поиграть с ним самостоятельно и получить свои собственные результаты (и выводы!), Не стесняйтесь использовать тестовый код, который я использовал:
https://github.com/hzub/node-perf -test
Репозиторий включает тестовый код и пример скаффолдинга приложения, которые использовались в этой статье. Не забудьте поделиться своими результатами!

Ваше здоровье!