openjdk.ruOpenJDK на русском

JEP draft: 4-byte Object Headers (Experimental)

4-байтовые заголовки объектов, статус Experimental (экспериментальная функция)

Авторrkennke
ОтветственныйRoman Kennke
ТипFeature
ОбластьImplementation
СтатусDraft
Компонентhotspot / runtime
ТрудоёмкостьL
ДлительностьL
Создан2025/01/30 13:03
Обновлён2025/01/30 13:04
Задача8349069

Аннотация

Уменьшить размер заголовков объектов в HotSpot JVM на 64-битных архитектурах: сейчас он составляет от 64 до 128 бит, а должен составить 32 бита. Это уменьшит размер кучи, повысит плотность развёртывания и улучшит локальность данных.

Цели

Когда эта возможность включена, она

  • обязана уменьшать размер заголовка объекта до 32 бит (4 байт) на целевых 64-битных платформах (x64 и AArch64),
  • должна уменьшать размеры объектов и объём занимаемой памяти на реалистичных нагрузках,
  • не должна увеличивать пропускную способность или задержку более чем на 5 % на целевых 64-битных платформах, причём лишь в редких случаях, и
  • не должна вносить измеримых накладных расходов на пропускную способность или задержку на нецелевых 64-битных платформах.

Когда эта возможность выключена, она

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

Эта Experimental-возможность окажет широкое влияние на реальные приложения. В коде могут быть неэффективные места, ошибки и непредвиденное поведение, которое ошибкой не является. Поэтому эта возможность обязана быть выключена по умолчанию и включаться только по явному запросу пользователя. Мы намерены включить её по умолчанию в более поздних выпусках, а в конечном счёте полностью удалить код прежних заголовков объектов.

Что не является целью

Целью не является

  • уменьшение размера заголовка объекта ниже 32 бит на 64-битных платформах,
  • уменьшение размера заголовка объекта на нецелевых 64-битных платформах,
  • изменение размера заголовка объекта на 32-битных платформах или
  • изменение кодирования содержимого объекта (то есть полей и элементов массива) или метаданных массива (то есть длины массива).

Мотивация

У объекта, который хранится в куче, есть метаданные, и HotSpot JVM хранит их в заголовке объекта. Размер заголовка постоянен: он не зависит от типа объекта, формы массива и содержимого. В 64-битной HotSpot JVM заголовки объектов занимают от 64 бит (8 байт) до 128 бит (16 байт) в зависимости от конфигурации JVM.

Объекты в программах на Java, как правило, небольшие. Эксперименты в рамках проекта Lilliput показывают, что во многих нагрузках средний размер объекта составляет от 256 до 512 бит (от 32 до 64 байт). Это означает, что более 20 % живых данных может приходиться на одни только заголовки объектов. Поэтому даже небольшое уменьшение размера заголовка объекта может дать значительный выигрыш: меньше занимаемой памяти, лучше локальность данных и ниже нагрузка на сборку мусора. Первые пользователи проекта Lilliput, которые опробовали его на реальных приложениях, подтверждают, что объём живых данных обычно сокращается на 10–20 %.

JEP 450 ввёл Compact Object Headers (компактные заголовки объектов), которые уменьшили размер заголовка объекта до 8 байт. Этот JEP основан на JEP 450, идёт ещё дальше и уменьшает размер заголовка объекта всего до 4 байт.

Описание

Compact Object Headers — Experimental-возможность, поэтому по умолчанию она выключена. Режим Compact Object Headers можно включить флагом -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders.

Текущая структура заголовков объектов

Будет дополнено

Структура 4-байтового заголовка объекта

Будет дополнено

Компактный хэш-код Identity (идентичность объекта)

Будет дополнено

Компактная переадресация объектов при сборке мусора

Будет дополнено

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

  • Таблица поиска для хэш-кода Identity (будет дополнено)
  • Таблица поиска для переадресации объектов при сборке мусора (будет дополнено)

Тестирование

Изменение структуры заголовка объектов в куче Java затрагивает многие подсистемы HotSpot JVM: среду выполнения, все сборщики мусора, все JIT-компиляторы, интерпретаторы, serviceability agent и платформенно-зависимый код для всех поддерживаемых платформ. Такие масштабные изменения требуют масштабного тестирования.

Режим Compact Object Headers будет проверяться с помощью:

тестов уровней 1–4 и, возможно, дополнительных уровней тестирования у тех поставщиков, у которых они есть; наборов бенчмарков SPECjvm, SPECjbb, DaCapo и Renaissance для проверки как корректности, так и производительности; JCStress для проверки новой реализации блокировок; а также некоторых реальных нагрузок. Все эти тесты будут выполняться с включённой и с выключенной возможностью, с разными сочетаниями сборщиков мусора и JIT-компиляторов и на нескольких аппаратных платформах.

Мы также предоставим новый набор тестов, которые измеряют размер различных объектов, например обычных объектов, массивов примитивных типов и массивов ссылок, а также размер их заголовков.

Окончательной проверкой производительности и корректности станут реальные нагрузки после выпуска этой Experimental-возможности.

Риски и допущения

  • Будущим возможностям среды выполнения нужны биты заголовка объекта — в частности, известно, что проекту Valhalla могут понадобиться несколько битов заголовка. Чтобы учесть такие потребности, это предложение оставляет 4 свободных бита заголовка для использования в будущем.

  • Ошибки реализации в коде возможности — обычный риск для такой глубокой переделки, как эта, — ошибки в реализации. Проблемы в структуре заголовка, скорее всего, сразу проявятся в большинстве тестов, а вот тонкие места новых протоколов блокировки и переадресации объектов при сборке мусора могут приводить к ошибкам лишь изредка. Мы снижаем этот риск тщательным рецензированием со стороны ответственных за компоненты и запуском множества тестов с включённой возможностью. Этот риск не затрагивает продукт, пока возможность остаётся в статусе Experimental и выключена по умолчанию.

  • Ошибки реализации в прежнем коде — мы стараемся не менять прежние пути выполнения кода, но некоторые рефакторинги неизбежно затрагивают общий код. Из-за этого возникает риск ошибок даже при выключенной возможности. Помимо тщательного рецензирования и тестирования, мы снижаем этот риск, программируя защитно и стараясь не изменять общие пути выполнения кода, даже если из-за этого приходится больше работать над путями кода самой возможности.

  • Проблемы производительности в коде возможности — более сложные протоколы Compact Object Headers могут вызывать проблемы производительности при включённой возможности. Мы снижаем этот риск, запуская основные бенчмарки и выясняя, как возможность влияет на их производительность. Этот риск не затрагивает продукт, пока возможность остаётся в статусе Experimental и выключена по умолчанию.

  • Проблемы производительности в прежнем коде — есть небольшой риск, что рефакторинг прежних путей выполнения кода неожиданным образом повлияет на производительность. Мы снижаем этот риск, сводя к минимуму изменения в прежних путях выполнения кода и показывая, что производительность основных нагрузок существенно не меняется.

  • Поддержка сжатых указателей на классы — JVMCI на x64 не поддерживает сжатые указатели на классы. Мы снижаем непосредственный риск, выключая Compact Object Headers при включённом JVMCI. Долгосрочный риск состоит в том, что Compact Object Headers так и не будут реализованы в JVMCI, и это навсегда заблокирует удаление прежней реализации заголовков. Мы оцениваем вероятность этого риска как небольшую, поскольку другие JIT-компиляторы поддерживают Compact Object Headers без глубоких изменений.

  • Кодирование сжатых указателей на классы — как сказано выше, текущая реализация сжатых указателей на классы ограничена примерно 500 000 классов. Сейчас пользователи могут обойти это ограничение, выключив Compact Object Headers и сжатые указатели на классы, но если мы удалим прежнюю реализацию заголовков, это станет невозможно. Мы снижаем непосредственный риск, предоставляя Compact Object Headers как Experimental-возможность; в долгосрочной перспективе мы намерены работать над более эффективными схемами кодирования сжатых указателей на классы.

  • Изменение низкоуровневых интерфейсов — некоторым компонентам, которые работают с заголовками объектов напрямую, в частности компилятору Graal как основному пользователю JVMCI, придётся реализовать новую структуру заголовка. Мы снижаем текущий риск, выявляя эти компоненты и выключая возможность, когда они используются. Прежде чем возможность выйдет из статуса Experimental, эти компоненты нужно будет обновить.

  • Мягкий провал проекта — есть небольшой риск, что у возможности окажутся неустранимые функциональные регрессии по сравнению с прежней реализацией, например ограничение числа представимых классов. Связанный риск: возможность сама по себе даёт значительный прирост производительности, но при этом имеет существенные функциональные ограничения, и это может стать доводом в пользу того, чтобы навсегда сохранить и новую, и прежнюю реализацию заголовков. Поскольку цель этой работы — в конечном счёте заменить прежнюю реализацию заголовков, мы считаем такой исход мягким провалом проекта. Мы снижаем этот риск: тщательно изучаем текущие ограничения, планируем дальнейшую работу по их устранению и выявляем другие риски по отчётам первых пользователей, прежде чем вкладывать слишком много усилий.

  • Жёсткий провал проекта — хотя это очень маловероятно, может оказаться, что Compact Object Headers не дают ощутимых улучшений на практике или что достижимые улучшения не оправдывают дополнительной сложности. Мы снижаем этот небольшой риск, закрывая новые пути выполнения кода статусом Experimental и тем самым оставляя возможность при необходимости удалить эту функциональность в будущем выпуске.

Зависимости

Этот JEP основан на JEP 450: Compact Object Headers (Experimental) и расширяет его.