PrintStream 有缓冲,但是 flush 不会降低性能,BufferedOutputStream 可以加速性能

PrintStream is buffered, but flush does not degrade performance and BufferedOutputStream speeds up performance

我预计由于 PrintStream 被缓冲,通过在每次 print() 之后添加刷新操作,速度性能应该会显着降低,但它根本没有,如下面的代码片段所示。

此外,将 PrintStream 包裹在 BufferedOutputStream 周围可以提高 10 倍以上的性能——这意味着 PrintStream 没有缓冲。

PrintStream 是否真的没有缓冲,或者它有一个非常小的缓冲区,或者是否有其他解释为什么它不能提供缓冲流所期望的速度提升?

       // PrintStream is buffered but takes 4228ms to complete
    long start = System.currentTimeMillis();
    try (PrintStream ps = new PrintStream(new FileOutputStream("1.txt") ))
    {
        for (int i = 0; i < 1_000_000; i++) {
            ps.print(i + " ");
        }
    }
    long stop = System.currentTimeMillis();
    System.out.println(stop - start);

     // PrintStream is buffered, but with auto-flush takes 4140ms to complete, no degraded speed implying flush did nothing
    start = System.currentTimeMillis();
    try (PrintStream os = new PrintStream(new FileOutputStream("1.txt") ))
    {
        for (int i = 0; i < 1_000_000; i++) {
            os.print(i + " ");
            os.flush();
        }
    }
    stop = System.currentTimeMillis();
    System.out.println(stop - start);
    // PrintStream is buffered explicitly as a BufferedOutputStream and runs quickly: 202ms
    start = System.currentTimeMillis();
    try (PrintStream os = new PrintStream(new BufferedOutputStream(new FileOutputStream("1.txt")) ))
    {
        for (int i = 0; i < 1_000_000; i++) {
            os.print(i + " ");
        }
    }
    stop = System.currentTimeMillis();
    System.out.println(stop - start);

虽然内部是 "buffered",但写入方法会在每个 write() 上将内部缓冲区刷新到基础流。因此,在您的前两个示例中,每个 write() 最终都会命中 FileOutputStream。在您的第三种情况下,您将获得 实际 缓冲,其中写入仅定期命中 FileOutputStream。

如果您使用自己的底层流而不是 FileOutputStream,您会发现前两种情况将导致对您的流进行约 1,000,000 次写入调用,而最后一种情况将导致更少的调用(基于缓冲区尺寸)。