【问题标题】:What is the size of standard output buffer size?标准输出缓冲区大小是多少?
【发布时间】:2018-12-12 02:16:09
【问题描述】:

我正在向标准输出写入大量数据,并且我注意到根据输出控制台,程序执行时间是可变的。例如,该程序在 NetBeans 控制台上比在 Windows cmd 中慢。

所以我认为写入 stdout 会填充缓冲区,并且当该缓冲区已满时写入会阻塞(控制台输出消耗的速度不够快)。

我用 Java 程序重现了这种行为。

这是一个输出数据的程序。

public class Output {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        for (int i = 0; i < 10_000; i++) {
            System.out.println("Awesone Output ");
        }

        System.out.println("Total time : " + (System.currentTimeMillis() - start));
    }

}

这里有一个使用上述程序数据的程序

public class StdoutBlocking {

    public static void main(String[] args) throws IOException, InterruptedException {

        ProcessBuilder processBuilder = new ProcessBuilder("java", "stackoverflowDemo.StdoutBlocking.Output");
        processBuilder.directory(new File("C:/Users/me/Documents/NetBeansProjects/tmp/build/classes"));
        Process process = processBuilder.start();

        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = null;
        String lastLine = null;

        while ((line = reader.readLine()) != null) {
            Thread.sleep(10);
            lastLine = line;
        }
        System.out.println("done : " + lastLine);

    }
}

我启动第二个启动输出并消耗它的输出。 没有睡眠,输出程序真的很快,但很慢。

那么这个缓冲区的大小是多少??

这只是为了我的好奇心,我并没有试图实现特定的目标

【问题讨论】:

标签: java stdout stderr


【解决方案1】:

System.outSystem.err 的默认缓冲区大小为 8192。您可以通过查看其方法的源代码来查看它,例如 println(String)。他们使用具有默认缓冲区大小的BufferedWriter

【讨论】:

  • 我认为您没有查看正确的缓冲区。我认为这是一个操作系统设置我的第一个程序可能是 C、python bash 或其他任何东西。我不太确定是否有人可以确认。
【解决方案2】:

Without sleep the program is really quick with it's very slow. 这与缓冲区大小无关。对于每一行输出(10000 行),您的程序至少休眠 10 毫秒。因此,使用Thread.sleep(10),您的程序至少在 100 秒内什么都不做。这就是为什么 Thread.sleep() 很慢的原因。

关于System.out.println()的性能检查这个问题:Why is System.out.println so slow?

底层操作系统操作(在控制台窗口上显示字符)很慢,因为

1.字节必须发送到控制台应用程序(应该很快)

2.每个字符都必须(通常)使用真正的字体呈现(这很慢,关闭抗锯齿可以提高性能,顺便说一句)

3.显示区域可能需要滚动才能在可见区域添加新行(最佳情况:位块传输操作,最坏情况:重新渲染整个文本区域)

您也可以在 Javadoc 中找到 Process

由于部分原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。

对于 UNIX,您可以查看此链接:https://unix.stackexchange.com/questions/11946/how-big-is-the-pipe-buffer

【讨论】:

  • 在我的例子中有 2 个程序显然我在谈论第一个程序的速度,因为没有睡眠!!!第一个只会被第二个缓慢读取标准输出的第二个减慢。第二个程序是模拟控制台。而且不能与渲染有关,因为在我的测试中,屏幕上几乎没有打印任何内容
  • 要检查打印到屏幕是否引入了缓慢,您可以在第一个程序中将 System.out.println() 替换为打印到文件系统上的文件。
  • 我没有在任何地方打印“很棒的输出”,我只是从第二个程序中使用它。如果我慢慢消耗它,第一个程序会变慢,如果我快速消耗它,它会变得更快。我想知道为什么???我不是想优化任何东西,我想知道为什么消费速度会影响生产速度。这是两个独立的进程,唯一的共同点应该是由操作系统管理的缓冲区,我正在寻找有关它的信息。你真的了解这个现象吗???
猜你喜欢
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 2015-06-07
相关资源
最近更新 更多