Java string concatenation and performance analysis

  • 2020-04-01 02:42:37
  • OfStack

Let's say we have a string, and we're going to do a lot of loop splicing on that string, and using "+" gives us the lowest performance. But how bad is this performance? If we also put the StringBuffer StringBuilder or String. The concat () in the performance test, the result? This article will give an answer to these questions!

We will use Per4j to calculate performance, because this tool can give us a complete set of performance metrics, such as minimum, maximum time, standard deviation for statistical time periods, and so on. In the test code, we will perform 20 splice "*" 50,000 tests to get an accurate standard deviation value. Here is the method we will use to concatenate strings:


Concatenation Operator (+)
String concat method  �  concat(String str)
StringBuffer append method  �  append(String str)
StringBuilder append method  �  append(String str)

Finally, we'll look at the bytecode to see how these methods are actually executed. Now, let's start by creating our children's classes. Note that to calculate the performance of each loop, each piece of test code in the code needs to be encapsulated with the Per4J library. First we define the number of iterations


private static  final int  OUTER_ITERATION=20;  
private static final int INNER_ITERATION=50000;  

Next, we'll use the four methods above to implement our test code.


String addTestStr = "";  

String concatTestStr = "";  

StringBuffer concatTestSb = null;  

StringBuilder concatTestSbu = null;  

for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {  

    StopWatch stopWatch = new LoggingStopWatch("StringAddConcat");  

    addTestStr = "";  

    for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)  

    addTestStr += "*";  

    stopWatch.stop();  

}        

for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {  

    StopWatch stopWatch = new LoggingStopWatch("StringConcat");  

    concatTestStr = "";  

    for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)  

    concatTestStr.concat("*");  

    stopWatch.stop();  

}  

for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {  

    StopWatch stopWatch = new LoggingStopWatch("StringBufferConcat");  

    concatTestSb = new StringBuffer();  

    for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)  

    concatTestSb.append("*");  

    stopWatch.stop();  

}  

for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {  

    StopWatch stopWatch = new LoggingStopWatch("StringBuilderConcat");  

    concatTestSbu = new StringBuilder();  

    for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)  

    concatTestSbu.append("*");  

    stopWatch.stop();  

}  


Next, run the program to generate performance metrics. My operating environment was a 64-bit Windown7 operating system, a 32-bit JVM(7-ea) with 4GB of memory, and a dual-core Quad 2.00ghz CPU

The results were perfect as we expected. The only interesting thing is why string.concat is also good. As we all know, String is a constant class (one that doesn't change after initialization), so why concat performs better. The test code for the concat() method should be written as concatTestStr= concatteststr.concat (" * "). To answer this question, we should look at the bytecode that concat decomcompiles. The download package for this article contains all the bytecode, but for now let's look at the code snippet for concat:


46:  new #6; //class java/lang/StringBuilder 
49:  dup 
50:  invokespecial   #7; //Method java/lang/StringBuilder."<init>":()V 
53:  aload_1 
54:  invokevirtual   #8; //Method java/lang/StringBuilder.append: 
         (Ljava/lang/String;)Ljava/lang/StringBuilder; 
57:  ldc #9; //String * 
59:  invokevirtual   #8; //Method java/lang/StringBuilder.append: 
         (Ljava/lang/String;)Ljava/lang/StringBuilder; 
62:  invokevirtual   #10; //Method java/lang/StringBuilder.toString:() 
         Ljava/lang/String; 
65:  astore_1 
66:  iinc    7, 1 
69:  goto    38 

This code is the bytecode of string.concat (). From this code, we can see clearly that the concat() method USES StringBuilder, and concat() should perform as well as StringBuilder, but concate's performance is somewhat affected by the additional operations of creating StringBuilder and doing.append(STR).append(STR).tostring (). So The Times for StringBuilder and String Cancate are 1.8 and 3.3.

Therefore, concat should also be used if we do not want to create a StringBuffer or a StringBuilder instance even when doing the simplest splicing. However, concat should not be used for a large number of string concatenation operations. The result is in the comments of the original article. Because concat will degrade the performance of your program and consume your CPU. Therefore, we should try to use StringBuilder for maximum performance, regardless of thread safety and synchronization.


Related articles: