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

15,775 views

Published on

Презентация с Highload++ 2011
---
Принципы работы сборщика мусора в JVM. Использование принципа поколений. Параллельная и фоновая сборка мусора. Особенности реализации алгоритмов сборки мусора в HostSpot и JRockit JVM. Причины пауз сборки мусора и способы борьбы с ними. Особенности работы с "большими" JVM - 32 гигабайта и больше. Альтернативы сборщике мусора, прямое управление памятью в Java.

Published in: Technology
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
15,775
On SlideShare
0
From Embeds
0
Number of Embeds
6,629
Actions
Shares
0
Downloads
0
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide

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

  1. 1. Секреты сборки мусора в Java Алексей Рагозин [email_address]
  2. 2. О чём этот доклад? <ul><li>Обзор проблемы автоматического управления памятью </li></ul><ul><li>Stop-the-world паузы – причины </li></ul><ul><li>Сборка мусора в современных JVM </li></ul>
  3. 3. Сборка мусора <ul><li>Языки использующие автоматическое управление памятью </li></ul><ul><li>Java, JavaScript, Erlang, Haskell, Python, PHP, C#, Ruby, Perl, SmallTalk, OCaml, List, Scala, ML, Go, D, … </li></ul><ul><li>… and counting </li></ul><ul><li>Языки не использующие автоматическое управление памятью </li></ul><ul><li>C, C++, Pascal/Delphi, Objective-C </li></ul><ul><li>Что я забыл ? </li></ul>
  4. 4. Способы сборки мусора <ul><li>Мусор – структура данных (объект) в памяти не достижимый из программного кода. </li></ul><ul><li>Подсчёт ссылок </li></ul><ul><li>Транзитивное замыкание ссылок </li></ul><ul><li>Вообще не собирать </li></ul>
  5. 5. Подсчёт ссылок <ul><li>Просто </li></ul><ul><li>Не требует пауз для сбора мусора </li></ul><ul><li>Не очищает циклические графы </li></ul><ul><li>Дополнительные 15-30% нагрузки CPU </li></ul><ul><li>Плохо сочетается с много поточностью </li></ul>
  6. 6. Транзитивное замыкание ссылок <ul><li>Корневой набор ссылок </li></ul><ul><ul><li>Статические переменные </li></ul></ul><ul><ul><li>Локальные переменные </li></ul></ul><ul><li>Объекты достижимые из корневых ссылок – живые </li></ul><ul><li>Объекты недостижимые из корневых ссылок – мусор </li></ul><ul><li>В общем случае , граф объектов не должен меняться по мере обхода. Следовательно , приложение должно быть остановлено пока идёт сборка мусора . </li></ul>
  7. 7. Алгоритмы сборки мусора <ul><li>Mark-Sweep </li></ul><ul><ul><li>Фаза 1 – маркировка достижимых объектов </li></ul></ul><ul><ul><li>Фаза 2 – “ вычистка ” мусора </li></ul></ul><ul><li>Copy collector ( сборка копированием) </li></ul><ul><ul><li>Использует две области памяти, но выполняется в один проход </li></ul></ul><ul><li>Mark - Sweep - Compact </li></ul><ul><ul><li>Mark-Sweep + перемещение живых объектов </li></ul></ul>
  8. 8. Трёх цветная маркировка
  9. 9. Трёх цветная маркировка
  10. 10. Трёх цветная маркировка
  11. 11. Трёх цветная маркировка
  12. 12. Сборка копированием
  13. 13. Сборка копированием
  14. 14. Сборка копированием
  15. 15. Сборка копированием
  16. 16. Сборка копированием
  17. 17. Сборка копированием
  18. 18. Экономика сборки мусора <ul><li>S – объём кучи </li></ul><ul><li>L – объём живых объектов </li></ul><ul><li>Copy collection </li></ul><ul><li>Эффективность </li></ul><ul><li>Mark - Sweep </li></ul><ul><li>Эффективность </li></ul>Объём мусора в куче
  19. 19. Слабая гипотеза о поколениях <ul><li>Постулаты </li></ul><ul><li>Большинство объектов умирают молодыми </li></ul><ul><li>Число ссылок на молодые объекты мало </li></ul><ul><li>Следствие </li></ul><ul><li>Если хранить молодые и старые объекты отдельно, можно обеспечить высокую пропускную способность (молодое поколение) и эффективное использование памяти (старое поколение) . </li></ul>
  20. 20. Демография объектов в куче
  21. 21. Generational collection <ul><li>Молодое поколение </li></ul><ul><ul><li>Сборщик настроен на пропускную способность </li></ul></ul><ul><li>Старое поколение </li></ul><ul><ul><li>Сборщик настроен на эффективное использование памяти </li></ul></ul><ul><li>Продвижение ( promotion) объектов в старое поколение </li></ul><ul><ul><li>Сборщик молодого поколения копирует живые объекты в старое поколение после достижения “ зрелого ” возраста </li></ul></ul>
  22. 22. Generational collection <ul><li>Как получить все указатели из старого поколения на молодое? </li></ul><ul><li>Ответ - write barrier </li></ul><ul><li>Каждый раз при записи указателя в память в “ старом ” пространстве, срабатывает барьер </li></ul>
  23. 23. Молодая сборка HotSpot JVM Сбор “ корневых ” ссылок
  24. 24. Молодая сборка HotSpot JVM Копирование живых объектов
  25. 25. Молодая сборка HotSpot JVM Сборка закончена Области памяти , не помеченные в таблице карт , не могут содержать ссылки на молодое поколение
  26. 26. Stop-the-world паузы <ul><li>Изменение графа объектов во время обхода может привести к пропуску достижимых объектов </li></ul><ul><li>Большинство managed runtimes может перемещать объекты только в режиме паузы </li></ul>
  27. 27. Stop-the-world паузы <ul><li>Параллельные (parallel) алгоритмы </li></ul><ul><li>Используют несколько потоков чтобы сократить время пауз </li></ul><ul><li>Конкурентные ( concurrent) алгоритмы </li></ul><ul><li>Выполняют большую часть работы в фоновом режиме (без STW пауз) </li></ul><ul><li>Инкрементальные алгоритмы </li></ul><ul><li>Много маленьких STW вместо одной длитетьной </li></ul>
  28. 28. Concurrent marking <ul><li>Проблема </li></ul><ul><li>Граф объектов меняется по мере обхода * </li></ul><ul><li>* Даже в функциональных языках могут выполняться отложенные вычисления , меняющие граф </li></ul><ul><li>Решение </li></ul><ul><li>write-barrier – отслеживать ссылки изменившиеся за время обхода </li></ul>
  29. 29. Concurrent marking <ul><li>Card marking write barrier </li></ul><ul><ul><li>HotSpot CMS, JRockit, IBM J9 </li></ul></ul><ul><li>Snapshot-at-the-beginning (SATB) write barrier </li></ul><ul><ul><li>HotSpot G1 </li></ul></ul><ul><li>Read barrier ( помечать объекты как живые при чтении) </li></ul><ul><ul><li>Azul Zing JVM </li></ul></ul>
  30. 30. SATB write barrier (G1)
  31. 31. SATB write barrier (G1)
  32. 32. STAB write barrier (G1)
  33. 33. STAB write barrier (G1)
  34. 34. SATB write barrier (G1)
  35. 35. SATB write barrier (G1)
  36. 36. SATB write barrier (G1)
  37. 37. Card marking write barrier <ul><li>[ пауза ] Сбор корневых ссылок </li></ul><ul><li>[ фон ] Обход графа объектов </li></ul><ul><li>[ фон ] Перемаркирова “ грязных ” страниц </li></ul><ul><li>[ пауз a] Финальная перемаркирова </li></ul>
  38. 38. Перемещение объектов <ul><li>Большинство JVM не могут перемещать объекты без STW паузы. </li></ul><ul><li>Цель – уменьшение длительности пауз </li></ul><ul><li>Параллельная обработка (задействовать все ядра) </li></ul><ul><li>Инкрементальное уплотнение (чаще , но короче) </li></ul><ul><li>Не уплотнять – опасность фрагментации </li></ul>
  39. 39. Oracle HotSpot <ul><li>Default (serial) collector </li></ul><ul><li>Young: Serial copy collector, Old: serial MSC </li></ul><ul><li>Parallel scavenge / Parallel old GC </li></ul><ul><li>Young: Parallel copy collector, Old: serial MSC or parallel MSC </li></ul><ul><li>Concurrent mark sweep (CMS) </li></ul><ul><li>Young: Serial or parallel copy collector, Old: concurrent mark sweep </li></ul><ul><li>G1 (garbage first) </li></ul><ul><li>Young: Copy collector (region based) Old: Incremental MSC </li></ul>http://aragozin.blogspot.com/2011/0 9 /hotspot-jvm-garbage-collection-options.html
  40. 40. Oracle’s HotSpot JVM http://aragozin.blogspot.com/2011/0 9 /hotspot-jvm-garbage-collection-options.html
  41. 41. Oracle JRockit http:// aragozin.blogspot.com/2011/07/jrockit-gc-in-action.html -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
  42. 42. IBM J9 <ul><li>-Xgcpolicy:optthruput </li></ul><ul><li>Одно поколение , stop-the-world сборщик </li></ul><ul><li>-Xgcpolicy:optavgpause </li></ul><ul><li>Одно поколение , частично конкурентный сборщик </li></ul><ul><li>-Xgcpolicy:gencon </li></ul><ul><li>Два поколения, частично конкурентный сборщик </li></ul>
  43. 43. Azul Zing <ul><li>Два поколения </li></ul><ul><li>Молодое поколение – конкурентный mark-sweep-compact (MSC) </li></ul><ul><li>Старое поколение – конкурентный mark-sweep-compact (MSC) </li></ul><ul><li>Azul Zing выполняет перемещение объектов (уплотнение памяти) без останова приложения. Ни одна из фаз сборки мусора не требует STW паузы . </li></ul><ul><li>Секрет – read barrier. </li></ul>
  44. 44. Масштабируемость JVM <ul><li>Может ли JVM работать с большим объёмом памяти (16GiB и более) без “ фризов ”? </li></ul><ul><li>Ответ да , если приложение удовлетворяет постулатам гипотезы о поколениях. </li></ul>
  45. 45. Рецепт работы без пауз <ul><li>HotSpot JVM </li></ul><ul><li>CMS ( Concurrent Mark Sweep) сборщик мусора </li></ul><ul><li>Тюнинг </li></ul><ul><li>Результат </li></ul><ul><li>Паузы не более 150 ms на 32 GiB хипа </li></ul>
  46. 46. HotSpot CMS сборщик <ul><li>Сборка молодого поколения копированием </li></ul><ul><li>Не перемещает объекты в старом поколении </li></ul><ul><li>Статистические методы борьбы с фрагментацией </li></ul><ul><li>Две дополнительные STW фазы </li></ul><ul><ul><li>initial-mark, remark </li></ul></ul><ul><li>Вся остальная работа происходит в фоне </li></ul>
  47. 47. Длительность пауз CMS сборщика
  48. 48. Можно лучше – OpenJDK патч http://aragozin.blogspot.com/2011/07/openjdk-patch-cutting-down-gc-pause.html
  49. 49. Сборка мусора в JVM <ul><li>Сборка мусора не чёрная магия </li></ul><ul><li>Каждое приложение индивидуально </li></ul><ul><li>Приложение не должно мешать сборщику мусора </li></ul><ul><li>JVM может работать без пауз (с паузами не более 100 -200ms) </li></ul><ul><li>Автоматическое управление памятью не универсально (Проблемные приложения : HBase, Cassandra) </li></ul>
  50. 50. Альтернативы <ul><li>java.nio.ByteBuffer.allocateDirect() </li></ul><ul><li>Pro </li></ul><ul><li>Memory is allocated out of heap </li></ul><ul><li>Memory is deallocated when ByteBuffer is collected </li></ul><ul><li>Cross platform, native java </li></ul><ul><li>Con </li></ul><ul><li>Fragmentation of non-heap memory </li></ul><ul><li>Memory is deallocated when ByteBuffer is collected </li></ul><ul><li>Complicated multi thread programming </li></ul><ul><li>-XX:MaxDirectMemorySize=<value> </li></ul>
  51. 51. Альтернативы <ul><li>Real Time System Java </li></ul><ul><li>Иерархия регионов памяти </li></ul><ul><li>Объекты выделяются в выбранном регионе </li></ul><ul><li>Локальные и “ бессмертные ” регионы не собираются </li></ul><ul><li>Локальные регионы освобождаются целиком </li></ul><ul><li>Глобальные объекты не могу ссылаться на локальные </li></ul>
  52. 52. Альтернативы <ul><li>Unsafe java </li></ul><ul><li>sun.misc.Unsafe </li></ul><ul><li>Unsafe.allocateMemory(…) </li></ul><ul><li>Unsafe.reallocateMemory(…) </li></ul><ul><li>Unsafe.freeMemory(…) </li></ul>
  53. 53. <ul><li>Спасибо </li></ul>Алексей Рагозин [email_address] http://aragozin.blogspot.com - мои статьи о JVM и не только

×