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. Даже после устранения дубликатов оставшиеся строковые данные могут занимать меньше места, если кодировать их эффективнее. Мы предполагаем, что этот проект всё же принесёт пользу, соизмеримую с требуемыми усилиями.