String performance test

I found string plus using StringBuffer but not StringBuilder when I was implementing my simple JVM. So I wrote some test case to test it. But it became using StringBuilder but not StringBuffer. So I guess whether use StringBuffer or StringBuilder is depend on compiler option. Any way I got a performance test result between using StringBuffer and StringBuilder. The result is that using StringBuilder is much faster than using StringBuffer . The time consume ratio between using StringBuilder and StringBuffer is about 2:3 .

 

Here comes my test code.

 

public class StringAddTest implements Runnable {

    static long time1 = 0;
    static long time2 = 0;
    static long time3 = 0;

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new StringAddTest());
        Thread thread2 = new Thread(new StringAddTest());
        Thread thread3 = new Thread(new StringAddTest());
        Thread thread4 = new Thread(new StringAddTest());
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

        thread1.join();
        thread2.join();
        thread3.join();
        thread4.join();

        System.out.println("stringAdd1 spent " + time1 + " ms");
        System.out.println("stringAdd2 spent " + time2 + " ms");
        System.out.println("stringAdd3 spent " + time3 + " ms");
    }

    public static void stringAdd1(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = a + b + i;
        }
        long spent = System.currentTimeMillis() - start;
        time1 += spent;
        System.out.println("TestStringAdd1 spent " + spent + "ms");
    }

    public static void stringAdd2(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = new StringBuilder().append(a).append(b).append(i).toString();
        }
        long spent = System.currentTimeMillis() - start;
        time2 += spent;
        System.out.println("TestStringAdd2 spent " + spent + "ms");
    }

    public static void stringAdd3(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = new StringBuffer().append(a).append(b).append(i).toString();
        }
        long spent = System.currentTimeMillis() - start;
        time3 += spent;
        System.out.println("TestStringAdd3 spent " + spent + "ms");
    }
    
    public static void StringAddx()
    {
        String orignal = "Original";
        orignal += "What";
    }

    public void run() {
        int n = 1000 * 1000;
        for (int i = 0; i < 10; i++) {
            stringAdd1(n);
            stringAdd2(n);
            stringAdd3(n);
            
            stringAdd3(n);
            stringAdd2(n);
            stringAdd1(n);
            
            stringAdd2(n);
            stringAdd3(n);
            stringAdd1(n);
        }
    }
}

 I ran it for several times. The results are closed to each other. One test result on my machine is

DirectStringAdd      spent 138057 ms
StringBuilderAppend  spent 152647 ms
StringBufferAppend   spent 256578 ms
 

From the result can see that use direct string plus is a little faster than use StringBuilder. I was trying to figure it out by analyze the binary code generated and add two more test case. Here comes my new test code.

public class StringAddTest implements Runnable {

    static long timeDirectStringAdd = 0;
    static long timeStringBuilderAppend = 0;
    static long timeStringBufferAppend = 0;
    static long timeStringBuilderAppend2 = 0;
    static long timeStringBufferAppend2 = 0;
    
    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new StringAddTest());
        Thread thread2 = new Thread(new StringAddTest());
        Thread thread3 = new Thread(new StringAddTest());
        Thread thread4 = new Thread(new StringAddTest());
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

        thread1.join();
        thread2.join();
        thread3.join();
        thread4.join();

        System.out.println("DirectStringAdd      spent " + timeDirectStringAdd + " ms");
        System.out.println("StringBuilderAppend  spent " + timeStringBuilderAppend + " ms");
        System.out.println("StringBufferAppend   spent " + timeStringBufferAppend + " ms");
        System.out.println("StringBuilderAppend2 spent " + timeStringBuilderAppend2 + " ms");
        System.out.println("StringBufferAppend2  spent " + timeStringBufferAppend2 + " ms");
    }

    public static void directStringAdd(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = a + b + i;
        }
        long spent = System.currentTimeMillis() - start;
        timeDirectStringAdd += spent;
        System.out.println("DirectStringAdd      spent " + spent + "ms");
    }

    public static void stringBuilderAppend(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = new StringBuilder().append(a).append(b).append(i).toString();
        }
        long spent = System.currentTimeMillis() - start;
        timeStringBuilderAppend += spent;
        System.out.println("StringBufferAppend   spent " + spent + "ms");
    }

    public static void stringBuilderAppend2(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = new StringBuilder(a).append(b).append(i).toString();
        }
        long spent = System.currentTimeMillis() - start;
        timeStringBuilderAppend2 += spent;
        System.out.println("StringBufferAppend2  spent " + spent + "ms");
    }
    
    public static void stringBufferAppend(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = new StringBuffer().append(a).append(b).append(i).toString();
        }
        long spent = System.currentTimeMillis() - start;
        timeStringBufferAppend += spent;
        System.out.println("StringBuilderAppend  spent " + spent + "ms");
    }
    
    public static void stringBufferAppend2(int n) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String a = "First";
            String b = "Second";
            String x = new StringBuffer(a).append(b).append(i).toString();
        }
        long spent = System.currentTimeMillis() - start;
        timeStringBufferAppend2 += spent;
        System.out.println("StringBuilderAppend2 spent " + spent + "ms");
    }
    
    
    public static void StringAddx()
    {
        String orignal = "Original";
        orignal += "What";
    }

    public void run() {
        int n = 1000 * 1000;
        for (int i = 0; i < 5; i++) {
            directStringAdd(n);
            stringBuilderAppend(n);
            stringBuilderAppend2(n);
            stringBufferAppend2(n);
            stringBufferAppend(n);
            
            stringBufferAppend(n);
            stringBufferAppend2(n);
            stringBuilderAppend2(n);
            stringBuilderAppend(n);
            directStringAdd(n);
            
            stringBuilderAppend(n);
            stringBuilderAppend2(n);
            stringBufferAppend2(n);
            stringBufferAppend(n);
            directStringAdd(n);
        }
    }
}
 

And the test result is like

DirectStringAdd      spent 67991 ms
StringBuilderAppend  spent 76464 ms
StringBufferAppend   spent 120135 ms
StringBuilderAppend2 spent 65543 ms
StringBufferAppend2  spent 118215 ms

 I picked up the binary code snippet from the test case and list it in following table.

1:
String x = a + b + i; 
    17  new java.lang.StringBuilder [56]
    20  dup
    21  aload 4 [a]
    23  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [106]
    26  invokespecial java.lang.StringBuilder(java.lang.String) [60]

2:
String x = new StringBuilder().append(a).append(b).append(i).toString();
    17  new java.lang.StringBuilder [56]
    20  dup
    21  invokespecial java.lang.StringBuilder() [125]
    24  aload 4 [a]
    26  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [69]
 
3:
String x = new StringBuilder(a).append(b).append(i).toString();
    17  new java.lang.StringBuilder [56]
    20  dup
    21  aload 4 [a]
    23  invokespecial java.lang.StringBuilder(java.lang.String) [60]

1: String.valueOf(String) only cost a little. It only need return the reference.

2: append need a string copy. It cost quite much.

3: it even don't need valueOf. So it is the fastest.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值