Технология Java, стиль IBM: Часть 1. Методы Утилизации Памяти

Варьирование методов для более гибкого программирования

Одно из больших преимуществ Java™-платформы состоит в том, что она уделяет большое внимание процессу утилизации памяти, но бывают случаи, когда вам самим хочется наладить способ утилизации памяти. В последней версии технологии Java от IBM®, вы можете выбирать между несколькими методами утилизации памяти, чтобы вы могли получить наиболее удобный для вас результат работы приложения. Во второй статье из выпуска технологий Java, стиль IBM, разработчик Java, Матиас Персон рассматривает возможные опции и детально разбирает ситуации, в которых это более всего присуще.

Матиас (Mattias) Персон (Persson), Staff Software Engineer, IBM

Матиас (Mattias) Персон (Persson)Матиас Персон (Mattias Person) работает в команде разработчиков IBM Software в Великобритании, специализируется на производительности платформы Java и масштабировании системы. Он связан с IBM уже четыре года и имеет степень магистра наук по программированию, которую он получил в Университете Ваксио в Швеции. Он является сертифицированным J2EE архитектором и ведущим профессионалом, сертифицированным в Lotus. Можно часто увидеть, как в свободное время он на своем горном велосипеде поднимается и спускается по холмам к северу от здания IBM в г. Херсли.



09.05.2006

Утилизация памяти (GC) в IBM SDK для платформы Java 5.0 можно сконфигурировать с помощью четырех различных методов. Эта статья, первая из двух на тему утилизации памяти, дает представление о различных методах утилизации памяти и рассматривает их общие характеристики. Вам желательно уже иметь базовое понимание процесса утилизации памяти на платформе Java перед тем, как начнете изучение. Часть 2 представляет численные характеристики GC и несколько примеров.

Для чего нужны различные методы GC?

Возможность выбора различных методов GC увеличивает вашу производительность. Существует много различных алгоритмов, доступных для GC, каждый их которых имеет достоинства и недостатки, зависящие от вида и объема работы. (Если вы не знакомы с общей темой алгоритмов GC, см. Ресурсы для дополнительной информации.) В IBM SDK 5.0, вы можете конфигурировать утилизацию памяти одним из четырех методов, каждый из которых действует по своему алгоритму. Стандартный метод подходит к большинству приложений. Если у вас нет соответствующей требованиям производительности приложения, тогда содержание данной статьи (и следующей) могут быть вам неинтересны. Вы можете запускать IBM SDK 5.0 без изменения метода GC. Однако если вашему приложению необходима оптимальная производительность или вам нужно знать длину задержки GC, можете читать далее. Вы увидите, что последняя версия от IBM имеет еще больше возможностей, чем его предшественники.

И так почему же среда выполнения программ Java от IBM не делает выбор за вас автоматически? Это не всегда возможно. Среде выполнения сложно понять ваши нужды. В некоторых ситуациях вам может понадобиться запустить программу с большой производительностью. В других случаях, вам будет предпочтительнее снизить время задержки.

Таблица 1 представляет перечень доступных методов и поясняет, когда нужно использовать каждый из них. Последующие главы описывают характеристики каждого метода более подробно.

Таблица 1. Методы GC в IBM SDK 5.0
МетодВозможностиОписание
Оптимизация производительности-Xgcpolicy:optthruput (на усмотрение пользователя)Стандартный метод. Обычно используется для приложений, когда недоработанная производительность гораздо важнее, чем маленькие задержки GC. Приложение прекращает работать каждый раз, когда завершена утилизация памяти.
Оптимизация времени задержки-Xgcpolicy:optavgpauseОбеспечивает высокую производительность за счет более коротких задержек GC, предоставляя некоторые из результатов GC синхронизировано. Приложение задерживается на более короткие периоды.
Генеративная синхронизация-Xgcpolicy:genconПо-разному управляет кратковременными объектами и объектами, существующими долгое время. С использованием этого метода приложения, в котором есть много кратковременных объектов, задерживаются на меньшие периоды времени и при этом выдают хорошую производительность.
Суб-буферизация-Xgcpolicy:subpoolИспользует тот же алгоритм, что и у стандартного метода, но еще применяет метод распределения, который более подходит для многопроцессорных машин. Мы рекомендуем этот метод для симметричных мультипроцессорных машин с 16-ю и более процессорами. Этот метод возможен только на платформах IBM pSeries® и zSeries®. Этот метод обеспечит хорошее преимущество приложениям, которым нужны масштабные и большие машины.

Определения некоторых терминов

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

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

В этой статье я использую аббревиатуры из опций командной строки, показанных детально в Таблице 1, чтобы показать различия этих методов: optthruput для Оптимизации производительности, optavgpause для оптимизации времени задержки, gencon для генеративной синхронизации и subpool для cуббуферизации.

Когда следует учитывать нестандартный метод GC?

Я рекомендую вам всегда начинать со стандартным методом GC. Перед тем, как вы измените стандартную настройку, вам нужно понять обстоятельства, при которых следует использовать альтернативный метод. Таблица 2 представляет ряд причин, по которым возможно их использование:

Таблица 2. Причины, по которым целесообразней переключаться на альтернативный метод GC
Переключение на методПричины
optavgpause
  • Мое приложение не может позволить такую длину задержек GC. Ухудшение в производительности происходит до тех пор пока не уменьшится время задержки GC.
  • Я работаю на 64-битной платформе и использую очень большую память -- более 3 или 4ГБ.
  • Мое приложение является приложением с графическим интерфейсом и мне сообщается о времени ответа пользователя.
gencon
  • Мое приложение оперирует большим количеством кратковременных объектов.
  • Область памяти фрагментирована.
  • Мое приложение основано на транзакциях (это означает, что объекты, участвующие в транзакции, после ее завершения уничтожаются.)
subpool
  • У меня возникают проблемы с наращиванием системы на большой многопроцессорной машине.

Позвольте подчеркнуть то, что причины, перечисленные в Таблице 2, не достаточны, чтобы сделать вывод о том, что альтернативные методы будут работать лучше. Это всего лишь небольшие подсказки. В любых случаях вам необходимо запускать приложение и измерять продуктивность и/или время ответа в комбинации со временем задержки GC. В следующей части этой темы будут показаны примеры такого рода тестирования.

Оставшиеся части этой статьи описывают более детально различия между методами GC.


optthruput

Признаки фрагментации памяти

Наиболее распространенный признак фрагментации памяти - это наличие найденной преждевременной ошибки. Это видно из результата процесса утилизации памяти (-Xverbose:gc) в то время как GC еще в действии хотя в памяти уже есть свободное место. Другим признаком является локальный кэш потока. (см. подглаву "Затвор памяти и локальный кэш потока"). Вы можете использовать -Xtgc:freelist, чтобы определить среднюю величину. Две эти опции объясняются в Тестовом Справочнике IBM SDK 5 доступном в Ресурсах.

optthruput является стандартным методом. Это коллектор трассировки, относящийся также и к коллектору маркировки, счистки и сжатия (mark-sweep-compact). Фазы маркирования и чистки всегда запускаются во время GC, а сжатие происходит только лишь при определенных условиях. В фазе маркирования происходит обнаружение и маркировка всех действующих объектов. В фазе чистки удаляются все немаркированные объекты. Третье и необязательное действие - это сжатие. Существуют различные условия, при которых может происходить сжатие. Наиболее распространенный случай, когда неспособность системы утилизировать достаточное количество свободного места.

Фрагментация происходит тогда, когда объекты отсоединены друг от друга и расположены так часто, что в памяти остались лишь маленькие кусочки свободного места. Может быть так, что в памяти осталось огромное количество свободного места, но смежные области очень малы, что вызывает местные ошибки. Сжатие перемещает все объекты вместе в начало памяти и выравнивает так, чтобы между ними не было свободного места. Этот процесс удаляет фрагментацию из памяти, но он является ресурсоемкой задачей, поэтому его производят только по необходимости.

Рисунок 1 изображает то, как схематически выглядит память после различных фаз: маркировки, счистки и сжатия. Темные области обозначают объекты, а светлые области - свободное место.

Маркировка и чистка

Маркировка проходит через все объекты, которые могут быть отнесены к скоплению потоков, помехам, interned strings, and JNI сноски. В процессе этого мы создаем метку-вектор, который определяет начало всех действующих объектов mark bit vector.

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

Рисунок 1. Вид памяти перед и после утилизации памяти (GC)
Heap layout before and after garbage collection

Подробности того, как различные фазы GC работают, выходит за рамки данной статьи. Меня больше волнует то, на сколько вы хорошо понимаете свойства среды выполнения. Я рекомендую вам прочитать Тестовый Справочник (см. Ресурсы) для более подробной информации.

Рисунок 2 изображает, как время выполнения распределяется между потоком приложения (или мутатором) и потоками GC. Горизонтальная ось - это оставшееся время, и вертикальная ось содержит потоки, где n показывает число процессоров в машине. В этом изображении необходимо принять во внимание, что приложение использует один поток посредством одного процессора. GC изображена синими прямоугольниками, которые показывают остановленные мутаторы и запущенные потоки GC. Все это потребляет 100 процентов мощности процессора, а потоки мутатора не работают. Этот рисунок изображает довольно общо, но достаточно для того, чтобы сравнить этот метод с другими, рассматриваемыми в этой статье. В действительности, длительность и частота GC варьируется в зависимости от приложения и объема работы.

Рисунок 2. Распределение времени процессора между мутаторами и потоками GC в методе optthruput
Distribution of CPU time between mutators and GC threads in the optthruput policy

Мутатор против потоков GC

Поток мутатора - это прикладная программа, которая размещает объекты. Мутатор также можно назвать приложением. Поток GC существует, как часть процесса организации памяти и выполняет процесс утилизации памяти.

Блокировка динамической памяти и распределение потоков в кэше

Метод optthruput использует смежные области памяти, которые распределяются между всеми потоками. Потоку нужен свой собственный доступ к памяти для резервирования места под новые объекты. Данная блокировка, которую называют блокировкой памяти, гарантирует, что лишь только один поток может разместить объекты в единицу времени. На машинах с множеством процессоров может вызвать проблемы с масштабированием, потому что несколько запросов на размещение объектов могут произойти в один момент времени, когда как каждому потоку нужен свой собственные доступ к блокировке динамической памяти.

Чтобы уменьшить вероятность этой проблемы, каждый поток резервирует небольшой кусок памяти, называемый локальный кэш потока (что также относится к thread local heap - локальная память потока или TLH). Эта область для данных индивидуальна для каждого потока, поэтому во время размещения объектов блокировка динамической памяти не используется. Когда локальный кэш заполнен, поток возвращается к памяти и запрашивает еще один, используя блокировку динамической памяти.

Фрагментация памяти может мешать потоку, получить большие TLH, поэтому один TLH заполняется очень быстро, заставляя поток приложения быстро обратиться к памяти за еще одним локальным кэшем. В данной ситуации я блокировка динамической памяти становиться большой помехой. В такой ситуации хорошей альтернативой могут стать методы gencon или subpool.


optavgpause

Для многих приложений производительность не так важна как быстрое время ответа. Необходимо учитывать, что приложению требуется не больше 100 миллисекунд, чтобы завершить обработку рабочих элементов. С задержками GC в диапазоне 100 миллисекунд, вы получаете элементы, которые не возможно обработать в эти временные рамки. Проблема с утилизацией памяти состоит в том, что время задержек увеличивается до максимального времени, которое требуется для обработки одного элемента. Большие размеры памяти (доступных на 64-битных платформах) увеличивают этот эффект, так как больше объектов находятся в процессе обработки.

О выпуске

Выпуск Технология Java, стиль IBM охватывает последние версии платформы Java, разработанной IBM. вы узнаете о том, как IBM реализовала новые возможности, входящие в состав версии 5.0 Java-платформы. А также вы узнаете о том, как использовать некоторые ценные дополнения, реализованные в новых выпусках от IBM.

Вы можете связаться непосредственно с авторами, прислав им свои комментарии или вопросы по поводу статей. Написать комментарий на весь выпуск вы можете связаться с ведущим выпуска Крисом Бэйли. Более подробно на темы, рассматриваемые в этом выпуске, а также скачать последние релизы от IBM, см. в разделе Ресурсы.

optavgpause является альтернативным методом GC, созданным для того, чтобы сохранять задержки в минимальном состоянии. Он не гарантирует определенного размера временную задержку, но задержки становятся короче, чем те, которые производятся стандартным методом GC. Суть этого метода в том, что некоторая часть процесса утилизации памяти происходит синхронизировано с работой приложения. Это происходит в двух местах:

  • Синхронизированная маркировка и счистка: Перед тем, как память будет заполнена, каждый мутатор помогает маркировать объекты (синхро-маркировка). Тем не менее, задержка работы GC имеет место, но она значительно короче. После GC потоки мутатора help out и производят чистку объектов (синхро-счистка).
  • Фоновый поток GC: Один (или более) замыкающих фоновых потоков GC производят маркирование, когда приложение уже не работает.

В зависимости от приложения производительность падает на 5 - 10 процентов по сравнению со стандартным методом GC.

Рисунок 3 изображает то, как время выполнения может быть распределено между потоками GC и потоками мутатора, используя optavgpause. Фоновый поток трассировки не показан, потому что он не должен влиять на производительность приложения.

Рисунок 3. Распределение времени процессора между мутаторами и потоками GC в методе optavgpause
Distribution of CPU time between mutators and GC threads in the optavgpause policy

Под серыми областями в рисунке подразумевается, что включена синхронизированная трассировка и что каждому потоку мутатора приходится снижать время обработки. За каждой такой синхронизированной фазой следует полная утилизация памяти, которая завершает маркирование и чистку, которые не происходили во время синхронизированной фазы. Задержка, которая возникает из-за этого, должна быть намного меньше нормальной GC, которую мы видели в optthruput, как и отмечено на Рисунке 3 меньшим прямоугольником на временной шкале. Промежуток между концом GC и началом синхронизированной фазы варьируется, но во время этой фазы это незначительно влияет на производительность.


gencon

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

При генеративной GC объекты, которые должны существовать большой промежуток времени, обрабатываются иначе по сравнению с кратковременными объектами. Память делится на области: инкубатор (nursery space) и хранилище (tenured space) как показано на Рисунке 4. В инкубаторе объекты создаются и, если они живут достаточно долго, их переводят в хранилище. Объекты переводятся после того как они выжили определенное количество утилизаций памяти. Суть в том, что большинство объектов являются кратковременными. Часто производя утилизацию инкубатора, эти объекты освобождаются, и нет необходимости утилизировать всю память целиком. Утилизация хранилища происходит намного реже.

Рисунок 4. Новые и старые области в методе GC gencon
New and old area in gencon garbage collection

Как вы видите из Рисунка 4, инкубатор в свою очередь разбит на две области: размещенных и уцелевших. Объекты, которые должны быть распределены, располагаются в область размещенных (Allocate Space), а когда он заполняется, действующие объекты копируются в область уцелевших (Survivor Space) или хранилище, в зависимости от их времени действия. Затем в инкубаторе происходит переключение областей из области размещенных в область уцелевших и наоборот. Если какая-либо область заполняется недействующими объектами, ее просто перезаписывают новыми распределенными объектами. Сборка инкубатора называется очисткой (scavenge). Рисунок 5 изображает то, что происходит во время этого процесса:

Рисунок 5. Пример того, как выглядит память до и после GC
Example of heap layout before and after GC

Когда область размещенных заполнена, запускается процесс утилизации памяти. Происходит трассировка и копирование действующих объектов в область уцелевших. Если большая часть объектов недействующие, этот процесс совершенно не занимает ресурсы процессора. Более того, объекты достигшие состояния, когда происходит копирование, отсылаются в хранилище. Того говорят, что объект сохранен.

Исходя из названия метода gencon оно подразумевает Generational concurrent (генеративная синхронизация). Хранилище синхронизировано маркировано, с тем же подходом, что и в методе optavgpause, за исключением синхронизированной счистки. Во время фазы синхронизирова все распределения немного снижают производительность. Таким образом, время задержки остается маленькой из-за процесса сборки хранилища.

Рисунок 6 изображает, как распределяется время выполнения, когда происходит процесс GC метода gencon:

Рисунок 6. Распределение времени процессора между мутаторами и процессами GC в gencon
Distribution of CPU time between mutators and GC threads in gencon

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


Подпул

Метод subpool может быть полезен для увеличения производительности в многопроцессорных системах. Как я уже отмечал ранее, этот метод доступен только на машинах IBM pSeries и zSeries. Вид схемы динамической памяти такой же, как и у метода optthruput, но есть различие в структуре списка свободной памяти. Вместо одного списка свободной памяти для всей динамической памяти, теперь их, подпулов, несколько. Каждых пул имеет свой объем памяти, по которым происходит их упорядочивание. Распределение запросов на определенный размер осуществляется с помощью обращения к пулу нужного размера. Элементарные (в зависимости от платформы) высокопроизводительные команды используются, чтобы извлекать ввод списка свободной памяти из списка памяти, избегая преобразования доступа. Рисунок 7 изображает то, как кусочки записи упорядочены по размеру:

Рисунок 7. Свободные куски подпулов, упорядоченные по размеру
Subpool free chunks ordered by size

Когда запускаются Виртуальные Машины или когда произошло сжатие, подпулы не используются, потому что есть большие области свободной динамической памяти. В таких случаях, каждый процессор получает свою собственную мини-память для обработки запросов. Когда происходит первая утилизация памяти, фаза счистки (sweep phase) начинает производить подпулы, и последующие распределения в основном пользуются подпулами.

Метод subpool может сократить время, затрачиваемое на распределение объектов. Элементарные команды гарантируют то, что распределение происходит без запроса глобальной блокировки динамической памяти. Мини-память размещается в процессоре, что увеличивает производительность, потому что снижается вероятность вмешательства кэша. Эта имеет прямое влияние на расширяемость, особенно для многопроцессорных систем. На платформах, где метод subpool недоступен, то генеративная GC может предоставить те же преимущества.


Заключение

Эта статья осветила доступные вашему выбору различные методы GC в версии IBM SDK 5.0 и некоторые из их характеристик. Стандартный метод подходит для большинства приложений. Однако, в некоторых случаях, другие методы действуют лучше. Я описал несколько общих сценариев, в которых вам нужно принимать во внимание, когда именно переключаться на optavgpause, gencon или subpool. Измерение производительности приложений при оценке методов очень важно. Часть 2 продемонстрирует вам этот процесс оценки более подробно.

Ресурсы

Научиться

Получить продукты и технологии

  • Пакет разработки IBM Java 5.0 для Eclipse: для использования его в популярной свободной интегрированной среде разработки (open source IDE).
  • IBM Java SDK: Скачайте различные SDK для операционных систем AIX, Linux, и z/OS и другие предлагаемые IBM SDK для Java-технологии с этой страницы.

Обсудить

  • Среды выполнения и SDK от IBM: Посетите форум, открытый ведущим выпуска Крисом Бэйли, если хотите задать вопросы, связанные с комплектом средств разработки IBM для Java-платформы.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=165704
ArticleTitle=Технология Java, стиль IBM: Часть 1. Методы Утилизации Памяти
publish-date=05092006