Java System.out.print效率

时间:2018-08-23 16:07:45

标签: java performance io stringbuilder

最近几天,我通过一些竞争性编程练习,找到了一些问题的解决方案,他们不是通过在for循环中在控制台中打印文本,而是通过附加一个StringBuilder彼此之间的文本。首先,我很困惑,但是我尝试了一下,并制定了一些基准。

首次测试:这是在屏幕上打印内容的经典方法:

class TestClass {

    public static void main(String args[]) throws Exception {
        double startTime = System.currentTimeMillis();

        //code
        for (int i = 0; i < 1000000; i++) {
            System.out.print("test");
        }
        //code
        double endTime = System.currentTimeMillis();
        String result = String.format("for loop: %.5f", (endTime-startTime) / 1000);
        System.out.print("\n"+result);
    }

}

第二项测试:这是StringBuilder的增强版本:

class TestClass {

    public static void main(String args[]) throws Exception {
        double startTime = System.currentTimeMillis();

        //code
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1000000; i++) {
            sb.append("test");
        }
        System.out.print(sb);
        //code
        double endTime = System.currentTimeMillis();
        String result = String.format("for loop: %.5f", (endTime - startTime) / 1000);
        System.out.print("\n" + result);
    }

}

多次运行测试后(使用Intel i5 6500四核3.2 GHZ CPU,Win 10运行它们),结果如下:

first test(for loop): 4,25s  
second test(StringBuilder): 0.23s

结果并不意外,因为out.print已同步,因此每次调用它都会增加一些开销。但是慢将近20倍有点奇怪。

我的问题是:有没有办法进一步改善这一点?

1 个答案:

答案 0 :(得分:1)

在这种情况下,不应责怪

synchronized关键字。

第一个测试用例很慢,因为System.out.print将带来频繁的最小I / O。

您可以使用BufferedWriter(它的写入方法也是同步的)来减少不必要的I / O:

BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));

//code
for (int i = 0; i < 1000000; i++) {
    log.write("test");
}

for loop: 0.21200

而且,StringBuilder在内部使用byte[]进行字符存储。通过将旧值复制到新的byte[]中来保持附加内容时,此字节数组将增大。

赋予它足够大的容量可能会带来一些效率:

StringBuilder sb = new StringBuilder(1000000 * 10);