【问题标题】:Java: What's the reason behind System.out.println() being that slow?Java: System.out.println() 这么慢的原因是什么?
【发布时间】:2010-10-31 07:19:00
【问题描述】:

对于可以在文本编辑器中完成的小型逻辑程序,我使用经典的 System.out.println() 进行跟踪。

我想你们都知道在大量迭代中使用它是多么令人沮丧。为什么这么慢?背后的原因是什么?

【问题讨论】:

    标签: java performance console stdout


    【解决方案1】:

    这与 JVM 无关。将文本打印到屏幕上简单地涉及操作系统在绘制字母,尤其是滚动方面的大量工作。如果将 System.out 重定向到一个文件,它会快得多。

    【讨论】:

    • +1 表示“绘制字母,尤其是滚动”。谢谢
    • 因此取决于终端的速度。我曾经使用过具有透明度和其他令人眼花缭乱的东西的终端。它看起来不错,但性能很差,切换到另一个终端解决了这些问题。
    • 在 Linux 上,你可以尝试 echo bigfile.txt 然后重定向它 echo bigfile.txt > anotherfile.txt 看看有什么不同。
    【解决方案2】:

    这非常依赖于操作系统。例如,在 Windows 中,写入控制台是一个阻塞操作,而且速度也很慢,因此向控制台写入大量数据会减慢(或阻塞)您的应用程序。在 unix 类型的操作系统中,对控制台的写入是缓冲的,因此您的应用可以继续畅通无阻,并且控制台会尽可能地赶上。

    【讨论】:

      【解决方案3】:

      是的,写入控制台会产生大量开销。远远大于写入文件或套接字所需的量。此外,如果有大量线程,它们都在同一个锁上竞争。我建议使用 System.out.println 以外的东西来跟踪。

      【讨论】:

        【解决方案4】:

        这与 Java 和 JVM 无关,而是与控制台终端有关。在大多数操作系统中,我知道在控制台输出中写入速度很慢。

        【讨论】:

          【解决方案5】:

          缓冲有很大帮助。试试这个:

          System.setOut( new PrintStream(new BufferedOutputStream(System.out)) );
          

          但请注意:您不会看到输出逐渐出现,而是一瞬间。这很好,但是如果您将它用于调试,并且程序在终止之前崩溃,在某些情况下,您可能不会在崩溃之前看到打印的文本。 这是因为缓冲区在崩溃之前没有被刷新。它被打印出来了,但它仍然在缓冲区中,并没有出现在你可以看到它的控制台上。我记得这发生在我身上,在一个令人费解的调试会话中。最好偶尔显式刷新,以确保您看到它:

          System.out.flush();
          

          【讨论】:

            【解决方案6】:

            有些终端比其他终端快。即使在一个操作系统中,这也可能会有所不同。

            【讨论】:

              【解决方案7】:

              这可能看起来并没有直接回答您的问题,但我的建议是永远不要使用 System.out 进行跟踪(如果您指的是一种调试,只是为了查看您的应用程序的进步)

              System.out 用于调试的问题有几个:

              • 一旦应用程序结束,当您关闭控制台时,您将丢失日志

              • 一旦您的应用程序正常运行(或评论它们),您就必须删除这些语句。稍后如果您想重新激活它们,您将不得不再次取消评论/评论......乏味

              我建议改用 log4j 并“监视”日志文件,或者使用 tail 命令 - 还有一个 Tail for Windows - 或者使用像 LogWatcher 这样的 Eclipse 插件。

              【讨论】:

                【解决方案8】:

                我注意到关于写入终端的一件有趣的事情(至少在 Windows 中)。如果窗口最小化,它实际上运行得更快吗?这绝对与 Michael Borgwardt 关于绘图和滚动的回答密切相关。确实,如果您的日志记录足以注意到速度变慢,那么您最好写入文件。

                【讨论】:

                  【解决方案9】:

                  缓慢是由于每次换行或刷新时都会发生大量 Java-Native 转换。如果迭代有很多步骤,那么 System.out.println() 就没有多大帮助。如果迭代步骤本身并不重要,您可以仅在每 10 或 100 步调用 System.out.println()。您还可以将 System.out 包装到 BufferedOutputStream 中。当然,始终可以选择通过 ExecutorService 异步打印。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2012-07-08
                    • 2016-08-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-09-14
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多