Skip to content

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

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 메서드로 ‘+’연산을 처리하고 있었습니다.

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions