Разница между компактными строками и сжатыми строками в Java 9
каковы преимущества компактный строки над сжатыми строками в JDK9?
4 ответов:
сжатые строки (Java 6) и компактные строки (Java 9) имеют одинаковую мотивацию (строки часто эффективно латинские-1, поэтому половина пространства тратится впустую) и цель (делают эти строки маленькими), но реализации сильно отличаются.
Сжатые Строки
на интервью Алексей Шипилев (который отвечал за реализацию функции Java 9) сказал следующее о сжатых строках:
UseCompressedStrings особенность была довольно консервативной: при различении
char[]иbyte[]случай, и пытается сжатьchar[]наbyte[]onStringстроительство, это сделано большинствоStringоперацииchar[], который требуется для распаковкиString.таким образом, он выиграл только специальный тип рабочих нагрузок, где большинство строк сжимаются (поэтому сжатие не идет впустую), и только ограниченное количество известныхStringоперации выполняются на них (поэтому распаковка не требуется). В Великом много рабочих нагрузок, включая-XX:+UseCompressedStringsбыла пессимизация.[...] Реализация UseCompressedStrings была в основном дополнительной функцией, которая поддерживала полностью отличную
Stringреализации вalt-rt.jar, который был загружен после предоставления опции VM. Дополнительные функции сложнее проверить, так как они удваивают количество комбинаций опций, чтобы попробовать.Компактный Строки
в Java 9, с другой стороны, компактные строки полностью интегрирован в источник JDK.
Stringи всегда при поддержкеbyte[], где символы используют один байт, если они латинские-1 и в противном случае два. Большинство операций делают проверку, чтобы увидеть, что это так, напримерcharAt:public char charAt(int index) { if (isLatin1()) { return StringLatin1.charAt(value, index); } else { return StringUTF16.charAt(value, index); } }компактные строки включены по умолчанию и могут быть частично отключены - "частично", потому что они все еще поддерживаются
byte[]и операции возвратаchars все равно должен собрать их вместе из двух отдельных байтов (из-за встроенных функций это трудно сказать, влияет ли это на производительность).больше
если вы заинтересованы в более подробной информации на компакт-строки, которые я рекомендую прочитать интервью я связан с выше и/или смотреть это великий разговор того же Алексея Шипилева (что также объясняет новую конкатенацию строк).
XX: + UseCompressedStrings и Компактный Строки разные вещи.
UseCompressedStringsозначало, что строки, которые являются только ASCII, могут быть преобразованы вbyte[], но это было выключено по-умолчанию. В jdk-9 эта оптимизация всегда включена, но не через сам флаг, а встроена.пока строки java-9 не будут сохранены внутренне как
char[]в кодировке UTF-16. От java-9 и выше они будут храниться какbyte[]. Зачем?потому что
ISO_LATIN_1каждый символ может быть закодирован в один байт (8 бит) против того, что он используется до сих пор (16 бит, 8 из каждого, где никогда не используется). Это работает только наISO_LATIN_1, но это большинство строк, используемых в любом случае.так что это делается для использования пространства.
вот небольшой пример, который должен сделать вещи более ясно:
class StringCharVsByte { public static void main(String[] args) { String first = "first"; String russianFirst = "первыи"; char[] c1 = first.toCharArray(); char[] c2 = russianFirst.toCharArray(); for (char c : c1) { System.out.println(c >>> 8); } for (char c : c2) { System.out.println(c >>> 8); } } }в первом случае мы получим только нули, это означает, что наиболее значимые 8 бит-это нули; во втором случае будет ненулевое значение, означающее, что присутствует по крайней мере один бит из наиболее значимых 8.
это означает, что если внутренне мы храним строки как массив символов, есть строковые литералы, которые фактически теряют половину каждого символа. Оказывается, есть несколько приложений, которые на самом деле тратят много места из-за этого.
у вас есть строка, сделанная из 10 символов Latin1? Вы просто потерял 80 бит, или 10 байт. Чтобы смягчить это сжатие строки было сделано. И теперь для этих строк не будет потери пространства.
внутренне это также означает, что некоторые очень хорошие вещи. Различать строки
LATIN1иUTF-16там есть полеcoder:/** * The identifier of the encoding used to encode the bytes in * {@code value}. The supported values in this implementation are * * LATIN1 * UTF16 * * @implNote This field is trusted by the VM, and is a subject to * constant folding if String instance is constant. Overwriting this * field after construction will cause problems. */ private final byte coder;теперь на основе этого
lengthвычисляется по-другому:public int length() { return value.length >> coder(); }если наша строка только Latin1, кодер будет равен нулю, поэтому длина значения (массив байтов) является размер символов. Для не-латинских типа 1 делить на два.
Компактный Строки будете иметь лучшее из обоих миров.
Как видно из определения, приведенного в документации OpenJDK:
новый класс String будет хранить символы, закодированные либо как ISO-8859-1/латинский-1 (один байт на символ), или как UTF-16 (два байта на символ), основанный на содержании строки. Флаг кодирования будет указывать, какая кодировка используется.
Как уже упоминалось @Eugene, большинство строки кодируются в формате Latin-1 и требуют одного байта на символ и, следовательно, не требуют всего 2-байтового пространства, предусмотренного в текущей реализации класса String.
новая реализация класса String изменится с
UTF-16 char arrayдоa byte arrayплюс поле флага кодировки. Дополнительный кодировка полей покажет, хранятся ли символы в формате UTF-16 или Latin-1.Это также делает вывод, что мы также сможем при необходимости храните строки в формате UTF-16. И это также становится главным пунктом различия между сжатая строка Java 6 и компактная строка Java 9 как в сжатой строке только Byte[] массив использовался для хранения, которое затем представлялось как чистый ASCII.
Сжатые Строки (- XX:+UseCompressedStrings)
это была дополнительная функция, введенная в Java 6 обновление 21 для улучшения SPECjbb производительность путем кодирования только строки US-ASCII на байт на символ.
эта функция может быть включена с помощью
-XXфлаг (-XX:+UseCompressedStrings). Когда он включен,String.valueбыл изменен на ссылку на объект и будет указывать либо наbyte[], для строк, содержащих только 7-битные US-символы ASCII, или же achar[].позже он был удален в Java 7 из-за высокой и обслуживание трудно проверить.
Компактный Строку
это новая функция, введенная в Java 9 для построения эффективной строки памяти.
перед Java 9 строковый класс хранил символы в массиве символов, используя два байта для каждого символа, но из Java 9 новый строковый класс будет хранить символы в
byte[](один байт на символ) илиchar[](два байта на символ), основываясь на содержимом строки, плюс поле флага кодировки. Если строковые символы имеют типLatin-1затемbyte[]будет использоваться иначе, если символы имеют типUTF-16затемchar[]будет использоваться. Флаг кодирования будет указывать, какая кодировка используется.
Comments