Why Is System.Out.Println So Slow

Why is System.out.println so slow?

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)

Java: What's the reason behind System.out.println() being that slow?

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.

Adding System.out.println() slows down execution (a lot)?

Writing to the console, especially the MS-DOS console, is very very slow. You should try to keep the number of lines you write to the console to a minimum. If you have to write lots of data I suggest you write it to a file as it can be significantly faster.

I assume this is done in another thread and you are not tying up the GUI thread.

Does System.out.println() effect the code efficiency ?

System.out implementation contains a synchronized block on the output stream.

From PrintStream.java :

      /**
* Prints a String and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(String)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x The <code>String</code> to be printed.
*/

public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}

Putting System.out.println a lot will make the entire project to run almost single-threaded, because all thread will waiting for synchronization lock, and make your application begin to crawl.

This means your superior is right.

Alternatively, Use logging framework like log4j instead. You can still configure your log4j to still output to System.out.println by just minor changes in the appender configuration.

Java's System.out.println(); will it block the program it tty will have latency

Will it block the program it tty will have latency

Java's console output is blocking, so potentially your code may block, especially when you writing a lot of data.

what is the size of tty memory?

I am pretty sure that it depends on your kernel, this old thread suggests that it was 4096 bytes at some moment:

I've looked in the kernel code (linux\drivers\char\serial.c) and there is a #define called SERIAL_XMIT_SIZE. At first I thought maybe I could change that but it seems that the transmit buffer is actually fixed to be a memory page (4k).

 

If I will lose connection for a while - will it run still?

Yes, and if there is no one connected to the tty, then it will run much faster, as it will be able to discard the data.

Also small test application that simulates your use-case.

Echo.java

import java.io.IOException;

public class Echo {
public static void main(String[] args) throws InterruptedException, IOException {
final byte[] data = new byte[Test.BODY_LENGTH + Test.END_MARKER.length];
int index = 0;
outer: while (true) {
data[index++] = (byte) System.in.read();
final int dataOffset = index - Test.END_MARKER.length;
if (dataOffset < 0) {
continue;
}
for (int i = 0; i < Test.END_MARKER.length; i++) {
if (data[dataOffset + i] != Test.END_MARKER[i]) {
continue outer;
}
}
System.out.print(new String(data, 0, index));
return;
}
}
}

Test.java

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

public class Test {

public static final byte[] END_MARKER = "$TERMINATE$".getBytes();
public static final int BODY_LENGTH = 1024768;

public static void main(String[] args) throws IOException, InterruptedException {
StringBuilder data = new StringBuilder();
for (int i = 0; i < BODY_LENGTH; i++) {
data.append((char) ('a' + ThreadLocalRandom.current().nextInt(('z' - 'a' + 1))));
}
final Process process = new ProcessBuilder("java", Test.class.getPackage().getName() + ".Echo")
.directory(new File("out/production/week 3")) // Change to your output directory
.start();
process.getOutputStream().write(data.toString().getBytes());
process.getOutputStream().write(END_MARKER);
process.getOutputStream().flush();
System.out.println("Written!");
final boolean exitedAfterWroteData = process.waitFor(5, TimeUnit.SECONDS);
System.out.println(exitedAfterWroteData ? "Complete" : "Running"); // Will print running after 5 seconds
int read = 0;
while (process.getInputStream().read() > -1) {
read++;
}
if (read != data.toString().getBytes().length + END_MARKER.length) {
throw new IllegalStateException("Expected echo to print exactly " + BODY_LENGTH + END_MARKER.length + " symbols!");
}
final boolean exitedAfterWeReadData = process.waitFor(50, TimeUnit.MILLISECONDS);
System.out.println(exitedAfterWeReadData ? "Complete" : "Running"); // Will print complete after a few milliseconds
}
}

Why is printing B dramatically slower than printing #?

Pure speculation is that you're using a terminal that attempts to do word-wrapping rather than character-wrapping, and treats B as a word character but # as a non-word character. So when it reaches the end of a line and searches for a place to break the line, it sees a # almost immediately and happily breaks there; whereas with the B, it has to keep searching for longer, and may have more text to wrap (which may be expensive on some terminals, e.g., outputting backspaces, then outputting spaces to overwrite the letters being wrapped).

But that's pure speculation.

Java - System.out effect on performance

It can have an impact on your application performance. The magnitude will vary depending on the kind of hardware you are running on and the load on the host.

Some points on which this can translate to performance wise:

-> Like Rocket boy stated, println is synchronized, which means you will be incurring in locking overhead on the object header and may cause thread bottlenecks depending on your design.

-> Printing on the console requires kernel time, kernel time means the cpu will not be running on user mode which basically means your cpu will be busy executing on kernel code instead of your application code.

-> If you are already logging this, that means extra kernel time for I/O, and if your platform does not support asynchronous I/O this means your cpu might become stalled on busy waits.

You can actually try and benchmark this and verify this yourself.

There are ways to getaway with this like for example having a really fast I/O, a huge machine for dedicated use maybe and biased locking on your JVM options if your application design will not be multithreaded on that console printing.

Like everything on performance, it all depends on your hardware and priorities.

Why is System.err slower than System.out in Eclipse?

It's not slower; they're just not necessarily flushed in order. You can fix that, however:

System.err.println("err");
System.err.flush();
System.out.println("out");

Okay, so this appears to be a known Eclipse bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=32205



Related Topics



Leave a reply



Submit