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

JEP 254: Compact Strings

Компактные строки

АвторBrent Christian
ОтветственныйXueming Shen
ТипFeature
ОбластьImplementation
СтатусClosed / Delivered
Выпуск9
Компонентcore-libs / java.lang
Обсуждение core dash libs dash dev at openjdk dot java dot net
ТрудоёмкостьL
ДлительностьXL
Связан сJEP 192: String Deduplication in G1
8144691: JEP 254: Compact Strings: endiannes mismatch in Java source code and intrinsic
JEP 250: Store Interned Strings in CDS Archives
JEP 280: Indify String Concatenation
РецензентыAleksey Shipilev, Brian Goetz, Charlie Hunt
ОдобренBrian Goetz
Создан2014/08/04 21:54
Обновлён2025/07/23 10:59
Задача8054307

Аннотация

Перейти на более экономное по памяти внутреннее представление строк.

Цели

Повысить эффективность использования памяти классом String и связанными с ним классами, сохранив производительность в большинстве сценариев и полную совместимость для всех связанных Java- и нативных интерфейсов.

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

Использование других кодировок, например UTF-8, во внутреннем представлении строк не является целью. Этот подход может быть исследован в одном из последующих JEP.

Мотивация

Текущая реализация класса String хранит символы в массиве char и использует по два байта (шестнадцать бит) на каждый символ. Данные, собранные со множества разных приложений, показывают, что строки занимают значительную часть кучи и что большинство объектов String содержат только символы Latin-1. Для хранения таких символов нужен всего один байт, поэтому половина места во внутренних массивах char таких объектов String не используется.

Описание

Мы предлагаем изменить внутреннее представление класса String с массива char в кодировке UTF-16 на массив byte и поле с флагом кодировки. Новый класс String будет хранить символы либо в кодировке ISO-8859-1/Latin-1 (один байт на символ), либо в UTF-16 (два байта на символ), в зависимости от содержимого строки. Флаг кодировки будет указывать, какая кодировка используется.

Связанные со строками классы, такие как AbstractStringBuilder, StringBuilder и StringBuffer, будут обновлены и начнут использовать то же представление; то же относится и к встроенным (intrinsic) строковым операциям HotSpot VM.

Это исключительно изменение реализации, существующие публичные интерфейсы не меняются. Добавлять новые публичные API или другие интерфейсы не планируется.

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

Подробнее см.:

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

Мы пробовали возможность «сжатых строк» в обновлениях JDK 6; она включалась флагом -XX. Если она была включена, String.value заменялось ссылкой Object, которая указывала либо на массив byte (для строк, содержащих только 7-битные символы US-ASCII), либо на массив char. Исходный код этой реализации не был открыт, поэтому её было трудно поддерживать и синхронизировать с основной веткой исходного кода JDK. С тех пор она была удалена.

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

Для изменения столь фундаментальной части платформы необходимо тщательное тестирование совместимости и регрессионное тестирование.

Нам также нужно будет подтвердить, что цели этого проекта по производительности достигнуты. Потребуется проанализировать экономию памяти. Тестирование производительности следует проводить на широком спектре нагрузок — от узконаправленных микробенчмарков до крупномасштабных серверных нагрузок.

Мы будем призывать всё Java-сообщество заранее протестировать это изменение, чтобы выявить оставшиеся проблемы.

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

Оптимизация хранения символов с точки зрения памяти вполне может потребовать компромисса в производительности во время выполнения. Мы ожидаем, что это будет компенсировано снижением активности сборки мусора и что нам удастся сохранить пропускную способность в типичных серверных бенчмарках. Если нет, мы исследуем оптимизации, которые позволят найти приемлемый баланс между экономией памяти и производительностью во время выполнения.

Другие недавние проекты уже сократили объём кучи, занимаемый строками, в частности JEP 192: String Deduplication in G1. Даже после устранения дубликатов оставшиеся строковые данные могут занимать меньше места, если кодировать их эффективнее. Мы предполагаем, что этот проект всё же принесёт пользу, соизмеримую с требуемыми усилиями.