티스토리 뷰

Java & Kotlin

[Java] 중복 문자열 제거를 통한 메모리 절약을 위한 -XX:+UseStringDeduplication GC 옵션

망나니개발자 2024. 1. 23. 10:00
반응형

아래의 내용은 DZone의 포스팅을 바탕으로 참고하여 정리한 내용입니다.

 

 

 

1. 중복 문자열 제거를 통한 메모리 절약을 위한
-XX:+UseStringDeduplication GC 옵션 


[ 중복 문자열의 개념과 예시 ]

중복 문자열이란?

JDK 개발팀의 조사에 따르면 다음과 같은 자바 애플리케이션의 특징이 있다고 한다.

  • 프로세스의 25%는 문자열임
  • 그 중 13.5%는 중복 문자열임
  • 평균 문자열의 길이는 45자임

 

 

중복된 문자열이라 함은 다음과 같이 동일한 내용을 갖지만 별도로 저장된 객체를 의미한다. 둘을 equals로 비교하면 true가 나오지만, ==으로 비교하면 false가 나온다. 이러한 문자열을 우리는 중복 문자열이라고 한다.

String string1 = new String("MangKyu");
String string2 = new String("MangKyu");

 

 

우리는 중복된 문자열에 의해 평균적으로 13.5%의 메모리를 낭비하고 있는 것이다. 참고로 낭비중인 실제 메모리를 측정하려면 HeapHero와 같은 도구를 사용할 수 있다.

 

 

 

중복 문자열 생성 예시1

string literal 패턴을 사용하여 public static final String으로 생성하면 메모리를 최적화할 수 있다. 하지만 이를 적용하지 않고 매번 새롭게 만드는 경우가 있다.

public static final String MANGKYU = "MangKyu";

String string1 = MANGKYU;
String string2 = MANGKYU;

 

 

 

중복 문자열 생성 예시2

뱅킹/전자상거래 애플리케이션을 구축하는 경우 모든 거래 기록에 대한 통화(예: 'USD', 'EUR', 'INR', ....)를 저장하고 있다고 하자. 모든 거래 레코드에는 통화가 있으므로 애플리케이션은 데이터베이스에서 읽은 모든 거래 레코드에 대해 'USD' 문자열 객체를 생성하게 된다. 이 고객에게 수천 건의 거래가 있는 경우, 이 한 고객을 위해 메모리에 수천 개의 중복된 'USD' 문자열 객체를 생성하는 것이다.

마찬가지로 애플리케이션이 데이터베이스에서 여러 열(고객 이름, 주소, 주, 국가, 계좌 번호, ID, .....)을 여러 번 읽을 수도 있고, 그 중에는 중복되는 항목이 있을 수 있다. 애플리케이션은 외부 애플리케이션과 함께 JSON과 같은 데이터를 읽고 쓰며, 많은 문자열을 조작한다. 이러한 모든 작업은 중복 문자열을 생성할 수 있다.

이 문제는 1990년대 중반부터 JDK 팀에서 오랫동안 인식해 왔으며, 지금까지 여러 가지 해결책을 제시해 왔다. 그리고 가장 최근에 추가된 해결책 중 하나가 '- XX:+UseStringDeduplication'이다.

 

 

 

[ -XX:+UseStringDeduplication GC 옵션 ]

-XX:+UseStringDeduplication JVM 옵션은 중복 문자열을 제거하기 위한 최소한의 노력이라고 볼 수 있다.

애플리케이션 시작 시 해당 인수를 전달하면, JVM은 가비지 컬렉션 프로세스의 일부로 중복 문자열을 제거하려고 시도한다. 가비지 컬렉션 프로세스 중에 JVM은 메모리의 모든 객체를 검사하므로 이 프로세스의 일부로 객체 중 중복 문자열을 식별하여 제거하려고 시도한다.

'-XX:+UseStringDeduplication' 옵션만 추가한다고 13.5%의 메모리를 즉시 절약할 수 있는 것은 아니다. 해당 옵션에는 몇 가지 문제점이 있기 때문이다.

  1. G1 GC 알고리즘에서만 적용 가능하다
  2. Long-Lived 객체에만 적용된다
  3. 3번의 GC에서 살아남아야 대상이 되며, StringDeduplicationAgeThreshold 옵션으로 변경 가능하다
  4. GC 일시 중지 시간(Pause Time)에 영향을 줄 수 있다.
  5. 중복 문자열 객체 자체를 제거하는 것이 아니라, 내부의 char[]만 Replace된다.
  6. Java 8 Update 20에서만 적용 가능하다.
  7. XX:+PrintStringDeduplicationStatistics 옵션을 통해 실행에 걸린 시간, 제거된 중복 문자열의 양, 절감된 비용 등의 통계를 볼 수 있다.

 

 

해당 옵션을 사용한다고 하여 중복 문자열 객체 자체를 제거하는 것은 아니다. 그저 String 객체 내부의 char[]만 대체할 뿐이다. 따라서 중복 문자열 객체를 제거하는 것은 개념적으로 다음과 같이 값 필드를 재할당하는 것에 불과하다.

String.value = anotherString.value

 

 

각 문자열 객체는 최소 24바이트를 차지한다(문자열 객체의 정확한 크기는 JVM 구성에 따라 다르지만 24바이트는 최소값입니다). 따라서 이 기능은 짧은 중복 문자열이 많은 경우 메모리 절약이 덜 할 것이다.

 

 

 

 

 

아래의 내용은 DZone의 포스팅을 바탕으로 참고하여 정리한 내용입니다.

 

 

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함