在以下代码中比较test1()
和test2()
:
class Test{
//max value is a large number
int max_value = 100*1000;
public void test1(){
for(int i=0; i<max_value;){
StringBuilder builder = new StringBuilder();
builder.append("String value");
builder.append("append our value much time so will consume many memory");
}
}
public void test2(){
StringBuilder builder = new StringBuilder();
for(int i=0; i<max_value;i++){
builder.append("String value");
builder.append("append our value much time so will consume many memory");
builder.setLength(0);
}
}
}
哪种方法对我们的计划更好?我认为它是test2()
,但在我的项目中,当我使用test2()
之类的代码时,我的程序执行的时间是test1()
的两倍;为什么是这样?
通常test1()
会创建比test2()
更多的对象,因此test1()
会使用更多内存吗?对于垃圾收集,如何在test1()
中恢复构建器对象?
答案 0 :(得分:2)
Microbenchmark在测试前对JVM的状态有很大影响。
如果要测试你的表现,你会一个接一个地运行这两个代码,这会对结果产生很大的影响。
所以这是不同的召唤
test1();
test2();
或
test2();
test1();
因为在test1
中你使用了整个可用内存,而test2
需要运行垃圾收集器。
对于setLength
的内部实现,最好只考虑性能问题来使用第二个实现(test2
)。
请记住,表演并非都是。更改StringBuilder
的长度并不直观,因此从程序员的角度来看,很容易误解第二个实现。 通常,代码更具可读性优于代码更高效的代码。
答案 1 :(得分:0)
JVM对lots of small objects非常好。这是test1
中的内容。
在test2
中,VM可以执行的任何优化都会被丢弃,因为它必须将StringBuilder
中的后备数组归零。
但这不是故事的结尾。微观基准很难做到,结果不会在每个平台上都是正确的。因此,不要过于担心它们,而是编写可读代码(IMO test1
)。这样当分析器告诉你“这是需要花费这么多时间的东西”时,你可以更容易地优化它。