Skip to content

[item63] String '+' 연산 성능은 개선된걸까 #89

@jun108059

Description

@jun108059
  • 질문 1) JDK 6에서 어떤 부분이 개선됐을까요?
  • 질문 2) 이렇게 개선됐는데 왜 아직도 String '+' 연산은 엄청 느릴까요?

질문 1) JDK 6에서 어떤 부분이 개선됐을까요?

366p 마지막 문단
자바 6 이후 문자열 연결 성능을 다방면으로 개선했지만, …

책에는 자바6 이후 문자열 연결 성능을 개선했다고 되어있지만 아무리 찾아봐도 자바5 부터 String ‘+’ operator는 컴파일 시 StringBuilder(또는 StringBuffer)로 변환되도록 변경된 내용 밖에 찾지 못했습니다.

자바6에서 어떤 부분이 개선됐는지 궁금합니다 😭

image

출처 : JDK 5 docs : String

이것마저도 String ‘+’ 연산보다 객체 생성 비용과 메모리 사용을 줄일 수 있었지만, 문제가 해결되지는 않았습니다.

  1. StringBuilder와 String Buffer는 기본적으로 초기 capacity가 16 characters로 설정되고, 이는 사이즈가 작아서 재할당으로 인한 추가 비용이 발생하기 쉽습니다.
  2. loop를 돌 때 StringBuilder 객체가 반복적으로 생성되기 때문에 비효율적입니다.

추가적으로, JDK 9 버전 부터는 이를 개선하기 위해 StringConcatFactory 를 도입했습니다.

JDK8 버전과 JDK 11버전으로 각각 컴파일하여 바이트코드를 분석한 글을 참고하면 아래와 같습니다.

image

출처 : https://jerry92k.tistory.com/50

좌측 JDK8 버전은 반복문(L5) 안에서 NEW java/lang/StringBuilder를 통해 새로운 StringBuilder 객체를 생성하고, JDK11 버전은 StringConcatFatory.makeConcatWithConstants 메서드를 통해 처리하는 것을 알 수 있습니다.

질문 2) 이렇게 개선됐는데 왜 아직도 String '+' 연산은 엄청 느릴까요?

JDK 버전이 올라가면서 String ‘+’ 연산이 개선됐기 때문에 더이상 StringBuilder를 사용하지 않아도 된다는 의견은 어렵지 않게 찾아볼 수 있습니다.

그런데 제가 JDK 18 버전 기준으로 테스트해보니 여전히 큰 성능 차이를 확인할 수 있었습니다.

image

(10번 연산)

image

(1,000번 연산)

image

(50,000번 연산)

1,000번 50,000번 연산은 당연히 느려지겠지만, 적어도 10번 연산에서는 ‘+’ 연산에서도 내부적으로 StringBuilder를 생성해서 활용하기 때문에 성능 차이가 거의 없어야 할 것 같은데.. (실행할 때마다 차이는 있지만) 200배 이상 느린게 이상합니다.

image

(String ‘+’ 연산과 StringBuilder의 Bytecode 비교)

혹시나 하여 ByteCode를 확인해보아도 JDK 9 버전에 추가된 makeConcatWithConstants 메서드로 ‘+’연산을 처리하고 있었습니다.

이유를 아시는 분이 있다면 도와주세요!

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions