Why is System.out.println so slow?

后端 未结 7 1217
情歌与酒
情歌与酒 2020-11-27 08:30

Is this something common to all programming languages? Doing multiple print followed by a println seems faster but moving everything to a string and just printing that seem

相关标签:
7条回答
  • 2020-11-27 08:34

    Take a look at my System.out.println replacement.

    By default, System.out.print() is only line-buffered and does a lot work related to Unicode handling. Because of its small buffer size, System.out.println() is not well suited to handle many repetitive outputs in a batch mode. Each line is flushed right away. If your output is mainly ASCII-based then by removing the Unicode-related activities, the overall execution time will be better.

    0 讨论(0)
  • 2020-11-27 08:37

    Most of the answers here are right, but they don't cover the most important point: system calls. This is the operation that induces the more overhead.

    When your software needs to access some hardware resource (your screen for example), it needs to ask the OS (or hypervisor) if it can access the hardware. This costs a lot:

    Here are interesting blogs about syscalls, the last one being dedicated to syscall and Java

    http://arkanis.de/weblog/2017-01-05-measurements-of-system-call-performance-and-overhead http://www.brendangregg.com/blog/2014-05-11/strace-wow-much-syscall.html https://blog.packagecloud.io/eng/2017/03/14/using-strace-to-understand-java-performance-improvement/

    0 讨论(0)
  • 2020-11-27 08:44

    If you're printing to the console window, not to a file, that will be the killer.

    Every character has to be painted, and on every line the whole window has to be scrolled. If the window is partly overlaid with other windows, it also has to do clipping.

    That's going to take far more cycles than what your program is doing.

    Usually that's not a bad price to pay, since console output is supposed to be for your reading pleasure :)

    0 讨论(0)
  • 2020-11-27 08:45

    I believe this is because of buffering. A quote from the article:

    Another aspect of buffering concerns text output to a terminal window. By default, System.out (a PrintStream) is line buffered, meaning that the output buffer is flushed when a newline character is encountered. This is important for interactivity, where you'd like to have an input prompt displayed before actually entering any input.

    A quote explaining buffers from wikipedia:

    In computer science, a buffer is a region of memory used to temporarily hold data while it is being moved from one place to another. Typically, the data is stored in a buffer as it is retrieved from an input device (such as a Mouse) or just before it is sent to an output device (such as Speakers)

    public void println()
    

    Terminate the current line by writing the line separator string. The line separator string is defined by the system property line.separator, and is not necessarily a single newline character ('\n').

    So the buffer get's flushed when you do println which means new memory has to be allocated etc which makes printing slower. The other methods you specified require lesser flushing of buffers thus are faster.

    0 讨论(0)
  • 2020-11-27 08:47

    println is not slow, it's the underlying PrintStream that is connected with the console, provided by the hosting operating system.

    You can check it yourself: compare dumping a large text file to the console with piping the same textfile into another file:

    cat largeTextFile.txt
    cat largeTextFile.txt > temp.txt
    

    Reading and writing are similiar and proportional to the size of the file (O(n)), the only difference is, that the destination is different (console compared to file). And that's basically the same with System.out.


    The underlying OS operation (displaying chars on a console window) is slow because

    1. The bytes have to be sent to the console application (should be quite fast)
    2. Each char has to be rendered using (usually) a true type font (that's pretty slow, switching off anti aliasing could improve performance, btw)
    3. The displayed area may have to be scrolled in order to append a new line to the visible area (best case: bit block transfer operation, worst case: re-rendering of the complete text area)
    0 讨论(0)
  • 2020-11-27 08:48

    System.out is a static PrintStream class. PrintStream has, among other things, those methods you're probably quite familiar with, like print() and println() and such.

    It's not unique to Java that input and output operations take a long time. "long." printing or writing to a PrintStream takes a fraction of a second, but over 10 billion instances of this print can add up to quite a lot!

    This is why your "moving everything to a String" is the fastest. Your huge String is built, but you only print it once. Sure, it's a huge print, but you spend time on actually printing, not on the overhead associated with the print() or println().

    As Dvd Prd has mentioned, Strings are immutable. That means whenever you assign a new String to an old one but reusing references, you actually destroy the reference to the old String and create a reference to the new one. So you can make this whole operation go even faster by using the StringBuilder class, which is mutable. This will decrease the overhead associated with building that string you'll eventually print.

    0 讨论(0)
提交回复
热议问题