Почему 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.