/* * [TestBuffered.java] * * Summary: Discover whether BufferOutputSteam or BufferedWrite in more efficient. * * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2010-02-20 initial version */ package com.mindprod.example; import com.mindprod.common18.EIO; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.text.DecimalFormat; import static java.lang.System.*; /** * Discover whether BufferOutputSteam or BufferedWrite in more efficient. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2010-02-20 initial version * @since 2010-02-20 */ public final class TestBuffered { /** * buffer size in chars */ private static final int BUFFSIZE = 32 * 1024 /* 32K chars = 64K bytes */; /** * how many benchmark trials */ private static final int TRIALS = 5; /** * size of test file */ private static final long FILESIZE = 100L * 1024 * 1024 /* 100 mb */; /** * allows us to display with commas. */ private static final DecimalFormat df = new DecimalFormat( "###,##0" ); /** * allows us to display seconds to two decimal places. */ private static final DecimalFormat df2 = new DecimalFormat( "###,##0.00" ); /** * display nanoseconds as seconds to two decimal places. * * @param nanoseconds how many nanoseconds ( billionths of a second ) * * @return displayable String. */ private static String asSeconds( double nanoseconds ) { return df2.format( nanoseconds / 1000000000d ) + " seconds"; } /** * read test file with a BufferedInputStream * W O R S T * * @return time taken in nanoseconds * @throws java.io.IOException if trouble reading test file */ private static long withBufferedInputStream() throws IOException { out.println( "start read using BufferedInputStream" ); long prevTime = System.nanoTime(); final FileInputStream fis = new FileInputStream( "temp.txt" ); final BufferedInputStream bis = new BufferedInputStream( fis, BUFFSIZE * 2 ); /* buffsize in bytes */ final InputStreamReader isr = new InputStreamReader( bis, EIO.UTF8 ); int dummy = 0; // ints are used for reading chars int c; while ( ( c = isr.read() ) >= 0 ) { dummy += c; } isr.close(); out.println( "end read using BufferedInputStream " + asSeconds( System.nanoTime() - prevTime ) ); return System.nanoTime() - prevTime; } /** * write test file with BufferedOutputStream * W O R S T * * @return time taken in nanoseconds * @throws java.io.IOException if trouble writing file. */ private static long withBufferedOutputStream() throws IOException { out.println( "start write using BufferedOutputStream" ); long prevTime = System.nanoTime(); final FileOutputStream fos = new FileOutputStream( "temp.txt", false /* append */ ); final BufferedOutputStream bos = new BufferedOutputStream( fos, BUFFSIZE * 2 ); /* buffsize in bytes */ final OutputStreamWriter osw = new OutputStreamWriter( bos, EIO.UTF8 ); for ( long i = 0; i < FILESIZE; i++ ) { char c = ( char ) i; // avoid surrogate area if ( 0xd800 <= c && c <= 0xdfff ) { c &= 0x3ff; } osw.write( c ); } osw.close(); out.println( "end write using BufferedOutputStream " + asSeconds( System.nanoTime() - prevTime ) ); return System.nanoTime() - prevTime; } /** * read test file with a BufferedReader * * @return time taken in nanoseconds * @throws java.io.IOException if trouble reading file. */ private static long withBufferedReader() throws IOException { out.println( "start read using BufferedReader" ); long prevTime = System.nanoTime(); final FileInputStream fis = new FileInputStream( "temp.txt" ); final InputStreamReader isr = new InputStreamReader( fis, EIO.UTF8 ); final BufferedReader br = new BufferedReader( isr, BUFFSIZE /* buffsize in chars */ ); while ( br.read() >= 0 ) { // empty loop } br.close(); out.println( "end read using BufferedReader " + asSeconds( System.nanoTime() - prevTime ) ); return System.nanoTime() - prevTime; } /** * write test file with a BufferedWriter * * @return time taken in nanoseconds * @throws java.io.IOException if trouble writing file. */ private static long withBufferedWriter() throws IOException { out.println( "start write using BufferedWriter" ); long prevTime = System.nanoTime(); final FileOutputStream fos = new FileOutputStream( "temp.txt", false /* append */ ); final OutputStreamWriter osw = new OutputStreamWriter( fos, EIO.UTF8 ); final BufferedWriter bw = new BufferedWriter( osw, BUFFSIZE /* buffsize in chars */ ); for ( long i = 0; i < FILESIZE; i++ ) { char c = ( char ) i; // avoid surrogate area if ( 0xd800 <= c && c <= 0xdfff ) { c &= 0x3ff; } bw.write( c ); } bw.close(); out.println( "end write using BufferedWriter " + asSeconds( System.nanoTime() - prevTime ) ); return System.nanoTime() - prevTime; } /** * read test file with a DoubleBufferedReader * Split the buffer space in two for BufferedInputStream and BufferedReader * B E S T with 50% * * @param percent of buffer space to give to the BufferedInputStream. * * @return time taken in nanoseconds * @throws java.io.IOException if problem reading file. */ private static long withDoubleBufferedReader( int percent ) throws IOException { // round to multiple of 16 bytes. final int streamBuffSizeInBytes = ( ( BUFFSIZE * 2 * percent / 100 ) + 8 ) / 16 * 16; final int readerBuffSizeInChars = BUFFSIZE - streamBuffSizeInBytes / 2; out.println( "start read using DoubleBufferedReader " + percent + "% " + streamBuffSizeInBytes + " bytes for BufferedInputStream " + readerBuffSizeInChars + " chars for BufferedReader." ); long prevTime = System.nanoTime(); final FileInputStream fis = new FileInputStream( "temp.txt" ); final BufferedInputStream bis = new BufferedInputStream( fis, streamBuffSizeInBytes ); /* buffsize in bytes */ final InputStreamReader isr = new InputStreamReader( bis, EIO.UTF8 ); final BufferedReader br = new BufferedReader( isr, readerBuffSizeInChars /* buffsize in chars */ ); while ( br.read() >= 0 ) { // empty loop } br.close(); out.println( "end read using DoubleBufferedReader " + asSeconds( System.nanoTime() - prevTime ) ); return System.nanoTime() - prevTime; } /** * write test file with a BufferedWriter and BufferedOutputStream. * Split buffer allocation in two for BufferedOutputStream and BufferedWriter * B E S T with 25% * * @param percent of buffer space to give to the BufferedOutputStream. * * @return time taken in nanoseconds * @throws java.io.IOException if trouble writing file. */ private static long withDoubleBufferedWriter( int percent ) throws IOException { // round to multiple of 16 bytes. final int streamBuffSizeInBytes = ( ( BUFFSIZE * 2 * percent / 100 ) + 8 ) / 16 * 16; final int writerBuffSizeInChars = BUFFSIZE - streamBuffSizeInBytes / 2; out.println( "start write using DoubleBufferedWriter " + percent + "% " + streamBuffSizeInBytes + " bytes for BufferedOutputStream " + writerBuffSizeInChars + " chars for BufferedWriter." ); long prevTime = System.nanoTime(); final FileOutputStream fos = new FileOutputStream( "temp.txt", false /* append */ ); final BufferedOutputStream bos = new BufferedOutputStream( fos, streamBuffSizeInBytes ); /* buffsize in bytes */ final OutputStreamWriter osw = new OutputStreamWriter( bos, EIO.UTF8 ); final BufferedWriter bw = new BufferedWriter( osw, writerBuffSizeInChars /* buffsize in chars */ ); for ( long i = 0; i < FILESIZE; i++ ) { char c = ( char ) i; // avoid surrogate area if ( 0xd800 <= c && c <= 0xdfff ) { c &= 0x3ff; } bw.write( c ); } bw.close(); out.println( "end write using DoubleBufferedWriter " + asSeconds( System.nanoTime() - prevTime ) ); return System.nanoTime() - prevTime; } /** * Benchmark three ways of buffered writing and three ways of buffered reading. * * @param args not used * * @throws java.io.IOException if problem writing or reading the test file. */ public static void main( String[] args ) throws IOException { // accumulated time all trials long bw = 0; long br = 0; long bos = 0; long bis = 0; long bdw10 = 0; long bdr10 = 0; long bdw25 = 0; long bdr25 = 0; long bdw50 = 0; long bdr50 = 0; long bdw75 = 0; long bdr75 = 0; for ( int i = 0; i < TRIALS; i++ ) { bw += withBufferedWriter(); br += withBufferedReader(); bos += withBufferedOutputStream(); bis += withBufferedInputStream(); bdw10 += withDoubleBufferedWriter( 10 ); bdr10 += withDoubleBufferedReader( 10 ); bdw25 += withDoubleBufferedWriter( 25 ); bdr25 += withDoubleBufferedReader( 25 ); bdw50 += withDoubleBufferedWriter( 50 ); bdr50 += withDoubleBufferedReader( 50 ); bdw75 += withDoubleBufferedWriter( 75 ); bdr75 += withDoubleBufferedReader( 75 ); } //noinspection ResultOfMethodCallIgnored new File( "temp.txt" ).delete(); out.println(); out.println( "Speeds are in seconds averaged over " + TRIALS + " trials using " + df.format( FILESIZE ) + " character files and " + df.format( BUFFSIZE ) + " character buffers." ); out.println(); out.println( "BufferedWriter " + asSeconds( bw / TRIALS ) ); out.println( "BufferedOutputStream " + asSeconds( bos / TRIALS ) ); out.println( "DoubleBufferedWriter 10% to BufferedOutputStream " + asSeconds( bdw10 / TRIALS ) ); out.println( "DoubleBufferedWriter 25% to BufferedOutputStream " + asSeconds( bdw25 / TRIALS ) ); out.println( "DoubleBufferedWriter 50% to BufferedOutputStream " + asSeconds( bdw50 / TRIALS ) ); out.println( "DoubleBufferedWriter 75% to BufferedOutputStream " + asSeconds( bdw75 / TRIALS ) ); out.println(); out.println( "BufferedReader " + asSeconds( br / TRIALS ) ); out.println( "BufferedInputStream " + asSeconds( bis / TRIALS ) ); out.println( "DoubleBufferedReader 10% to BufferedInputStream " + asSeconds( bdr10 / TRIALS ) ); out.println( "DoubleBufferedReader 25% to BufferedInputStream " + asSeconds( bdr25 / TRIALS ) ); out.println( "DoubleBufferedReader 50% to BufferedInputStream " + asSeconds( bdr50 / TRIALS ) ); out.println( "DoubleBufferedReader 75% to BufferedInputStream " + asSeconds( bdr75 / TRIALS ) ); // SUN JVM 1.6.0_22 RESULTS 64K char buffer // Speeds are in seconds averaged over 3 trials using 104,857,600 character files and 65,536 character buffers. // BufferedWriter 4.31 seconds // BufferedOutputStream 22.18 seconds W O R S T // DoubleBufferedWriter 10% to BufferedOutputStream 4.03 seconds // DoubleBufferedWriter 25% to BufferedOutputStream 3.65 seconds B E S T // DoubleBufferedWriter 50% to BufferedOutputStream 3.82 seconds // DoubleBufferedWriter 75% to BufferedOutputStream 3.68 seconds // BufferedReader 3.94 seconds // BufferedInputStream 14.11 seconds W O R S T // DoubleBufferedReader 10% to BufferedInputStream 4.02 seconds // DoubleBufferedReader 25% to BufferedInputStream 3.82 seconds // DoubleBufferedReader 50% to BufferedInputStream 3.77 seconds B E S T // DoubleBufferedReader 75% to BufferedInputStream 3.81 seconds // SUN JVM 1.6.0_22 RESULTS 32K char buffer // Speeds are in seconds averaged over 5 trials using 104,857,600 character files and 32,768 character buffers. // // BufferedWriter 3.96 seconds // BufferedOutputStream 20.37 seconds W O R S T // DoubleBufferedWriter 10% to BufferedOutputStream 3.81 seconds // DoubleBufferedWriter 25% to BufferedOutputStream 3.65 seconds // DoubleBufferedWriter 50% to BufferedOutputStream 3.72 seconds // DoubleBufferedWriter 75% to BufferedOutputStream 3.59 seconds B E S T // // BufferedReader 4.00 seconds // BufferedInputStream 12.50 seconds W O R S T // DoubleBufferedReader 10% to BufferedInputStream 3.96 seconds // DoubleBufferedReader 25% to BufferedInputStream 4.05 seconds // DoubleBufferedReader 50% to BufferedInputStream 3.95 seconds // DoubleBufferedReader 75% to BufferedInputStream 3.94 seconds B E S T // JET RESULTS // Speeds are in seconds averaged over 3 trials using 104,857,600 character files and 65,536 character buffers. // // BufferedWriter 4.76 seconds // BufferedOutputStream 129.08 seconds W O R S T // DoubleBufferedWriter 10% to BufferedOutputStream 7.10 seconds // DoubleBufferedWriter 25% to BufferedOutputStream 4.91 seconds // DoubleBufferedWriter 50% to BufferedOutputStream 4.64 seconds // DoubleBufferedWriter 75% to BufferedOutputStream 4.36 seconds B E S T // // BufferedReader 5.08 seconds // BufferedInputStream 109.91 seconds W O R S T // DoubleBufferedReader 10% to BufferedInputStream 16.01 seconds // DoubleBufferedReader 25% to BufferedInputStream 5.11 seconds // DoubleBufferedReader 50% to BufferedInputStream 5.09 seconds // DoubleBufferedReader 75% to BufferedInputStream 5.01 seconds B E S T } }