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 ;
/**
* how many benchmark trials
*/
private static final int TRIALS = 5;
/**
* size of test file
*/
private static final long FILESIZE = 100L * 1024 * 1024 ;
/**
* 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 );
final InputStreamReader isr = new InputStreamReader( bis, EIO.UTF8 );
int dummy = 0;
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 );
final BufferedOutputStream bos = new BufferedOutputStream( fos, BUFFSIZE * 2 );
final OutputStreamWriter osw = new OutputStreamWriter( bos, EIO.UTF8 );
for ( long i = 0; i < FILESIZE; i++ )
{
char c = ( char ) i;
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 );
while ( br.read() >= 0 )
{
}
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 );
final OutputStreamWriter osw = new OutputStreamWriter( fos, EIO.UTF8 );
final BufferedWriter bw = new BufferedWriter( osw, BUFFSIZE );
for ( long i = 0; i < FILESIZE; i++ )
{
char c = ( char ) i;
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
{
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 );
final InputStreamReader isr = new InputStreamReader( bis, EIO.UTF8 );
final BufferedReader br = new BufferedReader( isr, readerBuffSizeInChars );
while ( br.read() >= 0 )
{
}
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
{
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 );
final BufferedOutputStream bos = new BufferedOutputStream( fos, streamBuffSizeInBytes );
final OutputStreamWriter osw = new OutputStreamWriter( bos, EIO.UTF8 );
final BufferedWriter bw = new BufferedWriter( osw, writerBuffSizeInChars );
for ( long i = 0; i < FILESIZE; i++ )
{
char c = ( char ) i;
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
{
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 );
}
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 ) );
}
}