【发布时间】:2010-10-31 07:19:00
【问题描述】:
对于可以在文本编辑器中完成的小型逻辑程序,我使用经典的 System.out.println() 进行跟踪。
我想你们都知道在大量迭代中使用它是多么令人沮丧。为什么这么慢?背后的原因是什么?
【问题讨论】:
标签: java performance console stdout
对于可以在文本编辑器中完成的小型逻辑程序,我使用经典的 System.out.println() 进行跟踪。
我想你们都知道在大量迭代中使用它是多么令人沮丧。为什么这么慢?背后的原因是什么?
【问题讨论】:
标签: java performance console stdout
这与 JVM 无关。将文本打印到屏幕上简单地涉及操作系统在绘制字母,尤其是滚动方面的大量工作。如果将 System.out 重定向到一个文件,它会快得多。
【讨论】:
这非常依赖于操作系统。例如,在 Windows 中,写入控制台是一个阻塞操作,而且速度也很慢,因此向控制台写入大量数据会减慢(或阻塞)您的应用程序。在 unix 类型的操作系统中,对控制台的写入是缓冲的,因此您的应用可以继续畅通无阻,并且控制台会尽可能地赶上。
【讨论】:
是的,写入控制台会产生大量开销。远远大于写入文件或套接字所需的量。此外,如果有大量线程,它们都在同一个锁上竞争。我建议使用 System.out.println 以外的东西来跟踪。
【讨论】:
这与 Java 和 JVM 无关,而是与控制台终端有关。在大多数操作系统中,我知道在控制台输出中写入速度很慢。
【讨论】:
缓冲有很大帮助。试试这个:
System.setOut( new PrintStream(new BufferedOutputStream(System.out)) );
但请注意:您不会看到输出逐渐出现,而是一瞬间。这很好,但是如果您将它用于调试,并且程序在终止之前崩溃,在某些情况下,您可能不会在崩溃之前看到打印的文本。 这是因为缓冲区在崩溃之前没有被刷新。它被打印出来了,但它仍然在缓冲区中,并没有出现在你可以看到它的控制台上。我记得这发生在我身上,在一个令人费解的调试会话中。最好偶尔显式刷新,以确保您看到它:
System.out.flush();
【讨论】:
有些终端比其他终端快。即使在一个操作系统中,这也可能会有所不同。
【讨论】:
这可能看起来并没有直接回答您的问题,但我的建议是永远不要使用 System.out 进行跟踪(如果您指的是一种调试,只是为了查看您的应用程序的进步)
System.out 用于调试的问题有几个:
一旦应用程序结束,当您关闭控制台时,您将丢失日志
一旦您的应用程序正常运行(或评论它们),您就必须删除这些语句。稍后如果您想重新激活它们,您将不得不再次取消评论/评论......乏味
我建议改用 log4j 并“监视”日志文件,或者使用 tail 命令 - 还有一个 Tail for Windows - 或者使用像 LogWatcher 这样的 Eclipse 插件。
【讨论】:
我注意到关于写入终端的一件有趣的事情(至少在 Windows 中)。如果窗口最小化,它实际上运行得更快吗?这绝对与 Michael Borgwardt 关于绘图和滚动的回答密切相关。确实,如果您的日志记录足以注意到速度变慢,那么您最好写入文件。
【讨论】:
缓慢是由于每次换行或刷新时都会发生大量 Java-Native 转换。如果迭代有很多步骤,那么 System.out.println() 就没有多大帮助。如果迭代步骤本身并不重要,您可以仅在每 10 或 100 步调用 System.out.println()。您还可以将 System.out 包装到 BufferedOutputStream 中。当然,始终可以选择通过 ExecutorService 异步打印。
【讨论】: