Ожидается ли сбор GC 32% времени выполнения? - PullRequest
2 голосов
/ 04 мая 2019

В настоящее время работает над оптимизацией библиотеки для скорости.Я уже значительно сократил время выполнения, используя V8 CPU и Memory Profiling через Webstorm.Это было достигнуто главным образом путем изменения основного метода с рекурсивного на итеративный .

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

enter image description here

Я предполагаю, что первая запись "узел" синхронизирует вызовы внутренних функций, и это здорово.Другие записи также имеют смысл.Я новичок в профилировании Nodejs, но 31,6% для GC кажется высоким, поэтому я решил исследовать.

Я сейчас создал дамп кучи через Webstorm, но, к сожалению, это не дает мне многоинформация.

enter image description here

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

Вопрос

  • Можно ли уменьшить накладные расходы GC?
  • Ожидается ли здесь только такая сумма распределения?
  • Можно липолучить более подробную информацию о профилировании памяти?

Инструкции по установке

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

Загрузите или клонируйте object-scan и запустите

yarn install --frozen-lockfile
yarn run test-simple --verbose

Теперь создайте файл test.js в корневом каталоге проекта, содержащий это содержимое и выполните node --trace_gc test.js илизапустите его через Webstorm для расширенного профилирования.

1 Ответ

1 голос
/ 05 мая 2019

В Javascript и в v8 (узел), в частности, количество времени, затрачиваемое на сборку мусора, зависит от объема данных, хранящихся в куче, но это только один из многих факторов.

В двигателе v8 существует два основных типа GC: второстепенный (мусор) и крупный (метка-развертка / метка-компакт). Вы можете увидеть типы GC, которые происходят во время ваших тестов в консоли с включенным --trace-gc. И в разных случаях один тип мог «съесть» больше времени, чем другой, и наоборот. Поэтому перед оптимизацией вы должны определить, какой gc требует больше времени.

Вариантов оптимизации основного ГХ не так много, потому что на него сильно влияет количество данных, которые остаются в памяти в течение «длительного» (фактически в этом случае «длинный» означает, что объект переживает очистку ГХ). Такие данные хранятся в так называемом «старом пространстве» в куче. И основной сборщик мусора работает с этим пространством, и он должен сканировать всю эту память и помечать объекты, которые больше не имеют ссылок для дальнейшей очистки.

В вашем случае количество загружаемых тестовых данных уходит в старое пространство. В результате это влияет на основные GC в течение всего теста. И в этом случае основной GC не будет очищать слишком много, потому что вы используете свой тестовый объект, но он все еще требует времени для сканирования всего старого пространства. Таким образом, вы можете запретить v8 делать это, запустив узел с флагами, специфичными для gc, такими как: --nouse-idle-notification --expose-gc --gc_interval=100500 (где 100500 - номер выделения, может принимать высокое значение, которое не позволит запустить gc до того, как пройдет весь тест), что будет разрешить запуск сборщиков мусора вручную. Протестируйте свой код, используя этот подход, и посмотрите, как основной GC влияет на него, попробуйте тестировать с различным количеством данных, которые вы предоставляете для работы. Если влияние слишком велико, вы можете попытаться реорганизовать свой код, пытаясь минимизировать долгоживущие переменные, замыкания и т. Д.

Если вы обнаружите, что основной сборщик мусора не сильно влияет на производительность, тогда сборщик мусора занимает большую часть времени. В отличие от основных GC он работает с так называемым «новым пространством» в куче. Это пространство, где хранятся все новые объекты. Если эти объекты выживают, они перемещаются в старое пространство. Новое пространство имеет гораздо меньший размер (вы можете управлять им, установив --max_semi_space_size, примечание: new space size = 2 * semi space size), чем старое пространство, и будет происходить больше новых объектов и переменных, которые вы выделите для большего количества прогонов утилизации мусора. Если этот GC слишком сильно нагревает производительность, вы можете подумать о рефакторинге своего кода, чтобы сделать меньше новых выделений. Но если вы будете использовать переменные повторно, это также может замедлить производительность, и эти объекты уйдут в старое пространство и могут стать проблемой, описанной в разделе «Major GC».

Также v8 GC не всегда работает в том же потоке, что и ваша программа. Он также работает в фоновом режиме, но я не знаю, что показывает Webstorm в вашем случае. Если он учитывает только общее время, проведенное в GC, возможно, он просто не оказывает такого большого влияния. Вы можете найти более подробную информацию о v8 GC в этом блоге .

TL; DR:

Можно ли уменьшить накладные расходы GC?

  • Да, но сначала вы должны выяснить, что следует оптимизировать, выполнив описанные выше шаги.

Является ли эта сумма только что ожидаемой здесь?

  • Это может быть просто обнаружено путем сравнения различных подходов. Не существует какого-либо абсолютного числа, которое могло бы ограничить «хорошее» количество из «плохого», потому что оно зависит от множества факторов, включая количество входных данных.

Можно ли получить лучшую информацию о профилировании памяти?

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