StringBuilder vs. .concat vs. “+” Operator relative performance different in eclipse than command line?

后端 未结 2 673
南笙
南笙 2020-12-06 12:17

I was reading about how when possible the java compiler will compile strings concatenated with the \"+\" operator into instances of StringBuilder, and how this makes it bett

相关标签:
2条回答
  • 2020-12-06 12:20

    On Oracle JDK 1.7 (javac 1.7.0_17), the "+" operator is still implemented using StringBuilder, as shown by running javap -c on the class to get the bytecode (only showing the loops here):

    public static void plusOperator();
    Code:
    
      16: iload         4
      18: ldc           #10                 // int 100000000
      20: if_icmpge     53
      23: new           #11                 // class java/lang/StringBuilder
      26: dup           
      27: invokespecial #12                 // Method java/lang/StringBuilder."<init>":()V
      30: aload_0       
      31: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      34: aload_1       
      35: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      38: aload_2       
      39: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      42: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      45: astore        5
      47: iinc          4, 1
      50: goto          16
    
    
    public static void stringBuilder();
    Code:
    
      16: iload         4
      18: ldc           #10                 // int 100000000
      20: if_icmpge     50
      23: new           #11                 // class java/lang/StringBuilder
      26: dup           
      27: invokespecial #12                 // Method java/lang/StringBuilder."<init>":()V
      30: aload_0       
      31: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      34: aload_1       
      35: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      38: aload_2       
      39: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      42: astore        5
      44: iinc          4, 1
      47: goto          16
    

    The only difference between these two is that the version with "+" converts the StringBuilder to a String within the loop.

    So the question becomes: why does your test show such different results for the same code. Or more completely, why is this not a valid micro-benchmark. Here are some possible reasons:

    • You're counting wall-clock time. This means that you're actually measuring everything that the JVM is doing while running your test. Which includes garbage collection (which is important because you're creating a lot of garbage). You can mitigate this by getting the thread CPU time.
    • You don't verify when or if HotSpot is compiling the methods. This is why you should do a warmup phase before any micro-benchmarks: basically, run your main() multiple times, before you run your actual test.
    0 讨论(0)
  • 2020-12-06 12:33

    Try to place StringBuilder toBuild = new StringBuilder() above the loop. The same with String toPrint and do += for string and you will see the difference.
    Don't create new String and StringBuilder in the loop.

    0 讨论(0)
提交回复
热议问题