오늘은 Naver Arcus Client 오픈소스 프로젝트에 대한 성능 분석 결과를 공유하고자 합니다. 특히 문자열 연결(String Concatenation) 부분에 초점을 맞추어 분석을 진행했습니다.
1. 배경
Naver에 대한 관심으로 시작된 이 분석은 오픈소스 프로젝트를 탐색하는 과정에서 시작되었습니다. 코드를 살펴보던 중, MapDelete와 MapGet 클래스의 getSpaceSeparatedMkeys() 메소드에서 복잡한 for 루프와 StringBuilder를 사용하는 것이 눈에 띄었습니다. 왜 이렇게 복잡한 방식을 사용했는지 궁금해졌고, 이를 간단한 String.join()으로 리팩토링해보기로 결정했습니다.
2. 분석 대상
분석 대상은 MapDelete와 MapGet 클래스의 getSpaceSeparatedMkeys() 메소드였습니다. 이 메소드는 키-값 쌍을 문자열로 변환하는 역할을 합니다.
3. 원본 코드와 리팩토링된 코드
원본 코드 (StringBuilder 사용)
public String getSpaceSeparatedMkeys() {
if (spaceSeparatedKeys != null) {
return spaceSeparatedKeys;
}
StringBuilder sb = new StringBuilder();
int numkeys = mkeyList.size();
for (int i = 0; i < numkeys; i++) {
sb.append(mkeyList.get(i));
if ((i + 1) < numkeys) {
sb.append(keySeparator);
}
}
spaceSeparatedKeys = sb.toString();
return spaceSeparatedKeys;
}
리팩토링된 코드 (String.join() 사용)
public String refactoredMethod() {
if (spaceSeparatedKeys != null) {
return spaceSeparatedKeys;
}
spaceSeparatedKeys = String.join(keySeparator, mkeyList);
return spaceSeparatedKeys;
}
리팩토링된 코드 (StringJoiner 사용)
public String stringJoinerMethod(List<String> testList, String separator) {
StringJoiner joiner = new StringJoiner(separator);
for (String element : testList) {
joiner.add(element);
}
return joiner.toString();
}
4. 성능 테스트
성능 테스트를 위해 JMH(Java Microbenchmark Harness)를 사용했습니다. Naver Arcus Client의 실제 사용 범위에 맞춰 4,000, 5,000, 10,000, 50,000개의 요소에 대해 벤치마크를 실행했습니다.
5. 테스트 결과
아래는 각 방법별 평균 실행 시간(나노초)입니다
6. 분석
- 모든 데이터셋 크기에서 StringBuilder가 가장 좋은 성능을 보였습니다.
- String.join()은 StringBuilder에 근접한 성능을 보였으며, 특히 작은 크기의 데이터셋에서는 거의 비슷한 성능을 나타냈습니다.
- StringJoiner는 예상과 달리 세 방법 중 가장 낮은 성능을 보였습니다. 특히 데이터셋의 크기가 커질수록 다른 두 방법과의 성능 차이가 더 벌어졌습니다. (StringJoiner는 for문으로 연결 시 속도가 저하 된다고 합니다.)
- 데이터셋 크기가 증가할수록 세 방법 간의 성능 차이가 더욱 두드러졌습니다.
7. 결론
- Naver Arcus Client의 사용 범위(4,000-50,000개)에서는 StringBuilder를 사용하는 것이 성능 면에서 가장 유리합니다.
- String.join()은 StringBuilder와 비교적 근접한 성능을 보이면서도 코드가 간결하므로, 성능이 약간 덜 중요한 경우에는 사용을 고려해볼 수 있습니다.
- 예상과 달리 StringJoiner의 성능이 가장 낮았으므로, 대규모 데이터셋에서는 사용을 피하는 것이 좋습니다.
- Naver Arcus Client의 경우, 다음과 같은 접근을 권장합니다:
- 성능이 매우 중요한 부분: StringBuilder 사용
- 코드 가독성이 더 중요한 부분: String.join() 사용 (성능 손실이 크지 않은 경우)
코드의 가독성만을 고려해 접근했던 분석이었지만 실제 성능 테스트를 통해 새로운 통찰을 얻을 수 있었습니다. StringBuilder가 대규모 데이터 셋에서 압도적으로 뛰어난 성능을 보인다는 사실은, 표면적으로 코드의 복잡성을 보고 판단하는 것을 조심해야 한다는 것과 어떤 기술을 선택할 때 성능 테스트의 중요성을 일깨워 주었습니다. 이번 경험을 통해 오픈소스와 프로그래밍에 대한 이해가 더욱 깊어졌으며, 코드 분석에 있어 다각적 접근의 필요성을 체감할 수 있었습니다.
'OpenSource' 카테고리의 다른 글
오픈소스 - Naver scavenger - 로깅 문자열 연결 vs 파라미터 치환 (1) | 2024.11.23 |
---|---|
오픈소스 - 표준프레임워크 기여하기 - logging-log4j2, readme (2) | 2024.11.13 |
오픈소스 - hibernate-orm 기여하기 - testing orm (0) | 2024.11.08 |
오픈소스 - 스프링프레임워크 기여하기 - WebSocketHandlerMapping (0) | 2024.11.07 |
2024 OSSCA 표준 프레임워크 및 MSA, 쿠버네티스 환경 살펴보기 (3) | 2024.10.02 |