21

I'm doing something like this:

for (int i = 0; i < 100000; i++) {
   System.out.println( i );
}

Basically, I compute an integer and output a string about 10K-100K times and then need to write the result to system.out, each result separated by a newline.

What's the fastest way to achieve this?

CodeSmith
  • 1,621
  • 1
  • 13
  • 31

5 Answers5

35

Thank you for the suggestions. I created a test program to compare them:

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.StringBuilder;

public class systemouttest {

    public static void main(String[] args) throws Exception {

        long starttime = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
           System.out.println( i );
        }
        long printlntime = System.currentTimeMillis();

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 100000; i++) {
            sb.append( i + "\n" );
        }
        System.out.print(sb.toString());
        long stringbuildertime = System.currentTimeMillis();

        OutputStream out = new BufferedOutputStream ( System.out );
        for (int i = 0; i < 100000; i++) {
            out.write((i + "\n").getBytes());
        }
        out.flush();
        long bufferedoutputtime = System.currentTimeMillis();

        BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
        for (int i = 0; i < 100000; i++) {
            log.write(i + "\n");
        }
        log.flush();
        long bufferedwritertime = System.currentTimeMillis();

        System.out.println( "System.out.println: " + (printlntime - starttime) );
        System.out.println( "StringBuilder: " + (stringbuildertime - printlntime) );
        System.out.println( "BufferedoutputStream: " + (bufferedoutputtime - stringbuildertime) );
        System.out.println( "BufferedWriter: " + (bufferedwritertime - bufferedoutputtime) );
    }

}

Results:

Environment1
System.out.println: 482
StringBuilder: 210
BufferedoutputStream: 86
BufferedWriter: 202

Environment2
System.out.println: 1763
StringBuilder: 45
BufferedoutputStream: 76
BufferedWriter: 34

The suggestions all performed better than System.out.println. BufferedOutputStream seems to be the safest choice as it performed well in both test environments. BufferedWriter maybe faster though.

Please post further suggestions if anyone has some ideas. I'm sure someone can make it go faster :)

CodeSmith
  • 1,621
  • 1
  • 13
  • 31
  • 3
    Please see [How do I write a correct micro-benchmark in Java?](https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java) because the measurements you've posted here are very likely to be unreliable – Michael Aug 24 '18 at 13:04
5

For large amount of data,System.out.println might be inefficient as it does not do very good buffering. In that case, you can use a BufferedOutputStream or a BufferedWriter.

Akash KC
  • 16,057
  • 6
  • 39
  • 59
4

Keep in mind that I/O operations are very slow compared to in-memory processing (e.g. parsing of Integer). So, I would propose you to create the whole string 'in advance' and then print it out only once (of course if its possible):

StringBuilder sb = new StringBuilder();

for(int i = 0 ; i < 100000; i++) { sb.append(i).append("\n");}
String printMe = sb.toString(); 
System.out.println(printMe);

There are various techniques like buffering the the level of output stream you're using, but I assume that you prefer to stay with the most basic System.out.println

Hope this helps

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
3

This includes fast input and output method as well

import java.io.*;
public class templa{
    static class FastReader 
    { 
        BufferedReader br; 
        StringTokenizer st; 

        public FastReader() 
        { 
            br = new BufferedReader(new
                     InputStreamReader(System.in)); 
        } 

        String next() 
        { 
            while (st == null || !st.hasMoreElements()) 
            { 
                try
                { 
                    st = new StringTokenizer(br.readLine()); 
                } 
                catch (IOException  e) 
                { 
                    e.printStackTrace(); 
                } 
            } 
            return st.nextToken(); 
        } 

        int nextInt() 
        { 
            return Integer.parseInt(next()); 
        } 

        long nextLong() 
        { 
            return Long.parseLong(next()); 
        } 

        double nextDouble() 
        { 
            return Double.parseDouble(next()); 
        } 

        String nextLine() 
        { 
            String str = ""; 
            try
            { 
                str = br.readLine(); 
            } 
            catch (IOException e) 
            { 
                e.printStackTrace(); 
            } 
            return str; 
        } 
    } 

    public static void main(String...args) throws Exception {
        OutputStream outputStream =System.out;
        PrintWriter out =new PrintWriter(outputStream);
        FastReader in =new FastReader();
        int testcase = in.nextInt();
        while(testcase-- >0){
            //in object works same as Scanner Object but much faster
            //out.println() works faster than System.out.println()
            //Write your code here
        }
        out.close();
      }
}
Piotr Labunski
  • 1,638
  • 4
  • 19
  • 26
1

The slowest part of writing to System.out is the time taken to display what you are writing. i.e. for every line you write the computer has to turn the information into pixels using a font and scroll a whole line. This is much more work than whatever you are likely to be doing to display the text.

You can speed up writing to the console by

  • writing less (usually the best idea)
  • writing to a file instead (This can be 5-10x faster)
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130