Почему Go может снизить GC-паузы до sub 1ms, а JVM - нет?
Итак, вот что: https://groups.google.com/forum/?fromgroups#!topic/golang-dev/Ab1sFeoZg_8:
Сегодня я представил изменения в сборщик мусора, которые делают типичные наихудшие случаи остановки в мире менее 100 микросекунд. Это должно особенно улучшить паузы для приложений со многими активными гортанами, которые могли бы значительно увеличить время паузы.
Высокие GC-паузы - это одно, если пользователи JVM работают с ними долгое время.
Каковы ограничения (архитектурные?), которые не позволяют JVM опускать GC-паузы до уровней Go, но не влияют на Go?
Ответы
Ответ 1
Каковы (архитектурные?) Ограничения, которые не позволяют JVM понижать паузы GC до уровней golang
Нет.
Высокие GC-паузы - это одна из тех вещей, с которыми пользователи JVM долго борются.
Небольшой поиск в Google показывает, что аналогичные решения доступны и для Java
- Азул предлагает бездействующий коллектор, который масштабируется даже до 100GB+
- Redhat вносит вклад shenandoah в openjdk и oracle zgc.
- IBM предлагает метроном, также рассчитывая на время микросекундной паузы
- различные другие виртуальные машины в реальном времени
Другие сборщики в openjdk, в отличие от Go, уплотняют сборщики поколений. Это делается для того, чтобы избежать проблем фрагментации и обеспечить более высокую пропускную способность на машинах серверного класса с большими кучами, позволяя выделять рельефные указатели и сокращать время ЦП, затрачиваемое в GC. И, по крайней мере, в хороших условиях CMS может достигать однозначных миллисекундных пауз, несмотря на то, что он работает в паре с движущимся коллектором молодого поколения.
Go-коллектор не поколен, не компактен и требует барьеров записи (см. этот другой вопрос SO), что приводит к снижению пропускной способности/увеличению загрузки ЦП для коллекций, увеличению объема памяти (фрагментации) и уменьшению кэш-памяти. эффективное размещение объектов в куче (некомпактное расположение памяти).
Ответ 2
Согласно этой презентации, Getting to Go: сборщик мусора Go, сборщики Go используют только половину кучи для живых данных:
Куча 2X живая куча
У меня сложилось впечатление, что Java GC, как правило, стремятся к более высокому использованию кучи, поэтому они делают здесь совсем другой компромисс.
Ответ 3
Каковы (архитектурные?) Ограничения, которые мешают JVM понизить паузы GC до уровней Go, но не влияют на Go?
Принципиально я бы сказал, что java - это ориентированный на ссылки язык, а Go - ориентированный на значение.
У этого есть много аспектов: метаданные объектов, обработка параллелизма... Естественно, Java не позволяет размещать примитивы в коллекциях, которые дают большие накладные расходы в смысле количества объектов, в Golang у вас есть Array, Slice и Map, которые поддерживают примитивные типы...
Здесь хорошая статья о развитии и развитии Golang GC.