Подтвердить что ты не робот

Установка -XX: + DisableExplicitGC в производстве: что может пойти не так?

у нас просто было совещание для решения некоторых проблем с производительностью в веб-приложении, которое используется для расчета ставок страхования. Расчеты выполняются в модуле C/С++, который также используется в других пакетах программного обеспечения. Чтобы сделать его доступным как веб-сервис, была реализована оболочка Java, которая предоставляет интерфейс на основе XML и вызывает модуль C/С++ через JNI.

Измерения показали, что несколько секунд были потрачены на каждый расчет внутри части Java. Таким образом, моя первая рекомодация заключалась в том, чтобы включить ведение журнала сбора мусора в виртуальной машине. Мы сразу увидели, что было сделано много прекрасных глобальных ГК. Говоря об этом, разработчик java-части сказал нам, что они несколько раз выполняли System.gc() "чтобы убедиться, что память выпущена после использования".

ОК, я не буду подробно останавливаться на этом утверждении...; -)

Затем мы добавили вышеприведенные -XX:+DisableExplicitGC аргументы виртуальных машин и повторили тесты. Это набрало около 5 секунд на расчет.

Так как мы не можем изменить код, сняв все эти вызовы System.gc() в этот момент нашего процесса выпуска, мы думаем о добавлении -XX:+DisableExplicitGC в производство до тех пор, пока не будет создан новый Jar.

Теперь возникает вопрос: может ли быть какой-то риск? Единственное, о чем я могу думать, это tomcat, использующий System.gc() внутренне при перераспределении, но это только предположение. Есть ли еще какие-то опасности?

4b9b3361

Ответ 1

Вы не одиноки в том, чтобы фиксировать события GC-события Stop-the-world, установив флаг -XX:+DisableExplicitGC. К сожалению (и, несмотря на отказ от документации в документации), многие разработчики решают, что они знают лучше, чем JVM, когда собирают память и вводят именно этот тип проблемы.

Мне известно о многих случаях, когда -XX:+DisableExplicitGC улучшил производственную среду и нулевые экземпляры, где были какие-то отрицательные побочные эффекты.

Безопасная задача - запустить текущий производственный код под нагрузкой, указав этот флаг в среде стресс-тестов и выполнить обычный цикл QA.

Если вы не можете этого сделать, я бы предположил, что риск установки флага меньше, чем стоимость его установки в большинстве случаев.

Ответ 2

Я боролся с этой же проблемой, и на основе всей информации, которую я смог найти, определенно, есть определенный риск. По комментариям к исходному сообщению от @millimoose, а также https://bugs.openjdk.java.net/browse/JDK-6200079, установлено, что установка -XX: + DisableExplicitGC будет плохая идея, если используются прямые буферы NIO. Похоже, что они используются во внутренней реализации сервера приложений Websphere 8.5, который мы используем. Здесь трассировка стека, которую я смог захватить при ее отладке:

3XMTHREADINFO      "WebContainer : 25" J9VMThread:0x0000000006FC5D00, j9thread_t:0x00007F60E41753E0, java/lang/Thread:0x000000060B735590, state:R, prio=5
3XMJAVALTHREAD            (java/lang/Thread getId:0xFE, isDaemon:true)
3XMTHREADINFO1            (native thread ID:0x1039, native priority:0x5, native policy:UNKNOWN)
3XMTHREADINFO2            (native stack address range from:0x00007F6067621000, to:0x00007F6067662000, size:0x41000)
3XMCPUTIME               CPU usage total: 80.222215853 secs
3XMHEAPALLOC             Heap bytes allocated since last GC cycle=1594568 (0x1854C8)
3XMTHREADINFO3           Java callstack:
4XESTACKTRACE                at java/lang/System.gc(System.java:329)
4XESTACKTRACE                at java/nio/Bits.syncReserveMemory(Bits.java:721)
5XESTACKTRACE                   (entered lock: java/nio/[email protected], entry count: 1)
4XESTACKTRACE                at java/nio/Bits.reserveMemory(Bits.java:766(Compiled Code))
4XESTACKTRACE                at java/nio/DirectByteBuffer.<init>(DirectByteBuffer.java:123(Compiled Code))
4XESTACKTRACE                at java/nio/ByteBuffer.allocateDirect(ByteBuffer.java:306(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/buffermgmt/impl/WsByteBufferPoolManagerImpl.allocateBufferDirect(WsByteBufferPoolManagerImpl.java:706(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/buffermgmt/impl/WsByteBufferPoolManagerImpl.allocateCommon(WsByteBufferPoolManagerImpl.java:612(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/buffermgmt/impl/WsByteBufferPoolManagerImpl.allocateDirect(WsByteBufferPoolManagerImpl.java:527(Compiled Code))
4XESTACKTRACE                at com/ibm/io/async/ResultHandler.runEventProcessingLoop(ResultHandler.java:507(Compiled Code))
4XESTACKTRACE                at com/ibm/io/async/ResultHandler$2.run(ResultHandler.java:905(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/util/ThreadPool$Worker.run(ThreadPool.java:1864(Compiled Code))
3XMTHREADINFO3           Native callstack:
4XENATIVESTACK               (0x00007F61083DD122 [libj9prt26.so+0x13122])
4XENATIVESTACK               (0x00007F61083EA79F [libj9prt26.so+0x2079f])
....

То, что именно полные разветвления имеют значение -XX: + DisableExplicitGC при использовании прямого байтового буфера NIO, пока не совсем ясны (это приводит к утечке памяти?), но, по крайней мере, будь то некоторый риск. Если вы используете сервер приложений, отличный от Websphere, вы можете убедиться, что сам сервер приложений не вызывает System.gc() через NIO перед его отключением. У меня есть связанный с этим вопрос, который, надеюсь, получит некоторое разъяснение о точном влиянии на библиотеки NIO: Влияние установки -XX: + DisableExplicitGC при использовании прямых буферов NIO

Кстати, Websphere также, как представляется, вручную вызывает System.gc() несколько раз во время процесса загрузки, обычно дважды в течение первых двух секунд после запуска сервера приложений, а третий раз в течение первых 1-2 минут (возможно, когда приложение развертывается). В нашем случае именно поэтому мы начали расследование в первую очередь, так как кажется, что все вызовы System.gc() поступают непосредственно с сервера приложений и никогда не из нашего кода приложения.

Следует также отметить, что в дополнение к библиотекам NIO внутренняя реализация JDK распределенной сборки мусора RMI также вызывает System.gc(): Необычные вызовы System.gc() из-за вызова удаленного метода Системные вызовы с помощью основных API

Является ли также неясным, будет ли включение -XX: + DisableExplicitGC также наносить ущерб RMI DGC. Единственная ссылка, которую я смог найти, что даже адреса это первая ссылка выше, которая гласит

"Однако в большинстве случаев регулярной активности GC достаточно для эффективный DGC"

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

Ответ 3

Если вы используете -XX:+DisableExplicitGC и, используйте CMS, вы можете использовать -XX:+CMSClassUnloadingEnabled, чтобы ограничить еще одну причину для полных GC (т.е. PermGen заполнен). Кроме этого, у меня не было проблем с использованием этой опции, хотя я переключился на использование -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses, потому что единственной причиной явных GC был RMI, а не код приложения.