developer tip

Java 9에서 압축 문자열과 압축 문자열의 차이점

optionbox 2020. 11. 18. 08:57
반응형

Java 9에서 압축 문자열과 압축 문자열의 차이점


의 장점은 무엇입니까 컴팩트 문자열 JDK9에서 압축 된 문자열 이상은?


압축 된 문자열 (Java 6)과 압축 된 문자열 (Java 9)은 모두 동일한 동기 (문자열은 사실상 Latin-1이므로 공간의 절반이 낭비 됨)와 목표 (문자열을 작게 만들기)는 동일하지만 구현 방식이 많이 다릅니다.

압축 된 문자열

에서 의 인터뷰 (자바 (9) 기능을 구현 담당 한) 알렉세이 Shipilëv이 압축 문자열에 대해 말을했다 :

구별 동안 : UseCompressedStrings 기능은 보수적이었다 char[]byte[]케이스, 그리고 압축하려고 char[]byte[]String건설이 대부분 완료 String에 대한 작업을 char[]압축을 풀 필요가있는, String.따라서 때문에 (대부분의 문자열이 압축되어 워크로드의 특별한 유형의 혜택을, 압축은 낭비되지 않으며 제한된 양의 알려진 String작업 만 수행됩니다 (따라서 포장을 풀지 않아도 됨). 많은 워크로드에서 활성화 -XX:+UseCompressedStrings는 비관적이었습니다.

[...] UseCompressedStrings 구현은 기본적으로 VM 옵션이 제공되면로드 된 String에서 완전히 별개의 구현 을 유지하는 선택적 기능 alt-rt.jar이었습니다. 옵션 기능은 시도 할 옵션 조합의 수를 두 배로 늘리기 때문에 테스트하기가 더 어렵습니다.

콤팩트 스트링

반면에 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);
    }
}

압축 문자열은 기본적으로 활성화되며 부분적으로 비활성화 될 수 있습니다. "부분적으로"여전히 a에 의해 지원되고 s를 byte[]반환 하는 작업 char은 여전히 ​​두 개의 개별 바이트에서 이들을 모아야합니다 (내 재성 때문에 이것이 성능에 영향을 미치는지 여부를 말하기는 어렵습니다). ).

콤팩트 한 스트링에 대한 더 많은 배경에 관심이 있다면 위에서 링크 한 인터뷰 를 읽 거나 동일한 Aleksey Shipilëv (새로운 스트링 연결에 대해서도 설명 함)의 훌륭한 강연을 시청하는 것이 좋습니다 .


XX : + UseCompressedStringsCompact Strings 는 서로 다릅니다.

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);
        }
    }
}

첫 번째 경우 우리는 0 만 얻을 것입니다. 즉, 최상위 8 비트는 0입니다. 두 번째 경우에는 0이 아닌 값이있을 것입니다. 즉, 최상위 8에서 적어도 하나의 비트가 존재 함을 의미합니다.

즉, 내부적으로 문자열을 문자 배열로 저장하면 실제로 각 문자의 절반을 낭비하는 문자열 리터럴이 있습니다. 이 때문에 실제로 많은 공간을 낭비하는 여러 응용 프로그램이 있습니다.

10 개의 Latin1 문자로 만든 문자열이 있습니까? 방금 80 비트 또는 10 바이트를 잃었습니다. 이 문자열 압축을 완화하기 위해 만들어졌습니다. 이제 이러한 문자열에 대한 공간 손실이 없습니다.

내부적으로 이것은 또한 매우 좋은 것을 의미합니다. 있는 문자열 LATIN1UTF-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;

Now based on this length is computed differently:

public int length() {
    return value.length >> coder();
}

If our String is Latin1 only, coder is going to be zero, so length of value (the byte array) is the size of chars. For non-Latin1 divide by two.


Compact Strings will have best of both worlds.

As can be seen in the definition provided in OpenJDK documentation:

The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

As mentioned by @Eugene, most of the strings are encoded in Latin-1 format and require one byte per character and hence do not require the whole 2-byte space provide in current String class implementation.

The new String class implementation will shift from UTF-16 char array to a byte array plus an encoding-flag field. The additional encoding field will show whether the characters are stored using UTF-16 or Latin-1 format.

This also concludes that we will also be able to store strings in UTF-16 format if required. And this also becomes the main point of difference between the Compressed String of Java 6 and Compact String of Java 9 as in Compressed String only byte[] array was used for storage which was then representated as pure ASCII.


Compressed Strings (-XX:+UseCompressedStrings)

This was a optional feature introduced in Java 6 Update 21 to improve SPECjbb performance by encoding only US-ASCII String on a byte per character.

This feature can be enabled by an -XX flag (-XX:+UseCompressedStrings). When it is enabled, String.value was changed to an Object reference and would point either to a byte[], for strings containing only 7-bit US-ASCII characters, or else a char[].

Later it was removed in Java 7 because of high maintenance and hard to test.

Compact String

This is a new feature introduced in Java 9 to build a memory efficient String.

Before Java 9, the String class stored characters in a char array, using two bytes for each character but from Java 9 the new String class will store characters in byte[](one byte per character) or char[](two bytes per character), based upon the contents of the string, plus an encoding-flag field. If String characters are of type Latin-1 then byte[] will be used else if characters are of type UTF-16 then char[] will be used. The encoding flag will indicate which encoding is used.

참고URL : https://stackoverflow.com/questions/44178432/difference-between-compact-strings-and-compressed-strings-in-java-9

반응형