我应该在循环内部或外部“新建”一个对象吗?

时间:2016-02-29 13:48:27

标签: java performance garbage-collection jvm

在以下代码中比较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()中恢复构建器对象?

2 个答案:

答案 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)。这样当分析器告诉你“这是需要花费这么多时间的东西”时,你可以更容易地优化它。