String vs StringBuffer vs StringBuilder 성능 테스트 해보기

jy.YOON·2022년 9월 11일
0

자바

목록 보기
1/8
  • String
    -짧은 문자열을 더할 경우에만 사용하자.
    -왠만하면 사용을 지양하자(생성할수록 무한대로 새로운 주소값이 생성되기때문).

  • StringBuffer
    -스레드에 안전한 프로그램 또는 개발중 스레드에 안전을 장담할수 없을때 사용하자

  • StringBuilder
    -스레드에 안전여부와는 전혀관계없는 프로그램 개발시 사용하자.

성능테스트

간단한 성능테스트를 위해 jmh(Java Microbenchmark Harness) 를 사용하였다.

정해진 문자열을 지속적으로 더해서 새로운 문자열을 만드는 테스트 진행

의존성 설정
 <dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.19</version>
  </dependency>
  <dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.19</version>
  </dependency>

jmh 공식 MD 에서는 아래의 구조와 같게 구성할것을 권고하고 있다.

src/jmh 구조에 맞게 구성하자

https://github.com/melix/jmh-gradle-plugin#configuration

package test;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS) //밀리세컨드 단위로 출력
@Fork(value = 2, jvmArgs= {"-Xms4G", "-Xmx4G"})//측정을 한번만 하는것은 벤치마크의 신뢰성에 문제가 있을 수 있다.
                                                // 특정 시점에 시스템이 다른 이유로 갑자기 느려지거나 하는 상황이 있을 수 있기 때문에 최대한 외부 변수의 영향을 배제하기 위해 측정을 2회 실시한다.
//그리고 힙 영역의 공간 부족으로 인한 gc 오버헤드를 최소화 하기 위해 힙 영역의 크기를 4GB 로 설정한다.
public class BenchTest {
    static final String aValue = "abc";
    
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(BenchTest.class.getSimpleName())
                .forks(2)
                .build();

        new Runner(opt).run();
    }

    @Benchmark
    public static String makeString(){
        String a = new String();
        for (int inLoop = 0; inLoop<10000; inLoop++){
            a+=aValue;
        }
        return a;
    }

    @Benchmark
    public static String makeStringBuffer(){
        StringBuffer sf = new StringBuffer();
        for (int inLoop = 0; inLoop<10000; inLoop++){
            sf.append(aValue);
        }
        return sf.toString();
    }

    @Benchmark
    public static String makeStringBuilder(){
        StringBuilder sb = new StringBuilder();
        for (int inLoop = 0; inLoop<10000; inLoop++){
            sb.append(aValue);
        }
        return sb.toString();
    }
}

테스트 결과

스레드를 고려하지 않은 테스트 환경에서는 StringBuilder 가 가장 효율적이라는 것을 확인 할 수 있구만

TMI
WAS나 시스템이 JDK5.0 이상을 사용한다면, 컴파일러에서 자동으로 StringBuilder로 변환해준다.

profile
5 Seconds rule

0개의 댓글

관련 채용 정보