책/자바 성능 튜닝이야기
String, StringBuilder, StringBuffer 성능 비교
유당불내증이 있는 개발자
2025. 3. 20. 19:29
JSCODE 자바스터디 2주차 공부 중 실습
String, StringBuilder, StringBuffer
지난번정리
https://bocho-developer.tistory.com/16
String은 불변클래스로 문자열 연산 시 기존 문자열을 수정하는 것이 아니라 새로운 인스턴스를 생성하여 힙 영역에 저장된다.
이런 작업이 반복 수행되면서 메모리를 많이 사용하게 되고 응답 속도에도 많은 영향을 끼치게 된다.
StringBuilder는 동기화 되어있지 않아 싱글스레드 환경에서 사용
StringBuffer는 메소드 내부에 synchronized 키워드 설정이 되어있어 멀티스레드 환경에서 안전하다.
성능 테스트

private static void stringTest() {
long startTime = System.currentTimeMillis();
long startMemory = getMemoryUsage();
String str = "";
for (int i = 0; i < 100000; i++) {
str += "abcd";
str += "efgh";
str += "ijkl";
str += "mnop";
}
long endTime = System.currentTimeMillis();
long endMemory = getMemoryUsage();
System.out.println("string 연산 실행 시간: " + (endTime - startTime) + "ms");
System.out.println("메모리 사용: " + ((endMemory - startMemory) / (1024.0 * 1024.0)) + " MB");
System.out.println();
}
private static void stringBufferTest() {
long startTime = System.currentTimeMillis();
long startMemory = getMemoryUsage();
StringBuffer stringBuffer = new StringBuffer("");
for (int i = 0; i < 100000; i++) {
stringBuffer.append("abcd");
stringBuffer.append("efgh");
stringBuffer.append("ijkl");
stringBuffer.append("mnop");
}
long endTime = System.currentTimeMillis();
long endMemory = getMemoryUsage();
System.out.println("stringBuffer 실행 시간: " + (endTime - startTime) + "ms");
System.out.println("메모리 사용: " + ((endMemory - startMemory) / (1024.0 * 1024.0)) + " MB");
System.out.println();
}
private static void stringBuilderTest() {
long startTime = System.currentTimeMillis();
long startMemory = getMemoryUsage();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 100000; i++) {
stringBuilder.append("abcd");
stringBuilder.append("efgh");
stringBuilder.append("ijkl");
stringBuilder.append("mnop");
}
long endTime = System.currentTimeMillis();
long endMemory = getMemoryUsage();
System.out.println("stringBuilder 실행 시간: " + (endTime - startTime) + "ms");
System.out.println("메모리 사용: " + ((endMemory - startMemory) / (1024.0 * 1024.0)) + " MB");
}
private static long getMemoryUsage() {
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
}
세가지 메서드다 테스트 방식은 비슷하다.
성능을 측정하기 위해 10만번의 루프를 돌며 각각 소요시간과 메모리 사용량을 측정
테스트 결과

String 연산 시 약 14초가 소요되었고 메모리 사용량도 String 연산과 StringBuilder 와 Buffer에 비하면 차이가 크다.
생각했던 거보다 꽤나 큰 차이를 보인다.
그러나 StringBuilder와 StringBuffer는 실행시간과 메모리 사용량이에서 큰 차이가 보이지는 않았다.
자바 성능 튜닝 이야기 - 조영호 참고
StringBuffer는 클래스의 static으로 선언한 문자열을 변경하거나, singleton으로 선언된 클래스에 선언된 문자열일 경우에 사용해야한다.
StringBuilder의 경우 메서드 내에 변수를 선언했다면 해당 변수는 메서드 내에서만 살아있으므로 StringBuilder를 사용하면 된다.