предисловие
В процессе настройки производительности страницы многие фронтенд-инженеры меньше внимания уделяют эффективности выполнения самого кода и больше внимания уделяют потреблению сети, например слиянию ресурсов для уменьшения количества запросов, сжатию для уменьшения размера ресурсов и т.д. кеширование и т. д. Я не считаю это необоснованным, наоборот, это достаточно правильно в значительной степени.Например, время выполнения самого 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
$ node --prof index.js
скопировать код
-
Шаг 2. Пройдите инструмент стресс-тестирования
loadtest
(Https://github.com/alexfernandez/loadtest) Чтобы поставить давление на сервис
$ loadtest http://127.0.0.1:6001 --rps 10
скопировать код
-
Шаг 3: Обработайте сгенерированный файл журнала
$ 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 для установки
$ wget -O- https://raw.githubusercontent.com/aliyun-node/tnvm/master/install.sh | bash
скопировать код
После завершения установки необходимо добавить tnvm в качестве программы командной строки, в зависимости от платформы это может быть ~/.bashrc, ~/.profile или ~/.zshrc и т. д.
$ source ~/.zshrc
скопировать код
Возьмите в качестве примера alinode-v3.8.0, соответствующий node-v8.9.0, загрузите эту версию и включите ее.
$ tnvm install alinode-v3.8.0
$ tnvm use alinode-v3.8.0
скопировать код
$ node --perf-basic-prof-only-functions index.js
скопировать код
-
Шаг 3: Инструмент измерения давления
loadtest
$ 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)
$ sh take_cpu_profile.sh 6989
скопировать код
-
Шаг 5: Полученный файл в CPUPROFIL анализируемый инструменты разработчика Chrome
Настоящий
Ниже показано, как шаг за шагом выполнить настройку производительности на реальном примере.
Запросите 1000 раз через loadtest, подсчитайте среднее RT, и начальное RT составляет 15,8 мс.
За исключением потребления программы и сборщика мусора, три основных показателя потребления производительности:get
, J
а также _eval
три пути
Расширить наиболее интенсивную производительностьget
Стек вызовов методов, его можно расположить вget
Расположение метода, конкретный код выглядит следующим образом
{
key: 'get',
value: function get(propName) {
if (!this.state[propName]) {
return null;
}
return JSON.parse(JSON.stringify(this.state[propName]));
}
}
скопировать код
В теле метода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), пожалуйста, укажите источник для перепечатки .