Секреты сборки мусора в java [dump-it 2012]

Post on 24-May-2015

4.221 Views

Category:

Documents

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

Слайды с презентации на dump-it.ru (2012)

TRANSCRIPT

Секреты сборки мусора в Java

Алексей Рагозин alexey.ragozin@gmail.com

О чём этот доклад?

• Обзор проблемы автоматического управления памятью

• Stop-the-world паузы – причины

• Сборка мусора в современных JVM

Сборка мусора

Языки использующие автоматическое управление памятью

Java, JavaScript, Erlang, Haskell, Python, PHP, C#, Ruby, Perl, SmallTalk, OCaml, List, Scala, ML, Go, D, …

… and counting

Языки не использующие автоматическое управление памятью

C, C++, Pascal/Delphi, Objective-C

Что я забыл?

Способы сборки мусора

Мусор – структура данных (объект) в памяти не достижимый из программного кода.

Подсчёт ссылок

Транзитивное замыкание ссылок

Вообще не собирать

Подсчёт ссылок

+ Просто

+ Не требует пауз для сбора мусора

– Не очищает циклические графы

– Дополнительные 15-30% нагрузки CPU

– Плохо сочетается с много поточностью

Транзитивное замыкание ссылок

• Корневой набор ссылок Статические переменные

Локальные переменные

• Объекты достижимые из корневых ссылок – живые

• Объекты недостижимые из корневых ссылок – мусор

В общем случае, граф объектов не должен меняться по мере обхода. Следовательно, прикладные потоки должны быть остановлены пока идёт сборка мусора.

Алгоритмы сборки мусора

• Mark-Sweep Фаза 1 – маркировка достижимых объектов

Фаза 2 – “вычистка” мусора

• Copy collector (сборка копированием) Использует две области памяти, но выполняется в один проход

• Mark-Sweep-Compact Mark-Sweep + перемещение живых объектов

Трёх цветная маркировка

roo

ts

Трёх цветная маркировка

roo

tsro

ots

Трёх цветная маркировка

roo

tsro

ots

Трёх цветная маркировка

roo

tsro

ots

Сборка копированием

FROM

TO

roo

ts

Сборка копированием

FROM

TO

roo

ts

FROM

TO

roo

ts

Сборка копированием

FROM

TO

roo

ts

FROM

TO

roo

ts

1

Сборка копированием

FROM

TO

roo

ts

FROM

TO

roo

ts

1 2

Сборка копированием

FROM

TO

roo

ts

FROM

TO

roo

ts

1 2

Сборка копированием

FROM

TO

roo

ts

FROM

TO

roo

ts

1 23

Экономика сборки мусора

S – объём кучи

L – объём живых объектов

Copy collection

Эффективность

Mark-Sweep

Эффективность

L

LSc

S

LSc

L

LSc

21

Объём мусора в куче

Слабая гипотеза о поколениях

Постулаты Большинство объектов умирают молодыми Число ссылок на молодые объекты мало

Следствие Если хранить молодые объекты отдельно от старых, можно обеспечить высокую пропускную способность (молодое поколение) и эффективное использование памяти (старое поколение).

Демография объектов в куче

См

ер

тно

сть

ай

т/с)

Возраст объектов

Период молодой сборки

Период старой сборки

Generational collection

Молодое поколение

Сборщик настроен на пропускную способность

Старое поколение

Сборщик настроен на эффективное использование памяти

Продвижение (promotion) объектов в старое поколение

Сборщик молодого поколения копирует живые объекты в старое поколение после достижения “зрелого” возраста

Generational collection

Как получить все указатели из старого поколения на молодое?

Ответ – барьер на запись

Каждый раз при записи указателя в память в “старом” пространстве, срабатывает барьер

Молодая сборка HotSpot JVM

Eden S1 S2 Tenured

Dirty cards

Collect roots for young GC

Scan stack tracesScan dirty pages in old space

Сбор “корневых” ссылок

Молодая сборка HotSpot JVM

Eden S1 S2 Tenured

Dirty cards

Collect roots for young GC

Clean cardsRecursive copy of live objects (only live objects are traversed)

Копирование живых объектов

Молодая сборка HotSpot JVM

Eden S1 S2 Tenured

Dirty cards

Сборка закончена

Области памяти, не помеченные в таблице карт, не могут содержать ссылки на молодое поколение

Stop-the-world паузы

• Изменение графа объектов во время обхода может привести к пропуску достижимых объектов

• Большинство managed runtimes может перемещать объекты только в режиме паузы

Stop-the-world паузы

Параллельные (parallel) алгоритмы Используют несколько потоков чтобы сократить время пауз

Фоновые (concurrent) алгоритмы Выполняют большую часть работы в фоновом режиме (без STW пауз)

Инкрементальные алгоритмы Много маленьких STW вместо одной длительной

Фоновая маркировка

Проблема Граф объектов меняется по мере обхода * * Даже в функциональных языках могут выполняться отложенные вычисления, меняющие граф

Решение барьер на запись – отслеживать ссылки изменившиеся за время обхода

Фоновая маркировка

Card marking write barrier

HotSpot CMS, JRockit, IBM J9

Snapshot-at-the-beginning (SATB) write barrier

HotSpot G1

Альтернатива барьеру на запись – барьер на чтение

Azul Zing JVM

SATB барьер записи (G1)

A B C D

GC A

C

SATB барьер записи (G1)

A B C D

GC C

D

SATB барьер записи (G1)

A B C D

GC C

D

Reference queue: B DОчередь ссылок:

SATB барьер записи (G1)

A B C D

GC C

D

SATB барьер записи (G1)

A B C D

GC D

D

SATB барьер записи (G1)

A B C D

GC

Reference queue: B DОчередь ссылок:

SATB барьер записи (G1)

A B C D

GC

Reference queue:

B

D

emptyОчередь ссылок: пусто

“Card marking” барьер записи

[пауза] Сбор корневых ссылок

[фон] Обход графа объектов

[фон] Перемаркирова “грязных” страниц

[паузa] Финальная перемаркирова

Перемещение объектов

Большинство JVM не может перемещать объекты без STW паузы.

Цель – уменьшение длительности пауз

Параллельная обработка (задействовать все ядра)

Инкрементальное уплотнение (чаще, но короче)

Не уплотнять – опасность фрагментации

Oracle HotSpot

Однопоточный сборщик мусора

-XX:+UseSerialGC

Молодое поколение:

• Сборка копированием

Старое поколение:

• Mark Sweep Compact

Возвращает неиспользуемую память ОС после сборки старшего поколения

http://aragozin.blogspot.com/2011/09/hotspot-jvm-garbage-collection-options.html

Oracle HotSpot

Параллельный сборщик мусора

-XX:+UseParallelGC –XX:+UseParallelOldGC

Молодое поколение:

• Многопоточная сборка копированием

Старое поколение:

• Многопоточный Mark Sweep Compact

http://aragozin.blogspot.com/2011/09/hotspot-jvm-garbage-collection-options.html

Oracle HotSpot

Фоновый сборщик мусора

-XX:+UseConcMarkSweepGC

Молодое поколение:

• Одно или многопоточная сборка копированием

Старое поколение:

• Фоновая Mark Sweep сборка

Не перемещает объекты в старом поколении при сборке в фоновом режиме

http://aragozin.blogspot.com/2011/09/hotspot-jvm-garbage-collection-options.html

Oracle HotSpot

Фоновый сборщик мусора

-XX:+UseG1GC

Молодое поколение:

• Многопоточная сборка копированием

Старое поколение:

• Инкрементальная многопоточная сборка копированием

Возвращает не используемую память ОС

http://aragozin.blogspot.com/2011/09/hotspot-jvm-garbage-collection-options.html

Oracle’s HotSpot JVM

Young collector Old collector JVM option

Serial (DefNew) Serial Mark-Sweep-Compact -XX:+UseSerialGC

Parallel scavenge (PSYoungGen) Serial Mark-Sweep-Compact (PSOldGen) -XX:+UseParallelGC

Parallel scavenge (PSYoungGen) Parallel Mark-Sweep-Compact (ParOldGen) -XX:+UseParallelOldGC

Serial (DefNew) Concurrent Mark Sweep -XX:+UseConcMarkSweepGC

-XX:-UseParNewGC

Parallel (ParNew) Concurrent Mark Sweep -XX:+UseConcMarkSweepGC

-XX:+UseParNewGC

G1 -XX:+UseG1GC

http://blog.ragozin.info/2011/09/hotspot-jvm-garbage-collection-options.html

Oracle JRockit

-Xgc: option Generational Mark Sweep/Compact

genconcon or gencon Yes concurrent incremental

singleconcon or singlecon No concurrent incremental

genconpar Yes concurrent parallel

singleconpar No concurrent parallel

genparpar or genpar Yes parallel parallel

singleparpar or singlepar No parallel parallel

genparcon Yes parallel incremental

singleparcon No parallel incremental

http://blog.ragozin.info/2011/07/jrockit-gc-in-action.html

IBM J9

-Xgcpolicy:optthruput

Одно поколение, stop-the-world сборщик

-Xgcpolicy:optavgpause

Одно поколение, частично конкурентный сборщик

-Xgcpolicy:gencon

Два поколения, частично конкурентный сборщик

Azul Zing

• Два поколения

• Молодое поколение – конкурентный mark-sweep-compact (MSC)

• Старое поколение – конкурентный mark-sweep-compact (MSC)

Azul Zing выполняет перемещение объектов (уплотнение памяти) без останова приложения. Ни одна из фаз сборки мусора не требует STW паузы.

Секрет – read barrier (барьер чтения).

Масштабируемость JVM

Может ли JVM работать с большим объёмом памяти (16GiB и более) без “фризов”?

Ответ да, если приложение удовлетворяет постулатам гипотезы о поколениях.

Рецепт работы без пауз

• HotSpot JVM

• CMS (Concurrent Mark Sweep) сборщик мусора

• Тюнинг

Результат

• Паузы не более 150ms на 32GiB кучи

HotSpot CMS сборщик

Сборка молодого поколения копированием

Не перемещает объекты в старом поколении

Статистические методы борьбы с фрагментацией

Две дополнительные STW фазы

initial-mark, remark

Вся остальная работа происходит в фоне

Длительность пауз CMS сборщика

Young collection

Scan thread stacks

Scan dirty cards

Read card table

Scan dirty

pages

Copy live

objects

Initial mark

Scan thread stacks

Scan young space

Remark

Scan thread stacks

Scan young space

Scan dirty cards

Read card table

Scan dirty

pages

CMS и фрагментация памяти

CMS не перемещает объекты в старшем поколении.

CMS использует отдельные списки свободного места (FSL) для каждого размера выделяемого блока.

Профилактика фрагментации:

• увеличение размера кучи

• более частые циклы сборки

• HotSpot JVM версии 6u26 и старше

Советы по настройке CMS

Настройка CMS на большом объёме кучи • -XX:MaxNewSize= ? – размер молодого поколения

• -XX:CMSWaitDuration= ?

• -XX:-CMSConcurrentMTEnabled – защита от бага в JVM

• -XX:+UseCMSInitiatingOccupancyOnly

• -XX:+CMSClassUnloadingEnabled – если действительно нужно

• -XX:ParGCCardsPerStrideChunk= ? – если куча больше 16 GiB

• JVM 1.6u26 или более поздняя

• плюс логирование GC

Другие причины пауз

• Свопинг ОС

• Обработка ссылок (weak, soft, phantom, JNI)

• Объекты требующие “финализации”

• JNI, native код может блокировать GC

• Проблемы с permanent generation

HotSpot G1

G1 (Garbage First) – новый алгоритм в последних версия HotSpot JVM

Решит ли он проблему пауз?

Можно лучше – OpenJDK патч

http://blog.ragozin.info/2011/07/openjdk-patch-cutting-down-gc-pause.html

RFE-7068625

ИТОГ: Сборка мусора в JVM

Сборка мусора не чёрная магия

Каждое приложение индивидуально

Приложение не должно мешать сборщику мусора

JVM может работать “почти” без пауз (с паузами не более 100-200ms)

Автоматическое управление памятью не универсально (Проблемные приложения: HBase, Cassandra, …)

Альтернативы

java.nio.ByteBuffer.allocateDirect()

Достоиства • Память выделяется вне кучи

• Память освобождается автоматически (через ByteBuffer объект)

• Кроссплатформенность, “чистая Java”

Недостатки • Фрагментация памяти вне кучи

• Память освобождается автоматически (через ByteBuffer объект)

• Усложняет многопоточное программирование

• -XX:MaxDirectMemorySize=<value>

Альтернативы

Real Time System Java Иерархия регионов памяти

• Объекты выделяются в выбранном регионе

• Локальные и “бессмертные” регионы не собираются

• Локальные регионы освобождаются целиком

• Глобальные объекты не могу ссылаться на локальные

Альтернативы

Unsafe Java™

sun.misc.Unsafe

• Unsafe.allocateMemory(…)

• Unsafe.reallocateMemory(…)

• Unsafe.freeMemory(…)

Спасибо

Алексей Рагозин alexey.ragozin@gmail.com

http://blog.ragozin.info - мои статьи о JVM и не только

top related