Эта статья включена в репозиторий Github.GitHub.com/silently952…
Публичный аккаунт WeChat: бета изучает Java
предисловие
Я составил статью об инструментах диагностики и обработки ошибок JVM.Учитывая, что большинство Java-программистов используют IntelliJ Idea, в этой статье используются инструменты для тренировки и настройки скорости работы IntelliJ Idea.
Состояние работы перед настройкой
Исходное содержимое конфигурации
Чтобы запросить путь к исходному файлу конфигурации, идею можно просмотреть в обзоре в VisualVM.
Исходное содержимое конфигурации:
-XX:ReservedCodeCacheSize=240m
-XX:+UseCompressedOops
-Dfile.encoding=UTF-8
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:ErrorFile=$USER_HOME/java_error_in_idea_%p.log
-XX:HeapDumpPath=$USER_HOME/java_error_in_idea.hprof
-Xmx512m
Разработка плагина времени запуска печати
Вам нужно визуально увидеть изменение времени запуска до и после оптимизации, поэтому вам нужно просто разработать подключаемый модуль для идей. Процесс разработки подключаемого модуля для идей см. в моей предыдущей статье.«Плагин IDEA: разработка плагина для многопоточной загрузки файлов»
Время от времени запуска JVM до времени после завершения инициализации всех компонентов считается временем запуска IDEA.Код выглядит следующим образом
public class MyApplicationInitializedListener implements ApplicationInitializedListener {
@Override
public void componentsInitialized() {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
long startTime = bean.getStartTime();
long costTime = System.currentTimeMillis() - startTime;
Messages.showMessageDialog("毫秒:" + costTime, "启动耗时", Messages.getInformationIcon());
}
}
Добавьте следующий код в plugin.xml:
<extensions defaultExtensionNs="com.intellij">
<applicationInitializedListener id="MyApplicationInitializedListener"
implementation="cn.silently9527.MyApplicationInitializedListener"/>
</extensions>
Информация о запуске и затраты времени до оптимизации
Согласно информации, собранной плагином запуска VisualGC и IDEA:
- Запуск IDEA занимает 15 секунд
- В общей сложности 22 сборки мусора заняли 1,2 с, в том числе 17 сборщиков мусора нового поколения, которые заняли 324 мс; 5 сборщиков мусора старого поколения, которые заняли 953 мс.
- Загрузка 27526 классов заняла 21 секунду
По этим данным это нормально, а 15s на самом деле находится в допустимом диапазоне.Поскольку в этой статье в основном демонстрируется настройка производительности, необходимо протестировать, может ли она быть быстрее.
Начните пытаться оптимизировать
Настройка памяти для управления частотой сборки мусора
Из рисунка видно, что из 512 м памяти, заданных параметрами запуска, в новом поколении выделяется только 169 м. Так как IDEA является широко используемым инструментом для нашей разработки, обычный процесс компиляции также требует достаточно памяти, поэтому нам нужно сначала поставить общую память Чтобы расширить, здесь я ставлю максимальную память-Xmx1024m
, чтобы JVM не нужно было тратить время на динамический расчет размера расширения во время GC, а также устанавливать-Xms1024m
;
Всего в Eden в процессе запуска произошло 17 GC.Чтобы уменьшить количество GC в новом поколении, я установил размер памяти нового поколения на-Xmn256m
;
Глядя на VisualGC после перезапуска, количество сборщиков мусора нового поколения сократилось с 17 до 7, а время, затрачиваемое на выполнение, сократилось с 324 мс до 152 мс.
До подгонки памяти было 5 полных сборщиков мусора, а после подгонки памяти оставалось еще 4 полных сборщика мусора, но из двух рисунков видно, что в старости еще много места осталось, и полный сборщик мусора должен не происходит; подумайте, нет ли где-нибудь в коде ручного вызоваSystem.gc()
Полная сборка мусора запущена, поэтому параметры добавлены-XX:+DisableExplicitGC
, снова перезапустить IDEA, результат очень неутешителен, осталось еще 4 Full GC;
Внимательно наблюдайте за графиком перед повторной оптимизацией и обратите внимание на Last Cause: Metadata GC Threshold. Последний GC — это GC, который должен произойти из-за нехватки памяти в области метапространства. Чтобы проверить наше предположение, распечатайте журнал GC в видеть. существуетidea.vmoptions
Добавьте параметры, связанные с журналом печати:
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:../gc.log
Основные параметры журнала сборщика мусора JVM включают следующее:
- -XX:+PrintGC выводить журнал GC
- -XX:+PrintGCDetails выводить подробный журнал GC
- -XX:+PrintGCTimeStamps Вывод временных меток GC (в виде базового времени)
- -XX:+PrintGCDateStamps Распечатать метку времени сборщика мусора (в виде даты, например 2013-05-04T21:53:59.234+0800)
- -XX:+PrintHeapAtGC Распечатать информацию о куче до и после GC
- -Xloggc:../logs/gc.log Выходной путь к файлу журнала
Перезапустите идею и проверьте gc.log
в
PSYoungGen:
Указывает сборщик мусора ParallelScavenge, используемый новым поколением,31416K->0K(181248K)
Указывает размер используемой памяти до gc -> объем используемой памяти после gc (общий размер памяти области)
Из журнала видно, что каждый полный сборщик мусора связан сMetadata GC Threshold
, а Metaspace каждый раз почти не восстанавливает память, он просто расширяет вместимость этой области, легко найти причину и добавить следующие параметры для настройки размера Metaspace:
-XX:MetaspaceSize=256m
После повторного перезапуска Idea я обнаружил, что Full GC пропал, а настроение у меня было хорошее.
Тест открыл большой проект и щелкнул, чтобы скомпилировать код, и обнаружил, что моя идея застряла.После проверки VisualGC я обнаружил, что память кучи все еще свободна, и только метапространство было полностью занято, поэтому параметр максимального пространства я дал был слишком мал, поэтому я удалил его напрямую.-XX:MaxMetaspaceSize=256m
Выбор сборщика мусора
Только что из журнала gc мы видим, что по умолчанию используется сборщик мусора ParallelScavenge + Parallel Old. Эта комбинация ориентирована на пропускную способность. Здесь мы пытаемся перейти на сборщик мусора, который фокусируется на низкой задержке.
- ParNew + CMS
существуетidea.vmoptions
Добавьте следующую конфигурацию в:
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
Просмотр VisualGC после перезапуска IDEA
Очень стыдно, один и тот же GC случился 6 раз,ParallelScavenge + Parallel Old
Комбинация занимает 197 мс, в то время какParNew + CMS
Комбинация занимает 379 мс, хотя это результат, но нужно учитывать, что на данный момент произошло только MinorGC, что будет, если произойдет результат FullGC, вы можете проверить это сами
- G1
Мы пытаемся перейти на новейший сборщик мусора G1, вidea.vmoptions
Добавьте следующую конфигурацию в:
-XX:+UseG1GC
Этот результат кажется немного медленнее Я тестировал эти два сборщика мусора много раз, хотя результаты каждый раз разные, разница не далекая, поэтому сборщик мусора может выбирать сам, здесь мы выбираем G1
Оптимизация времени загрузки класса
Согласно предыдущему анализу, идея начала загружать 27526 классов, что заняло 21 с. Можем ли мы это оптимизировать? Поскольку идея является распространенным инструментом разработки и часто используется многими людьми, мы можем думать, что ее код безопасен, соответствует ли он требованиям текущей виртуальной машины и не будет угрожать безопасности виртуальной машины, поэтому мы используем параметр-Xverify:none
чтобы отключить процесс проверки байт-кода
перезапустить ИДЕЮ
Потребление времени сократилось до 11 секунд, а эффект все еще относительно очевиден.
Суммировать
После завершения всех оптимизаций, после нескольких рестарт-тестов, среднее время запуска упало до 11с.Чтобы утешить меня, что эта операция была не напрасной, я сделал картинку ниже 11с
Пишите до конца (обратите внимание, не потеряйтесь)
В тексте может быть больше или меньше недостатков и ошибок.Если у вас есть предложения или мнения, вы можете их комментировать и обмениваться.
Наконец,Проституция нехороша, творить нелегко, я надеюсь, что мои друзья могутНравится Комментарий ПодписатьсяСанлян, потому что это все источники мотивации, которыми я могу поделиться🙏
Я написал упрощенную версию springmvc с нуля и написал подробную документацию, чтобы помочь партнерам понять основные принципы springmvc. Друзья, которые в этом нуждаются, могут обратить внимание на общедоступный номер: бета-версия JAVA, ответ
源码
Просто
![]()