본문 바로가기

Java

String/StringBuffer/StringBuilder 성능비교

String / StringBuffer / StringBuilder

간단한 성능비교 테스트.

package test;
public class StringTest {
     int test = 99999;

     public static void main(String[] args) {
          StringTest stringTest = new StringTest();
     
          System.out.println("스트링: " + stringTest.stringTest());
          System.out.println("스트링빌더: " + stringTest.stringbuilderTest());
          System.out.println("스트링버퍼: " + stringTest.stringbufferTest());
     }
         
     public long stringTest() {
          String a = "test";
          long start = System.currentTimeMillis();
          for(int i =0; i<test; i++) {
              a+="test";
          }
          long end = System.currentTimeMillis();
          return end-start;

     }
     
     public long stringbuilderTest() {
          StringBuilder sb = new StringBuilder("test");
          long start = System.currentTimeMillis();
          for(int i =0; i<test; i++) {
              sb.append("test");
          }
          long end = System.currentTimeMillis();
          return end-start;
     }
     
     public long stringbufferTest() {
          StringBuffer sb = new StringBuffer("test");
          long start = System.currentTimeMillis();
          for(int i =0; i<test; i++) {
              sb.append("test");
          }
          long end = System.currentTimeMillis();
          return end-start;
     }
}

결과 : 
스트링: 6674
스트링빌더: 3
스트링버퍼: 4

StringBuffer의 append 메소드에 들어가보면 
synchronized 키워드가 붙어 있어 동기화를 지원하는 것을 확인할 수 있다.
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

StringBuilder의 append 메소드 :  동기화를 지원하지 않는 대신 StringBuffer보다 조금 더 빠르다.
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }





String 클래스 뜯어보기 : 

단순 String a에 String b 를 더하기했다.
public class test {
     public class Concat {
         String plus(String a, String b) {
             a += b;
             return a;
         }
     }
}

javap -c 로 해체결과:



즉 a+=b 는
a = new StringBuilder()
.append(a)
.append(b)
.toString();
와 같이 동작함을 알 수 있다.




그럼 세개를 한번에 +하면 어떻게 될까?
package test;
public class test {
    String plus(String a, String b, String c) {
        String d = a+b+c;
        return d;
    }
}

javap -c 로 해체결과:


a+=b와 같이 처음 한 번만 StringBuilder 객체를 생성하고 append()메소드를 사용 후 toString으로 변환해 리턴하는 것을 볼 수 있다.




a+b+c 와 같이 한 번의 연산이 아니라 각각의 줄에서 문자열을 붙이면 어떻게 될까?
public class test {
         String plus(String a, String b) {
             a+=b;
             a+="1";
             a+="2";
             return a;
         }
}


javap -c 로 해체결과:

줄마다 StringBuilder 객체가 각각 생성되어 3번의 객체가 생성됨을 볼 수 있다.

마지막으로 문자열을 붙이는 String의 concat() 메소드에 들어가보니
    public String concat(String str) {
        int olen = str.length();
        if (olen == 0) {
            return this;
        }
        if (coder() == str.coder()) {
            byte[] val = this.value;
            byte[] oval = str.value;
            int len = val.length + oval.length;
            byte[] buf = Arrays.copyOf(val, len);
            System.arraycopy(oval, 0, buf, val.length, oval.length);
            return new String(buf, coder);
        }
        int len = length();
        byte[] buf = StringUTF16.newBytesFor(len + olen);
        getBytes(buf, 0, UTF16);
        str.getBytes(buf, len, UTF16);
        return new String(buf, UTF16);
    }

역시 새로운 String 객체를 생성해 리턴한다.
그러나 직접 해보니 concat()이 + 보다는 조금 더 빠른 것을 확인할 수 있었다.