Разница между компактными строками и сжатыми строками в Java 9



каковы преимущества компактный строки над сжатыми строками в JDK9?

633   4  

4 ответов:

сжатые строки (Java 6) и компактные строки (Java 9) имеют одинаковую мотивацию (строки часто эффективно латинские-1, поэтому половина пространства тратится впустую) и цель (делают эти строки маленькими), но реализации сильно отличаются.

Сжатые Строки

на интервью Алексей Шипилев (который отвечал за реализацию функции Java 9) сказал следующее о сжатых строках:

UseCompressedStrings особенность была довольно консервативной: при различении char[] и byte[] случай, и пытается сжать char[] на byte[] on String строительство, это сделано большинство 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, или же a char[].

позже он был удален в Java 7 из-за высокой и обслуживание трудно проверить.

Компактный Строку

это новая функция, введенная в Java 9 для построения эффективной строки памяти.

перед Java 9 строковый класс хранил символы в массиве символов, используя два байта для каждого символа, но из Java 9 новый строковый класс будет хранить символы в byte[](один байт на символ) или char[](два байта на символ), основываясь на содержимом строки, плюс поле флага кодировки. Если строковые символы имеют тип Latin-1 затем byte[] будет использоваться иначе, если символы имеют тип UTF-16 затем char[] будет использоваться. Флаг кодирования будет указывать, какая кодировка используется.

Comments

    Ничего не найдено.