Java очень большие размеры кучи

Есть ли у кого-нибудь опыт использования очень больших куч, от 12 ГБ и выше на Java?

  • ГХ делает программу непригодной для использования?
  • Какие параметры GC вы используете?
  • Какая JVM, Sun или BEA подойдет для этого лучше?
  • Какая платформа, Linux или Windows, лучше работает в таких условиях?
  • В случае Windows есть ли разница в производительности между 64-битной Vista и XP при таких высоких нагрузках на память?
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
76
0
61 089
14

Ответы 14

У нас есть приложение, на которое мы выделяем 12–16 Гб, но на самом деле оно достигает 8–10 при нормальной работе. Мы используем Sun JVM (попробовали IBM, и это было немного провалом, но это могло быть просто невежеством с нашей стороны ... У меня есть друзья, которые клянутся этим - они работают в IBM). Пока вы даете своему приложению передышку, JVM может обрабатывать большие размеры кучи с небольшим объемом сборки мусора. Ключевым моментом является наличие большого количества дополнительной памяти. Linux почти всегда более стабилен, чем Windows, а когда он нестабилен, понять причину намного проще. Solaris тоже скала, и вы тоже получаете DTrace :) С такой нагрузкой, зачем вам использовать Vista или XP? Вы просто напрашиваетесь на неприятности. Мы не делаем ничего особенного с параметрами GC. Мы устанавливаем минимальное выделение равным максимальному, чтобы он не пытался постоянно изменять размер, но это все.

Я бы не сказал, что Linux был более стабильным, чем Windows, однако вполне возможно, что Sun test это JVM больше на unit и linex, чем на windows.

Ian Ringrose 02.03.2010 17:55

Я также рекомендую подумать о том, чтобы сделать дамп кучи и посмотреть, где можно улучшить использование памяти в вашем приложении, и проанализировать дамп в чем-то вроде Коврик Затмения. На странице MAT есть несколько статей о том, как начать поиск утечек памяти. Вы можете использовать jmap для получения дампа с чем-то вроде ...

jmap -heap:format=b pid

... и как это отвечает на актуальный вопрос?

ddimitrov 18.10.2008 07:12

потому что с таким большим размером кучи вы должны стремиться уменьшить объем памяти, а также оптимизировать JVM

jlintz 18.10.2008 22:31

Соглашаться. Если у вас нет специального приложения, вам не понадобится 12 ГБ кучи. Обычно это указывает на плохие методы кодирования, например загрузка больших вещей в оперативную память сразу, которые вы должны вместо этого транслировать. Сделайте это правильно, и ваше приложение тоже хорошо масштабируется. Сделайте это неправильно, и вам придется продолжать увеличивать размер кучи, поскольку ваше приложение становится более загруженным / обрабатывает большие объемы данных.

Frans 19.11.2019 09:26

Максимальный объем памяти, который может адресовать XP, составляет 4 гигабайта (здесь). Так что вы можете не захотеть использовать для этого XP (используйте 64-битную ОС).

Или используйте 64-битную версию XP. ;)

Tyler Millican 19.10.2008 00:46

Это не ограничение XP, это ограничение любой 32-битной ОС, которая не использует PAE.

TM. 19.10.2008 06:14

Это ограничение всех 32-битных ОС, даже тех, которые используют PAE.

James 20.01.2010 22:57

@james, Если вы используете PAE, вы увидите все 4 ГБ, если у вас нет PAE, вы не увидите устройства, которые сопоставлены с памятью (видеокарты и т. д.).

Milhous 21.01.2010 08:04

Если вы переключитесь на 64-битную версию, вы будете использовать больше памяти. Указатели становятся 8 байтами вместо 4. Если вы создаете много объектов, это может быть заметно, поскольку каждый объект является ссылкой (указателем).

Недавно я без проблем выделил 15 ГБ памяти на Java с помощью Sun 1.6 JVM. Хотя все это выделяется только один раз. По сравнению с начальным объемом памяти выделяется или освобождается не намного больше. Это было в Linux, но я полагаю, что Sun JVM будет работать так же хорошо в 64-битной Windows.

Sun уже некоторое время использует 64-битную jvm для itanium, хотя itanium не является популярным местом назначения. 64-битные JVM solaris и linux должны быть такими, какими вы должны быть после. Некоторые вопросы

1) стабильно ли ваше приложение?
2) вы уже тестировали приложение на 32-битной JVM?
3) можно ли запускать несколько JVM на одном компьютере?

Я ожидал, что 64-разрядная ОС Windows станет стабильной примерно через год, но до тех пор лучше выбрать Solaris / linux.

Вам может помочь статья Sun о Java 6: https://www.oracle.com/java/technologies/javase/troubleshooting-javase.html

12Gb не должно быть проблемой с достойной реализацией JVM, такой как Sun Hotspot. Я бы посоветовал вам использовать коллектор Concurrent Mark and Sweep (-XX: + UseConcMarkSweepGC) при использовании SUN VM. В противном случае вы можете столкнуться с длительными фазами «остановки мира», когда все потоки останавливаются во время GC.

ОС не должна иметь большого значения для производительности сборщика мусора.

Конечно, вам понадобится 64-битная ОС и машина с достаточным объемом физической памяти.

вот статья о gc ОТ одного из чемпионов Java - http://kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm

Кирк, автор пишет "Отправьте мне журналы сборки мусора

В настоящее время я заинтересован в изучении журналов сборки мусора, созданных Sun JVM. Поскольку эти журналы не содержат информации, имеющей отношение к бизнесу, это должно облегчить опасения по поводу защиты конфиденциальной информации. Все, что я прошу, чтобы в журнале вы указали ОС, полную информацию о версии для JRE и любые параметры командной строки, связанные с heap / gc, которые вы установили. Я также хотел бы знать, используете ли вы Grails / Groovey, JRuby, Scala или что-то еще, кроме Java или параллельно с ним. Лучшая настройка - -Xloggc :. Имейте в виду, что этот журнал не обновляется, когда он достигает предельного размера вашей ОС. Если я найду что-нибудь интересное, я буду рад дать вам взамен очень краткий синопсис. "

Пожалуйста, обновите ссылку на kirk.blog-city.com/is_your_concurrent_collector_failing_you.‌ htm

Claes Mogren 19.10.2010 12:49

Вам следует попробовать запустить visualgc в своем приложении. Это инструмент визуализации кучи, который входит в состав jvmstat, загружаемого по адресу http://java.sun.com/performance/jvmstat/.

Это намного проще, чем читать журналы сборки мусора.

Это быстро поможет вам понять, как работают части (поколения) кучи. Хотя общая куча может составлять 10 ГБ, различные части кучи будут намного меньше. Сборщики мусора в куче Eden относительно дешевы, в то время как полные сборщики мусора в старом поколении стоят дорого. Хорошей стратегией является определение размера вашей кучи так, чтобы Эдем был большим и старое поколение почти не касалось. Это может привести к очень большой общей куче, но какого черта, если JVM никогда не касается страницы, это просто виртуальная страница, и ей не нужно занимать оперативную память.

Пару лет назад я сравнил JRockit и Sun JVM для кучи 12G. Победил JRockit, а поддержка огромных страниц в Linux сделала наш тестовый запуск на 20% быстрее. YMMV, поскольку наш тест был очень интенсивным для процессора / памяти и был в основном однопоточным.

Какая это была версия Java, и успеете ли вы сделать это сегодня снова? Цифры были бы очень интересными.

Thorbjørn Ravn Andersen 04.12.2009 00:53

Я больше не консультирую ту же компанию, поэтому у меня даже нет среды, чтобы попробовать это. Это был JDK1.5 JRockit, IIRC.

ShabbyDoo 04.12.2009 19:26

Я использовал размер кучи более 60 ГБ в двух разных приложениях под Linux и Solaris соответственно, используя 64-битные версии (очевидно) Sun 1.6 JVM.

Я никогда не сталкивался с проблемами сборки мусора с приложением на базе Linux, за исключением случаев, когда приближался к пределу размера кучи. Чтобы избежать проблем, связанных с этим сценарием (слишком много времени тратится на сборку мусора), я просто оптимизировал использование памяти во всей программе, так что пиковое использование было примерно на 5-10% ниже предельного размера кучи в 64 ГБ.

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

  1. Включение / принудительное использование параллельного сборщика мусора с помощью параметров JVM -XX: + UseParallelGC -XX: + UseParallelOldGC, а также управление количеством используемых потоков GC с помощью параметра -XX: ParallelGCThreads. См. «Настройка сборки мусора виртуальной машины Java SE 6 HotSpot» для более подробной информации.

  2. Обширная и, казалось бы, нелепая установка для локальных переменных значения "null" после того, как они больше не нужны. Большинство из них были переменными, которые должны были иметь право на сборку мусора после выхода за пределы области видимости, и они не были ситуациями утечки памяти, поскольку ссылки не копировались. Однако эта «ручная» стратегия помощи сборке мусора по какой-то причине была необъяснимо необходима для этого приложения на рассматриваемой платформе Solaris.

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

Три вышеупомянутых шага сделали возможным сохранить это приложение изолированным и продуктивным при использовании кучи около 60 ГБ вместо того, чтобы бесконтрольно расти до предельного размера кучи 128 ГБ, который был установлен. В частности, очень полезен параллельный сборщик мусора, поскольку основные циклы сборки мусора обходятся дорого при большом количестве объектов, то есть время, необходимое для основной сборки мусора, зависит от количества объектов в куче.

Я не могу комментировать другие проблемы, связанные с платформой, в этом масштабе, а также не использовал JVM сторонних производителей (Oracle).

Если ваше приложение не интерактивно и паузы сборщика мусора для вас не проблема, у 64-битной Java не должно возникнуть проблем с обработкой очень больших куч, даже в сотни ГБ. Мы также не заметили никаких проблем со стабильностью ни в Windows, ни в Linux.

Однако, когда вам нужно держать паузы GC на низком уровне, все становится действительно неприятно:

  1. Забудьте о пропускной способности по умолчанию, остановите сборщик мусора. Это приостановит ваше приложение на несколько десятков секунд для умеренных куч (<~ 30 ГБ) и на несколько минут для больших (> ~ 30 ГБ). И покупка более быстрых модулей DIMM не поможет.

  2. Лучшим вариантом, вероятно, является сборщик CMS, включенный -XX: + UseConcMarkSweepGC. Сборщик мусора CMS останавливает приложение только на начальном этапе маркировки и этапах маркировки. Для очень маленьких куч, таких как <4 ГБ, это обычно не проблема, но для приложения, которое создает много мусора и большую кучу, фаза замечаний может занять довольно много времени - обычно намного меньше, чем полная остановка мира. , но все же может быть проблемой для очень больших куч.

  3. Когда сборщик мусора CMS не работает достаточно быстро, чтобы завершить работу до того, как постоянное поколение заполнится, он возвращается к стандартному сборщику мусора Stop the World. Ожидайте ~ 30 или более секундных пауз для куч размером 16 ГБ. Вы можете попытаться избежать этого, сохранив как можно более низкий уровень образования долгоживущего мусора в вашем приложении. Обратите внимание: чем больше ядер, на которых работает ваше приложение, тем больше проблема, потому что CMS использует только одно ядро. Очевидно, будьте осторожны, есть гарантия нет, что CMS не вернется к сборщику STW. И когда это происходит, обычно это происходит при пиковых нагрузках, и ваше приложение умирает на несколько секунд. Вероятно, вы не захотите подписывать SLA для такой конфигурации.

  4. Ну вот и новая штука G1. Теоретически он разработан, чтобы избежать проблем с CMS, но мы попробовали его и заметили, что:

    • Его пропускная способность хуже, чем у CMS.
    • Теоретически он должен избегать в первую очередь сбора популярных блоков памяти, однако вскоре он достигает состояния, когда почти все блоки являются «популярными», а предположения, на которых он основан, просто перестают работать.
    • Наконец, для G1 все еще существует запасной вариант «останови мир»; спросите Oracle, когда этот код должен быть запущен. Если они говорят «никогда», спросите их, почему там код. Так что IMHO G1 действительно не устраняет огромную проблему кучи Java, он только делает ее (возможно) немного меньше.
  5. Если у вас есть деньги на большой сервер с большой памятью, у вас, вероятно, также есть деньги на хорошее коммерческое оборудование с аппаратным ускорением и технологию GC без пауз, например, предлагаемую Azul. У нас есть один из их серверов с 384 ГБ ОЗУ, и он действительно отлично работает - без пауз, нулевых строк кода остановки мира в GC.

  6. Напишите чертову часть вашего приложения, которая требует много памяти на C++, как это сделал LinkedIn с обработкой социальных графиков. Вы по-прежнему не избежите всех проблем, сделав это (например, фрагментация кучи), но было бы определенно легче поддерживать низкие паузы.

5. Вряд ли. Машина 192 МБ стоит около 15 тыс. Евро. Цены на Azul - это предприятие, не так ли?

Stephan Eggermont 23.08.2011 11:12

Это, пожалуй, лучшее резюме здесь. Я бы добавил две вещи: (1) CMSInitiatingOccupancyFraction может смягчить проблему «CMS не может закончить, пока старый генератор не заполнится», но (2) в отличие от сборщика пропускной способности, CMS не сжимает кучу, поэтому фрагментация обычно вызывает STW GC в конце концов.

jbellis 29.09.2011 01:52

@StephanEggermont, вы имели в виду машину 192 ГБ, верно?

om-nom-nom 07.11.2013 13:30

@ om-nom-nom да, верно. К сожалению, не могу редактировать комментарии днем ​​позже

Stephan Eggermont 08.11.2013 03:05

Я генеральный директор Azul Systems, поэтому я, очевидно, предвзято отношусь к этой теме! :) Что, как говорится...

Технический директор Azul, Гил Тене, дает хороший обзор проблем, связанных со сборкой мусора, и обзор различных решений в своей презентации Общие сведения о сборке мусора Java и что вы можете с этим сделать, а в этой статье есть дополнительная информация: http://www.infoq.com/articles/azul_gc_in_detail.

Сборщик мусора C4 от Azul в нашей JVM Zing работает одновременно и параллельно, и использует один и тот же механизм сборки мусора как для нового, так и для старого поколения, работая одновременно и уплотняясь в обоих случаях. Самое главное, что у C4 нет возможности остановить мир. Все уплотнения выполняются одновременно с работающим приложением. У нас есть клиенты, использующие очень большие (сотни гигабайт) с временем паузы GC в худшем случае <10 мсек, а в зависимости от приложения часто меньше 1-2 мсек.

Проблема с CMS и G1 заключается в том, что в какой-то момент память кучи Java должна быть уплотнена, и оба этих сборщика мусора останавливают мир / STW (то есть приостанавливают приложение) для выполнения сжатия. Таким образом, хотя CMS и G1 могут выдвигать паузы STW, они не устраняют их. Однако Azul C4 полностью исключает паузы STW, и именно поэтому Zing имеет такие низкие паузы GC даже для гигантских размеров кучи.

После 6 электронных писем с одним из ваших менеджеров по продажам я отказался от получения информации о ценах. Решение, которое вы даже не можете оценить, не является решением.

Chad Wilson 09.01.2014 20:14

Как упоминалось выше, если у вас неинтерактивная программа, сборщик мусора (GC) по умолчанию должен работать нормально. Если у вас есть интерактивная программа, и вы (1) не выделяете память быстрее, чем GC может поддерживать, и (2) не создавайте временные объекты (или коллекции объектов), которые слишком велики (относительно общего максимальная память JVM) для работы GC, тогда CMS для вас.

У вас возникнут проблемы, если у вас есть интерактивная программа, в которой ГХ не хватает места для передышки. Это верно независимо от того, сколько у вас памяти, но чем больше у вас памяти, тем хуже становится. Это связано с тем, что, когда у вас становится слишком мало памяти, CMS не хватает памяти, тогда как сборщики мусора (включая G1) приостанавливают все, пока вся память не будет проверена на наличие мусора. Эта пауза «останови мир» становится тем больше, чем больше у тебя памяти. Поверьте, вы не хотите, чтобы ваши сервлеты останавливались более чем на минуту. Я написал подробный ответ StackOverflow об этих паузах в G1.

С тех пор моя компания перешла на Azul Zing. Он по-прежнему не справляется со случаем, когда вашему приложению действительно требуется больше памяти, чем у вас есть, но до этого момента оно работает как мечта.

Но, конечно, Zing не является бесплатным, и его специальный соус запатентован. Если у вас гораздо больше времени, чем денег, попробуйте переписать приложение, чтобы использовать кластер JVM.

В ближайшем будущем Oracle работает над высокопроизводительный сборщик мусора для многогигабайтных куч.. Однако на сегодняшний день это не вариант.

Другие вопросы по теме