Java String의 Byte [] 변환 성능을 향상시키는 방법에 대한 제안이 있습니까?

StackOverflow https://stackoverflow.com/questions/1023701

문제

나는 문자열 -> 바이트 [] 변환을 집중적으로 사용하는 코드를 상속하고 일부는 자체 제작 코드에 대해서도 그 반대를 상속했습니다. 본질적으로 Java 객체는 구성 부품을 문자열로 변환하는 방법을 알고 있으며 바이트로 변환됩니다 []. 그런 다음 바이트 배열을 JNI를 통해 C ++ 코드로 전달하여 바이트를 C ++ std :: 문자열로 재구성하고 Java 객체를 반영하는 C ++ 객체를 부트 스트랩하는 데 사용합니다. 조금 더 많지만 이것은이 코드 작용이 어떻게 작동하는지에 대한 높은 수준의 관점입니다. 커뮤니케이션은 C ++ -> Java 전이가 위에서 언급 한 Java-> C ++ 전이의 미러 이미지이되도록 양방향으로 이와 같이 작동합니다.

이 코드의 한 부분 - 문자열을 바이트 []로 실제 변환하는 것은 프로파일 러에 많은 CPU를 태우는 것으로 예기치 않게 나타납니다. 물론, 전송중인 많은 데이터가 있지만 이것은 예상치 못한 병목 현상입니다.

코드의 기본 개요는 다음과 같습니다.

public void convertToByteArray(String convert_me, ByteArrayOutputStream stream)
{
  stream.write(convert_me.getBytes());
}

함수에는 조금 더 있지만 많지는 않습니다. 위의 함수는 모든 문자열/문자열 객체에 대해 한 번 호출되며 모든 구성 요소가 BytearRayoutputStream에 기록 된 후 BytearRayoutputStream이 바이트로 변환됩니다 []. 위의 위를 추출하여보다 프로파일러 친화적 인 버전으로 나눕니다. convert_me.getBytes() 전화는이 기능에서 시간의 90% 이상이 getBytes () 호출에 소비된다는 것을 보여줍니다.

GetBytes () 호출의 성능을 향상시킬 수있는 방법이 있습니까? 아니면 동일한 변환을 달성 할 수있는 더 빠른 방법이 있습니까?

변환되는 객체의 수는 상당히 큽니다. 프로덕션 데이터의 작은 부분 집합 만 사용하는 프로파일 링 실행에서는 위의 전환 기능에 1 천만 건과 같은 호출을 보게됩니다.

우리가 프로젝트를 생산으로 공개하는 데 매우 가깝기 때문에이 시점에서 불가능한 몇 가지 해결 방법이 있습니다.

  • 직렬화 인터페이스를 다시 작성하여 JNI 레이어를 가로 질러 문자열 객체를 전달합니다. 이것은 상황을 개선하는 명백한 방법이지만 직렬화 계층의 주요 리엔지니어링이 필요합니다. 우리가 이번 주 초에 UAT에 가고 있다는 사실을 감안할 때, 이런 종류의 복잡한 변화를하기에는 너무 늦었습니다. 다음 릴리스는 내 최고 ToDO이므로 완료됩니다. 그러나 그때까지는 해결 방법이 필요하지만 지금까지 코드는 작동하고 있으며 몇 년 동안 사용되었으며 대부분의 꼬임이 해결되었습니다. 글쎄, 성능을 제외하고.
  • JVM (현재 1.5)을 변경하는 것도 옵션이 아닙니다. 불행히도 이것은 클라이언트의 컴퓨터에 설치되어 1.6으로 업데이트되는 기본 JVM입니다 (이 경우 더 빠르거나 빠르지 않을 수도 있음)는 불행하지 않습니다. 대규모 조직에서 일한 사람은 아마도 그 이유를 이해할 것입니다 ...
  • 이 외에도 우리는 이미 메모리 제약 조건을 사용하여 최소한 더 큰 문자열과 바이트 어레이 표현을 캐시하려고 시도하면서 잠재적으로 우아한 솔루션이므로 해결해야 할 것보다 더 많은 문제를 일으킬 수 있습니다.
도움이 되었습니까?

해결책

문제의 일부는 Java 문자열이 UTF -16 형식 인 것일 수 있습니다. 즉 문자 당 두 바이트입니다. 그래서 getBytes() 현재 문자 세트에 따라 각 UTF-16 요소를 하나 또는 두 바이트로 변환하기 위해 많은 작업을 수행하고 있습니다.

사용해 보셨습니까? charsetencoder - 이렇게하면 문자열 인코딩을 더 많이 제어 할 수 있으며 기본값의 일부 오버 헤드를 건너 뛸 수 있습니다. getBytes 구현.

또는 charset을 명시 적으로 지정하려고 시도 했습니까? getBytes, 및 사용 미국-ASCII 캐릭터 세트로?

다른 팁

몇 가지 옵션이 있습니다.

  • 라틴어 -1 문자열이 있다면 문자열에서 숯의 더 높은 바이트를 분할 할 수 있습니다 (Charset도 이것도 생각합니다).
  • 더 많은 경우 여러 코어로 작업을 분할 할 수도 있습니다 (포크 조인 프레임 워크에는 백포트가 1.5로 1.5로 백 포트가되었습니다).
  • 또한 데이터를 StringBuilder로 빌드하여 끝에서 한 번만 바이트 배열로 변환 할 수 있습니다.
  • GC/메모리 사용량을보십시오. 메모리 사용이 너무 많은 GC 중단으로 인해 알고리즘이 느려질 수 있습니다.
  • 모든 시간을 변환하는 것과 동일한 문자열 인 경우 결과를 약한 해쉬 맵으로 캐시 할 수 있습니다.

    또한 GetBytes () 메소드 (SDK를 설치하면 소스를 사용할 수 있음)를 살펴보고 정확히 무엇을하는지 확인하십시오.

    문제는 Java의 모든 방법이 오늘날에도 UTF-8 생산과 메모리를 할당한다는 것입니다. 인코딩 수행자를 얻으려면 사용자 정의 코드를 작성하고 바이트 [] 버퍼를 재사용해야합니다. Colfer는 코드를 생성하거나 간단히 구현을 복사 할 수 있습니다.

    https://github.com/pascaldekloe/colfer/blob/4c6f022c5183c0aebb8bc73e8137f976d31b1083/java/gen/o.java#l414

    라이센스 : CC-BY-SA ~와 함께 속성
    제휴하지 않습니다 StackOverflow
    scroll top