Java:System.out.println() 这么慢的原因是什么?
对于可以在文本编辑器中完成的小型逻辑程序,我使用经典的 System.out.println() 进行跟踪。
我想你们都知道在大量迭代的块中使用它是多么令人沮丧。 为什么这么慢? 其背后的原因是什么?
For small logical programs that can be done in a text editor, for tracing I use the classic System.out.println()
.
I guess you all know how frustrating it is to use that in a block of high number of iterations. Why is it so slow? What's the reason behind it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这与 JVM 没有任何关系。 将文本打印到屏幕上只涉及操作系统在绘制字母(尤其是滚动)方面的大量工作。 如果将 System.out 重定向到一个文件,速度会快得多。
This has nothing whatsoever to do with the JVM. Printing text to screen simply involves a lot of work for the OS in drawing the letters and especially scrolling. If you redirect System.out to a file, it will be much faster.
这非常依赖于操作系统。 例如,在 Windows 中,写入控制台是一个阻塞操作,而且速度也很慢,因此向控制台写入大量数据会减慢(或阻塞)应用程序的速度。 在unix类型的操作系统中,对控制台的写入是缓冲的,因此您的应用程序可以继续畅通无阻,并且控制台将尽力赶上。
This is very OS-dependent. For example, in Windows, writing to the console is a blocking operation, and it's also slow, and so writing lots of data to the console slows down (or blocks) your application. In unix-type OSes, writing to the console is buffered, so your app can continue unblocked, and the console will catch up as it can.
是的,写入控制台会产生大量开销。 远远大于写入文件或套接字所需的量。 此外,如果有大量线程,它们都会争用同一个锁。 我建议使用 System.out.println 之外的其他东西来跟踪。
Ya, there is a huge amount of overhead in writing to the console. Far greater than that required to write to a file or a socket. Also if there are a large number of threads they are all contending on the same lock. I would recommend using something other that System.out.println to trace.
这与Java和JVM无关,而是与控制台终端有关。 我知道在大多数操作系统中,写入控制台输出的速度很慢。
This has nothing to do with Java and JVM but with the console terminal. In most OSes I know writing in the console output is slow.
缓冲可以有很大帮助。 试试这个:
但要注意:你不会看到输出逐渐出现,而是一瞬间出现。 这很棒,但是如果您使用它进行调试,并且程序在终止之前崩溃,则在某些情况下您可能看不到崩溃之前打印的文本。
这是因为缓冲区在崩溃之前没有刷新。 它已被打印,但仍然在缓冲区中,并且没有到达控制台,您可以在其中看到它。 我记得这件事发生在我身上,在一次令人费解的调试过程中。 最好偶尔显式刷新,以确保您看到它:
Buffering can help enormously. Try this:
But beware: you won't see the output appear gradually, but all in a flash. Which is great, but if you're using it for debugging, and the program crashes before it terminates, in some circumstances it's possible you won't see the text printed just before the crash.
This is because the buffer wasn't flushed before the crash. It was printed, but it's still in the buffer, and didn't make it out to the console where you can see it. I remember this happening to me, in a puzzling debug session. It's best to occasionally flush explicitly, to make sure you see it:
有些终端只是比其他终端更快。 即使在一个操作系统内,这也可能有所不同。
Some terminals just are faster than others. This may vary even within one operating system.
是一种调试,只是为了查看你的应用程序的进展)
这可能看起来并没有直接回答你的问题,但我的建议是永远不要使用 System.out 进行跟踪(如果你的意思 用于调试的 System.out 有以下几种:
一旦应用程序结束,当您关闭控制台时,您将丢失日志
一旦您的应用程序正常运行,您就必须删除这些语句(或评论它们)。 稍后,如果您想重新激活它们,则必须再次取消注释/注释...繁琐
,
我建议改为使用 log4j 并“监视”日志文件,或者使用 tail 命令 - 还有一个 Tail for Windows - 可以使用 Eclipse 插件,例如 LogWatcher。
This might look as it doesn't directly answer your question, but my advice is to never use System.out for tracing ( if you mean by that a kind of debugging, in order just to see the advance of your app )
The problems with System.out for debugging are several :
once the app ends, when you close the console you'll loose the log
you'll have to remove those statements once your app is working properly ( or comment them ). Later if you want to reactivate them, you'll have to uncomment/comment again ... tedious
I recommend instead to use log4j and "watch" the log file, either with a tail command - there's also a Tail for Windows - either with an Eclipse plugin like LogWatcher.
关于写入终端(至少在 Windows 中),我注意到一件有趣的事情。 如果窗口最小化,它实际上运行得更快吗? 这绝对与 Michael Borgwardt 关于绘图和滚动的回答密切相关。 实际上,如果您记录的日志足够多,可以注意到速度减慢,那么最好写入文件。
One interesting thing I've noticed about writing to the terminal (at least in Windows). Is it actually runs much much faster if the window is minimized. This is definitely closely tied with Michael Borgwardt's answer about drawing and scrolling. Really if you're logging enough to notice the slowdown you're probably better off writing to a file.
缓慢的原因是每次换行或刷新时都会发生大量 Java 原生转换。 如果迭代有很多步骤,则 System.out.println() 没有太大帮助。 如果迭代步骤本身并不那么重要,您可以仅在每 10 或 100 个步骤上调用 System.out.println() 。 您还可以将 System.out 包装到 BufferedOutputStream 中。 当然,始终可以选择通过 ExecutorService 异步打印。
The slowness is due the large amount of Java-Native transitions which happen on every line break or flush. If the iteration has to many steps, the System.out.println() isn't much of a help. If the iteration steps are not that important by themselves, you may call System.out.println() on every 10 or 100 steps only. You can also wrap the System.out into a BufferedOutputStream. And of course there is always the option to asynchronize the print via ExecutorService.