DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java"...

60
Секреты сборки мусора Секреты сборки мусора в в Java Java Алексей Рагозин [email protected]

Transcript of DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java"...

Page 1: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Алексей Рагозин[email protected]

Page 2: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

• Stop-the-world паузы – причины• Сборка мусора в современных JVM

Page 3: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Языки использующие автоматическое управление памятью Java, JavaScript, Erlang, Haskell, Python, PHP, C#, Ruby, Perl, SmallTalk, OCaml, List, Scala, ML, Go, D, … … and counting

Языки не использующие автоматическое управление памятью C, C++, Pascal/Delphi, Objective-C Что я забыл?

Page 4: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Подсчёт ссылокТранзитивное замыкание ссылок Вообще не собирать

Page 5: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

+ Просто+ Не требует пауз для сбора мусора– Не очищает циклические графы– Дополнительные 15-30% нагрузки CPU– Плохо сочетается с много поточностью

Page 6: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

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

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

Page 7: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

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

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

Page 8: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

roots

Page 9: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

roots

roots

Page 10: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

roots

roots

Page 11: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

roots

roots

Page 12: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

FROM

TO

roots

Page 13: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

FROM

TO

roots

FROM

TO

roots

Page 14: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

FROM

TO

roots

FROM

TO

roots

1

Page 15: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

FROM

TO

roots

FROM

TO

roots

1 2

Page 16: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

FROM

TO

roots

FROM

TO

roots

1 2

Page 17: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

FROM

TO

roots

FROM

TO

roots

1 23

Page 18: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Экономика сборки мусораЭкономика сборки мусораS – объём кучиL – объём живых объектов

Copy collection ЭффективностьMark-Sweep Эффективность

L

LSc

S

LSc

L

LSc

21

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

Page 19: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

СледствиеЕсли хранить молодые объекты отдельно от старых, можно

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

Page 20: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

См

ертн

ость

айт/

с)

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

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

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

Page 21: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Generational collectionGenerational collection Молодое поколение

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

Сборщик настроен на эффективное использование памяти Продвижение (promotion) объектов в старое поколение

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

Page 22: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Generational collectionGenerational collection

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

Page 23: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Eden S1 S2 Tenured

Dirty cards

Collect roots for young GCScan stack tracesScan dirty pages in old space

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

Page 24: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Eden S1 S2 Tenured

Dirty cards

Collect roots for young GCClean cardsRecursive copy of live objects (only live objects are traversed)

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

Page 25: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Eden S1 S2 Tenured

Dirty cards

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

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

Page 26: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Stop-the-world Stop-the-world паузыпаузы

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

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

Page 27: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Stop-the-world Stop-the-world паузыпаузы

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

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

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

Page 28: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

Page 29: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Фоновая маркировкаФоновая маркировка Card marking write barrier

HotSpot CMS, JRockit, IBM J9 Snapshot-at-the-beginning (SATB) write barrier

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

чтение Azul Zing JVM

Page 30: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC A

C

Page 31: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC C

D

Page 32: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC C

D

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

Page 33: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC C

D

Page 34: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC D

D

Page 35: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC

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

Page 36: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

A B C D

GC

Reference queue:

B

D

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

Page 37: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

[пауза] Сбор корневых ссылок [фон] Обход графа объектов [фон] Перемаркирова “грязных” страниц [паузa] Финальная перемаркирова

Page 38: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

Цель – уменьшение длительности паузПараллельная обработка (задействовать все ядра)Инкрементальное уплотнение (чаще, но короче)Не уплотнять – опасность фрагментации

Page 39: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Oracle HotSpotOracle HotSpotОднопоточный сборщик мусора-XX:+UseSerialGCМолодое поколение:• Сборка копированиемСтарое поколение:• Mark Sweep CompactВозвращает неиспользуемую

память ОС после сборки старшего поколения

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

Page 40: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Oracle HotSpotOracle HotSpotПараллельный сборщик мусора-XX:+UseParallelGC –XX:+UseParallelOldGCМолодое поколение:• Многопоточная сборка копированиемСтарое поколение:• Многопоточный Mark Sweep Compact

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

Page 41: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Oracle HotSpotOracle HotSpotФоновый сборщик мусора-XX:+UseConcMarkSweepGCМолодое поколение:• Одно или многопоточная сборка копированиемСтарое поколение:• Фоновая Mark Sweep сборкаНе перемещает объекты в старом поколении при сборке в

фоновом режиме

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

Page 42: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Oracle HotSpotOracle HotSpotФоновый сборщик мусора-XX:+UseG1GCМолодое поколение:• Многопоточная сборка копированиемСтарое поколение:• Инкрементальная многопоточная сборка копированиемВозвращает не используемую память ОС

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

Page 43: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Oracle’s HotSpot JVMOracle’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

Page 44: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Oracle JRockitOracle JRockit

-Xgc: option Generational Mark Sweep/Compact

genconcon or gencon Yes concurrent incrementalsingleconcon or singlecon No concurrent incremental

genconpar Yes concurrent parallelsingleconpar No concurrent parallelgenparpar or genpar Yes parallel parallelsingleparpar or singlepar No parallel parallel

genparcon Yes parallel incrementalsingleparcon No parallel incremental

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

Page 45: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

IBM J9IBM J9-Xgcpolicy:optthruput Одно поколение, stop-the-world сборщик

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

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

Page 46: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Azul ZingAzul Zing• Два поколения• Молодое поколение – конкурентный mark-sweep-compact

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

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

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

Page 47: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

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

Page 48: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

• HotSpot JVM• CMS (Concurrent Mark Sweep) сборщик

мусора• ТюнингРезультат• Паузы не более 150ms на 32GiB кучи

Page 49: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

HotSpot CMS HotSpot CMS сборщиксборщик Сборка молодого поколения копированием Не перемещает объекты в старом поколении Статистические методы борьбы с фрагментацией Две дополнительные STW фазы

initial-mark, remark Вся остальная работа происходит в фоне

Page 50: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Page 51: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Профилактика фрагментации:• увеличение размера кучи• более частые циклы сборки• HotSpot JVM версии 6u26 и старше

Page 52: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Настройка CMS на большом объёме кучи• -XX:MaxNewSize= ? – размер молодого поколения• -XX:CMSWaitDuration= ? • -XX:-CMSConcurrentMTEnabled – защита от бага в JVM• -XX:+UseCMSInitiatingOccupancyOnly• -XX:+CMSClassUnloadingEnabled – если действительно нужно• -XX:ParGCCardsPerStrideChunk= ? – если куча больше 16 GiB• JVM 1.6u26 или более поздняя• плюс логирование GC

Page 53: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

• Свопинг ОС• Обработка ссылок (weak, soft, phantom, JNI)• Объекты требующие “финализации”• JNI, native код может блокировать GC• Проблемы с permanent generation

Page 54: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

HotSpot G1HotSpot G1

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

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

Page 55: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

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

RFE-7068625

Page 56: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

ИТОГИТОГ: : Сборка мусора в Сборка мусора в JVMJVM Сборка мусора не чёрная магия Каждое приложение индивидуально Приложение не должно мешать сборщику мусора JVM может работать “почти” без пауз

(с паузами не более 100-200ms) Автоматическое управление памятью не

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

Page 57: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

АльтернативыАльтернативыjava.nio.ByteBuffer.allocateDirect()Достоиства• Память выделяется вне кучи• Память освобождается автоматически (через ByteBuffer объект)• Кроссплатформенность, “чистая Java”Недостатки• Фрагментация памяти вне кучи• Память освобождается автоматически (через ByteBuffer объект)• Усложняет многопоточное программирование• -XX:MaxDirectMemorySize=<value>

Page 58: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Real Time System JavaИерархия регионов памяти• Объекты выделяются в выбранном регионе• Локальные и “бессмертные” регионы не собираются• Локальные регионы освобождаются целиком• Глобальные объекты не могу ссылаться на локальные

Page 59: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

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

Unsafe Java™sun.misc.Unsafe• Unsafe.allocateMemory(…)• Unsafe.reallocateMemory(…)• Unsafe.freeMemory(…)

Page 60: DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин

Спасибо

Алексей Рагозин [email protected]

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