[Alibaba UED] Только фаст не ломается, пусть быстрее будет nodejs

Node.js JavaScript React.js

предисловие

В процессе настройки производительности страницы многие фронтенд-инженеры меньше внимания уделяют эффективности выполнения самого кода и больше внимания уделяют потреблению сети, например слиянию ресурсов для уменьшения количества запросов, сжатию для уменьшения размера ресурсов и т.д. кеширование и т. д. Я не считаю это необоснованным, наоборот, это достаточно правильно в значительной степени.Например, время выполнения самого JS составляет 30 мс (миллисекунд), что слишком мало для времени загрузки страницы от трех до пяти секунд.Даже если производительность улучшится в 10 раз и время выполнения уменьшится до 3мс, общее улучшение производительности незначительно, и даже не воспринимается на уровне пользователя.Поэтому разумнее оптимизировать основная часть другого потребления производительности.

Но с точки зрения Node.js (сервера) решающим стало время выполнения самого JS, в предыдущем примере, если время выполнения сократить с 30 мс до 3 мс, теоретически можно увеличить QPS в 10 раз. Другими словами, трафик, для которого раньше требовалось 10 серверов, теперь может нести один сервер, а время отклика меньше.

Итак, как сторона Node выполняет оптимизацию производительности?

метод

Есть два пути, один из нихNode/V8自带的profile能力(https://nodejs.org/uk/docs/guides/simple-profiling/), другой черезalinode(http://alinode.aliba-inc.com/) Функция профиля CPU. Первый только перечисляет выполнение каждой функции, последний включает более полный стек вызовов, более читаемость, более простые задачу позиционирования рекомендуется использовать последнее Отказ

Способ 1: Node поставляется со своим профилем

  • Шаг 1: Запустите приложение Node с параметром --prof

  1. $ node --prof index.js

скопировать код
  • Шаг 2. Пройдите инструмент стресс-тестированияloadtest(Https://github.com/alexfernandez/loadtest) Чтобы поставить давление на сервис

  1. $ loadtest  http://127.0.0.1:6001 --rps 10

скопировать код
  • Шаг 3: Обработайте сгенерированный файл журнала

  1. $ node --prof-process isolate-0XXXXXXXXXXX-v8-XXXX.log > profile.txt

скопировать код
  • Шаг 4. Проанализируйте файл profile.txt

profile.txtФайл показан ниже, включая количество тиков, потребляемых кодом JS и C++.Для конкретных методов анализа см.node profile文档(https://nodejs.org/uk/docs/guides/simple-profiling/)

Способ 2: профиль ЦП алинода

  • Шаг 1: Установите Алинод

ALINODE - это полностью совместимая среда двоичной среды выполнения с версией сообщества узла, рекомендуется использовать TNVM Tools для установки

  1. $ wget -O- https://raw.githubusercontent.com/aliyun-node/tnvm/master/install.sh | bash

скопировать код

После завершения установки необходимо добавить tnvm в качестве программы командной строки, в зависимости от платформы это может быть ~/.bashrc, ~/.profile или ~/.zshrc и т. д.

  1. $ source ~/.zshrc

скопировать код

Возьмите в качестве примера alinode-v3.8.0, соответствующий node-v8.9.0, загрузите эту версию и включите ее.

  1. $ tnvm install alinode-v3.8.0

  2. $ tnvm use alinode-v3.8.0

скопировать код
  1. $ node --perf-basic-prof-only-functions index.js

скопировать код
  • Шаг 3: Инструмент измерения давленияloadtest

  1. $ loadtest  http://127.0.0.1:6001 --rps 10

скопировать код

Предполагая, что номер рабочего процесса, который нужно запустить, равен 6989, выполните следующий скрипт, файл cpuprofile будет создан в каталоге /tmp/ через три минуты./tmp/cpu-profile-6989-XXX.cpuprofileПодробности смотрите в сценарииtake_cpu_profile.sh(https://github.com/alibaba/beidou/blob/master/scripts/take cpuprofile.sh)

  1. $ sh take_cpu_profile.sh 6989

скопировать код
  • Шаг 5: Полученный файл в CPUPROFIL анализируемый инструменты разработчика Chrome

Настоящий

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

Запросите 1000 раз через loadtest, подсчитайте среднее RT, и начальное RT составляет 15,8 мс.

За исключением потребления программы и сборщика мусора, три основных показателя потребления производительности:getJа также _evalтри пути

Расширить наиболее интенсивную производительностьgetСтек вызовов методов, его можно расположить вgetРасположение метода, конкретный код выглядит следующим образом

  1. {

  2.    key: 'get',

  3.    value: function get(propName) {

  4.      if (!this.state[propName]) {

  5.        return null;

  6.      }

  7.      return JSON.parse(JSON.stringify(this.state[propName]));

  8.    }

  9.  }

скопировать код

В теле методаJSON.parse(JSON.stringify(obj))Несмотря на то, что это удобно в использовании, это операция с интенсивным использованием процессора.Выполните проверку, удалите операцию и вернитесь напрямую.this.state[propName], Время RT уменьшено до 12,3 мс

JSON.parse(JSON.stringify(obj))В противном случае это повлияет на бизнес логику. Обратитесь к общему методу копирования性能对比

Второй расход -Jметод, большую часть которого составляет время рендеринга каждого компонента, временно пропустить его, и точно так же_evalМетод оптимизируется один раз, и время восстановления уменьшается до 10,1 мс.

Примечание: Эта статья была впервые опубликована на Beidou isomorphism github (https://github.com/alibaba/beidou/blob/master/packages/beidou-docs/articles/node-performance-optimization.md), пожалуйста, укажите источник для перепечатки .