通常toString重写会优先使用StringBuffer来进行append,但jdk1.7以上,已经做了充分优化,让我们通过实际测试数据,来对比下是否String的concat(+)是否真的会差呢?
测试环境,JUnit和JMH(JMH相关资料请自行百度),相关Maven依赖如下:
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.openjdk.jmhgroupId>
<artifactId>jmh-generator-annprocessartifactId>
<version>1.12version>
<scope>providedscope>
dependency>
首先基于通用的System的当前时间进行测试,测试代码如下:
public String toStringConcat() {
return "ToStringTest{" +
"att1='" + att1 + '\'' +
", att2='" + att2 + '\'' +
", att3='" + att3 + '\'' +
'}';
}
public String toStringSb() {
final StringBuffer sb = new StringBuffer("ToStringTest{");
sb.append("att1='").append(att1).append('\'');
sb.append(", att2='").append(att2).append('\'');
sb.append(", att3='").append(att3).append('\'');
sb.append('}');
return sb.toString();
}
public String toStringStringBuilder() {
final StringBuilder sb = new StringBuilder("ToStringTest{");
sb.append("att1='").append(att1).append('\'');
sb.append(", att2='").append(att2).append('\'');
sb.append(", att3='").append(att3).append('\'');
sb.append('}');
return sb.toString();
}
下面通过JUnit进行允许测试
/**
* 功能说明 :junit测试try性能
* @author Zain 2016/7/14 10:28
* @return result
* @params
*/
@Test
public void simpleTest() throws Exception {
System.out.println("toStringConcat ---------------------------------");
long startTime = System.currentTimeMillis();
try {
for (int i = 0; i < 1000000; i++) {
toStringConcat();
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("toStringConcat " + (endTime - startTime) + " milliseconds");
System.out.println("toStringSb ---------------------------------");
startTime = System.currentTimeMillis();
try {
for (int i = 0; i < 1000000; i++) {
toStringSb();
}
} catch (Exception e) {
e.printStackTrace();
}
endTime = System.currentTimeMillis();
System.out.println("toStringSb " + (endTime - startTime) + " milliseconds");
System.out.println("toStringStringBuilder ---------------------------------");
startTime = System.currentTimeMillis();
try {
for (int i = 0; i < 1000000; i++) {
toStringStringBuilder();
}
} catch (Exception e) {
e.printStackTrace();
}
endTime = System.currentTimeMillis();
System.out.println("toStringStringBuilder " + (endTime - startTime) + " milliseconds");
}
代码很简单,直接给测试结果:
toStringConcat ---------------------------------
toStringConcat 80 milliseconds
toStringSb ---------------------------------
toStringSb 374 milliseconds
toStringStringBuilder ---------------------------------
toStringStringBuilder 146 milliseconds
当然,每次运行结果可能不一样,由于JVM“热身”的原因,我们调整下运行顺序,将String的concat放到最后,运行结果如下:
toStringSb ---------------------------------
toStringSb 370 milliseconds
toStringStringBuilder ---------------------------------
toStringStringBuilder 235 milliseconds
toStringConcat ---------------------------------
toStringConcat 69 milliseconds
这里已经可以看到曾经邪恶的+,貌似更加高效,下面用JMH测试进一步有效验证。
测试代码如下:
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public void toStringConcatBenchmark() {
int j = 3;
try {
for (int i = 0; i < 1000000; i++) {
toStringConcat();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public void toStringSbBenchmark() {
int j = 3;
for (int i = 0; i < 1000000; i++) {
try {
toStringSb();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public void toStringStringBuilderBenchmark() {
int j = 3;
for (int i = 0; i < 1000000; i++) {
try {
toStringStringBuilder();
} catch (Exception e) {
e.printStackTrace();
}
}
}
JMH允许代码:
/**
* 功能说明 :JMH测试try性能
* @author Zain 2016/7/14 10:29
* @return result
* @params
*/
@Test
public void benchmarkTest() throws Exception {
Options opt = new OptionsBuilder()
.include(ToStringTest.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
运行结果:
# Run complete. Total time: 00:02:10
第一次
Benchmark Mode Cnt Score Error Units
ToStringTest.toStringConcatBenchmark thrpt 20 0.029 ± 0.001 ops/ms
ToStringTest.toStringSbBenchmark thrpt 20 0.006 ± 0.001 ops/ms
ToStringTest.toStringStringBuilderBenchmark thrpt 20 0.008 ± 0.001 ops/ms
第二次
Benchmark Mode Cnt Score Error Units
ToStringTest.toStringConcatBenchmark thrpt 20 0.029 ± 0.001 ops/ms
ToStringTest.toStringSbBenchmark thrpt 20 0.006 ± 0.001 ops/ms
ToStringTest.toStringStringBuilderBenchmark thrpt 20 0.007 ± 0.001 ops/ms
综上,还是傻傻的什么都不想,用最原始的方式吧,哈哈...