What is the most commonly used class in java projects?
We use jmap tool from jdk to find the answer.
jmap -histo | head -n 14
Where - java application process id (I have used pid of running tomcat server)
The output of this command is:
num #instances #bytes class name
----------------------------------------------
1: 43101 18737736 [B
2: 61736 10054912 [C
3: 11598 5165024 [I
4: 58901 1413624 java.lang.String
5: 8514 749232 java.lang.reflect.Method
6: 21313 682016 java.util.HashMap$Node
7: 5286 549960 java.lang.Class
8: 7914 483944 [Ljava.lang.Object;
9: 9323 372920 java.util.HashMap$ValueIterator
10: 1814 320184 [Ljava.util.HashMap$Node;
11: 7862 314480 java.lang.ref.Finalizer
As we can see String is one of the common used classes in java projects and takes a lot of memory. The most common operations performed with strings is concatenation.
There are three variants of string concatenation:
1. String a = “Hello ” + “world”;
2. String b = new StringBuffer();
b.append(“Hello ”);
b.append(“world”).toString();
3. String c = “Hello ”.concat(“world”);
Let's look to them closer and try to compare. There are two common possibilities to concatenate strings using '+' sign:
1. String s1 = “STRING_VAL1” + “STRING_VAL2”;
2. String s2 = “STRING_VAL1” + STRING_VARIABLE;
We need to view generated bytecode by javap from jdk to compare them:
javap -c SomeJava.class
For the first expression it looks like this.
Source:
String q = "Hello " + "world";
Bytecode:
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: ldc #3 // String Hello world
2: astore_1
3: return
For the second expression.
Source:
String hello = "Hello ";
String result = hello + "world";
Bytecode:
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: ldc #3 // String Hello
2: astore_1
3: new #4 // class java/lang/StringBuilder
6: dup
7: invokespecial #5 // Method java/lang/StringBuilder."":()V
10: aload_1
11: invokevirtual #6 // Method java/lang/StringBuilder.append
14: ldc #7 // String world
16: invokevirtual #6 // Method java/lang/StringBuilder.append
19: invokevirtual #8 // Method java/lang/StringBuilder.toString
22: astore_2
23: return
If you try to concatenate two or more constant strings then java compiler do this operation in compile time:
String s = “Hello ” + “world” + “...”;
In other cases will be used explicitly or implicitly StringBuilder and String.concat() method. StringBuffer is also possible for multithreading applications, but we examine only first two in bold. Let's decide which of them better
We will create two microbenchmark tests to find out which is better StringBuilder or String.concat:
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class StringOpts {
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void concat_() {
String s1 = "Hello";
String s2 = s1.concat(" world");
}
@Benchmark
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void append_() {
StringBuilder s1 = new StringBuilder("Hello");
String s2 = s1.append(" world").toString();
}
}
When benchmark had been finished we got such result:
# Run complete. Total time: 00:00:12
Benchmark Mode Samples Score Error Units
t.StringOpts.append_ avgt 1 0.007 ± NaN us/op
t.StringOpts.concat_ avgt 1 0.010 ± NaN us/op
Where you can see that StringBuilder.append is faster than String.concat function. When you need concatenate only two strings in some cases you can prefer String.concat because this generates less objects than when you use StringBuilder.
Немає коментарів:
Дописати коментар