JavaSystem.out.print效率

Java System.out.print efficiency

最近几天,在做一些竞争性编程练习时,我找到了一些问题的解决方案,而不是在 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 倍有点奇怪。

我的问题是:有没有办法进一步改进它?

synchronized 在这种情况下不应归咎于关键字。

第一个测试用例比较慢,因为System.out.print会带来频繁极小I/O。

你可以使用BufferedWriter(它的write方法也是同步的)来减少不必要的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);