Что такое профилирование?
Процесс детализации кода и конфигурации приложения для поиска потенциальных узких мест в производительности. Профилирование - одно из наиболее важных действий, необходимых для обеспечения масштабируемости приложения. Таким образом, с помощью профилирования мы сможем найти:
- Где тратится процессорное время?
- Сколько памяти выделено каким объектам? (Также помогает проверить, есть ли утечка памяти - пространство занято неиспользуемым объектом)
Профилирование также помогает выполнять эффективное Планирование емкости (ссылка в конце блога) означает, сколько ЦП / памяти требуется для эффективной работы приложения в соответствии с SLA. Это, в свою очередь, также помогает сократить расходы.
Управление памятью в Node.JS:
Управление памятью в Node - это фактически управление памятью в V8. Управление памятью V8 почти аналогично JVM, разделено на 3 сегмента:
- Код: фактическое пространство для выполнения кода.
- Стек: пространство локальных переменных
- Куча: хранение ссылок, таких как строки, объекты и замыкания.
Сегменты кучи V8 - на более широком уровне ниже представлены сегменты:
- Новое пространство: здесь размещаются вновь созданные объекты (небольшая и быстрая сборка мусора). - Молодое поколение
- Старое пространство указателя: объекты, которые могут иметь указатель на другие присутствующие здесь объекты. Сюда переместились предметы, уцелевшие в New Space. - Старое поколение
- Старое пространство данных: объекты, содержащие данные (без указателей), то есть строки, числа в рамке и массив чисел без коробки перемещаются сюда после выживания в новом пространстве. - Старое поколение
- Пространство для больших объектов. Содержит объекты, размер которых превышает размер других пространств. Каждый объект получает свою собственную область mmap в памяти. - Старое поколение
- Пространство кода (исполняемый код) и Пространство карты (скрытые классы) - Старое поколение.
Каждое пространство состоит из набора страниц (непрерывный блок памяти). Страницы, отличные от размера больших объектов, имеют размер 1 МБ.
Алгоритмы сборки мусора V8:
- Короткая сборка мусора / мусор (молодое пространство) - Выделение для молодого поколения очень дешево. Он поддерживает указатель, который увеличивается всякий раз, когда добавляется новый объект, и когда пространство заполнено / указатель достигает конца, запускается Очистка. Это отслеживающая сборка мусора, которая работает путем перемещения доступных объектов и восстановления недоступных. Подходит только для небольшого пространства, так как у него большое пространство над головой. Время паузы обычно составляет ~ 2 мс
- Полная GC / Mark Sweep & Mark Compact - Объекты, пережившие несколько коротких GC, перемещаются в Old Space. Полный сборщик мусора (основной сборщик мусора) запускается, когда пространство старого поколения заполнено. Полный сборщик мусора обычно содержит сотни мегабайт данных и вызывает накладные расходы на производительность (полный сборщик мусора инициирует ОСТАНОВИТЬ МИРОВОЕ СОБЫТИЕ, т. Е. Приложение не отвечает, так как во время полного сборщика мусора требуется длительная пауза), поэтому Полные циклы сборщика мусора должен быть минимальным, чтобы можно было контролировать производительность приложения. Для полной GC V8 в основном зависит от Mark Sweep Collection и Mark Compacting.
Mark Sweep отслеживает сборку мусора, при которой мы сначала отмечаем все достижимые объекты, а затем очищаем память (для недоступных объектов). Это может вызвать фрагментацию.
Сжатие меток ( следующий шаг очистки меток) сжимает все достижимые объекты, а затем перемещает их в непрерывный блок памяти (для эффективного использования). Без фрагментации
Время паузы для сканирования метки: ~ 50 мс
Время паузы для Mark Compact: ~ 100 мс
С помощью приведенных выше алгоритмов для нашего приложения добавляется много времени паузы и производительность приложения Suffer. Чтобы сократить время паузы, Google представил в 2012 году инкрементную маркировку и медленную развертку.
В этом случае маркировка начинается, когда куча достигает определенного порога, и, несмотря на время паузы ~ 100 мс, она делает паузу на ~ 5 мс и отмечает, снова запускается мутатор (программа JS), снова запускается маркировка, и это продолжается. Параллельно запускается очистка недостижимых объектов и минимизируются паузы (заботится о производительности приложения). Но если скорость выделения очень высока во время инкрементного GC, тогда JS-движок может запускать OOM, и нужно позаботиться о неинкрементном GC.
Прежде чем перейти к фактическому профилированию Node.JS, давайте начнем с создания журналов сборки мусора при запущенной программе узла с помощью trace_gc:
узел - trace_gc build / server.js (если вы хотите выгрузить какой-либо файл, используйте ›› dump.txt). Ниже вывод:


Здесь мы можем увидеть, какая сборка мусора инициирована, и 2,5 - ›2,3, вероятно, будут обозначать память перед сборкой мусора и память после сборки мусора. Также мы получили время, потраченное на выполнение конкретного GC)
Как профилировать приложения Node.JS / Javascript с помощью бесплатных / утилит?
- Использование Chrome V8 (инструменты разработчика)
- V8-Profiler / V8-Profiler-next (модуль npm)
- Модуль HeapDump (можно использовать для производства)
- Профилировщик кучи выборки (можно использовать для производства)
- Использование памяти с использованием процесса узла
Использование Chrome V8:
запустите сервер с помощью следующей команды в режиме проверки:
узел - проверить build / server.js

Теперь откройте хром и введите chrome: // inspect / # devices в адресной строке. После этого появится окно, показанное ниже. щелкните ссылку ниже target, чтобы выбрать цель:

Теперь мы получаем инструменты разработчика, как показано ниже в окне.

Профилирование ЦП с помощью Chrome V8:
Нажмите кнопку профиля в окне инструментов разработчика.

Нажмите «Пуск», а затем, если хотите «Остановить профилирование ЦП», нажмите «Стоп» (он появится после нажатия «Пуск»). Мы получим снимок, как показано ниже

Выберите диаграмму из раскрывающегося списка под профилировщиком. Ниже будет показана диаграмма, показывающая время, потраченное на каждую часть процессора:

И когда мы нажимаем на любую часть, он переходит в кодовую точку, где тратится фактическое время.
Снимки кучи профилирования памяти версии 8:
Json с выделением памяти для каждого объекта.
Чтобы сделать снимки кучи, нажмите кнопку памяти (слева от профилировщика). Появится экран ниже:

Нажмите кнопку Сделать снимок.

На самом деле это снимок кучи (выделение памяти в определенный момент). Это дает полное представление о том, какие объекты занимают сколько памяти для своей работы.
Также мы можем увидеть агрегированную статистику, выбрав Статистику из раскрывающегося списка под профилировщиком:

Теперь один из способов поиска утечек - это сравнить снимки кучи с разными снимками, и мы можем определить, какие объекты сохраняют память дольше всего. Chrome V8 дает возможность сравнивать разные снимки:
Возьмите другой экран, щелкнув точку (черную) в верхнем левом углу. Ниже мы видим оба скриншота:

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

Выше показаны общие объекты между этими двумя снимками - одинаковые объекты, занимающие память в обоих снимках.
Теперь, помимо анализа, мы можем сохранять снимки состояния ЦП и памяти на нашем компьютере для совместного использования или анализа в будущем.
Модуль V8-profile / v8-profiler-next npm:
Внутри него используется тот же Chrome v8, но он предоставляет альтернативный способ создания снимков.
Чтобы получить снимки, нам нужно добавить несколько строк кода.
Снимки ЦП
Я создал одну конечную точку _status get и добавил в нее несколько строк кода.

Теперь я попаду в конечную точку / _status get, и мы получим файл cpu_snapshot (дамп времени процессора)

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


Снимки памяти / кучи:
Добавьте приведенный ниже код и запустите _status api. Получим heap_snapshot.heapdump

Давайте откроем то же самое в снимке кучи в инструментах разработчика, выбрав из кнопки Загрузить:

H Модуль eapdump:
Вышеупомянутые методы не подходят для получения кучи на производстве. Так что для производства мы можем использовать heapdump, который имеет небольшой вес (меньше накладных расходов).
npm run install heapdump (или node.js v0.6 или v0.8 используйте heapdump 0.1.0)
Мы можем интегрировать код разными способами. Некоторые из них перечислены ниже:
- Создайте конечную точку, которая будет генерировать дамп кучи
- На платформах Unix мы можем использовать kill -USR2 ‹PID›
Демонстрация 1-го метода:


Файл дампа кучи:

Теперь мы можем скопировать снимок кучи с удаленного сервера и легко открыть его в профилировщике памяти chrome dev tools.
Профилировщик кучи выборки (облегченный - для рабочей среды)
В основном он берет случайную выборку объектов по мере их распределения и поддерживает статистические данные для кучи / памяти. Мы также можем просматривать жизнь объектов по этим данным (от жизни до смерти).
npm установить профиль кучи
Добавьте ниже код в файл main.js. Код ниже генерирует снимки кучи каждые 1000 секунд.

Мы загрузим этот файл в инструменты chrome dev, и он даст диаграмму, как показано ниже (что-то похожее на то, что мы получили для процессора)

Использование памяти с использованием процесса узла (не подходит для производства как такового)
На высоком уровне мы можем разделить потребление памяти на 4 части:
- rss - размер резидентского набора. Количество используемых процессом узла RAM (V8, ядро узла, любая зависимая библиотека). Ожидаемое стабильное значение для rss, так как все эти вещи будут занимать память только при запуске процесса. Если размер rss увеличивается, мы можем подумать, что произошла утечка памяти.
- heapTotal - общее пространство, доступное для объектов javascript. Он будет подниматься и опускаться вместе с GC.
- heapUsed - Общее пространство, занятое объектами JS в текущий момент.
- внешняя: память, используемая узлом для объектов вне кучи, таких как буферы.
const {rss, heapTotal} = process.memoryUsage ();
Для анализа производительности и управления памятью приложений Java см. сообщения ниже:
В случае возникновения каких-либо вопросов и предложений, пожалуйста, свяжитесь со мной https://www.linkedin.com/in/rishabh-jain-a5978583/ или напишите письмо @ rishabh171192 @ gmail.com