package com.mindprod.example;
import com.mindprod.common18.EIO;
import com.mindprod.hunkio.HunkIO;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.Random;
import static java.lang.System.*;
/**
* Discover best way to allocate buffers.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2014-05-10 initial version
* @since 2014-05-10
*/
public final class TestBufferedRatio
{
/**
* how many benchmark trials
*/
private static final int TRIALS = 5;
/**
* size of test file in chars
*/
private static final long FILESIZE = 200L * 1024 * 1024;
/**
* size of line in chars including \n
*/
private static final int LINESIZE = 100;
/**
* allows us to display seconds to zero decimal places.
*/
private static final DecimalFormat df0 = new DecimalFormat( "###,##0" );
/**
* allows us to display seconds to two decimal places.
*/
private static final DecimalFormat df2 = new DecimalFormat( "###,##0.00" );
/**
* chars we allow in our random data
*/
private static final String ALLOWED = "abcdefghijklmnopqrstuvwxyzABCDEFGHJKMLMOPQRSTUVWXYZ 0123456789 +!@$#$%^&*()_-?/|\\\n";
/**
* character set to use
*/
private static final Charset charset = Charset.forName( "UTF-16" );
/**
* sample date file we read to test
*/
private static File sampleDataFile;
/**
* 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";
}
/**
* generate 100K of sample data in a temporary file.
*/
private static void generateSampleData() throws IOException
{
HunkIO.createTempFile( "temp_", ".tmp", new File( "H:/temp" ) );
sampleDataFile = File.createTempFile( "temp_", ".tmp" );
final Random wheel = new Random();
final BufferedWriter bw = EIO.getBufferedWriter( sampleDataFile, 256 * 1024, charset );
char[] line = new char[ LINESIZE - 1 ];
for ( int i = 0; i < ( FILESIZE / LINESIZE ); i++ )
{
for ( int j = 0; j < line.length; j++ )
{
line[ j ] = ALLOWED.charAt( ( wheel.nextInt() & Integer.MAX_VALUE ) % ALLOWED.length() );
}
bw.write( line );
bw.write( "\n" );
}
bw.close();
}
/**
* read test file with a withBufferedReader
*
* @param ratio 0.6 means give 60% of buffer space to the inputwriter and 40% to the inputStream
* @param buffsize total buffer space to allocate in bytes.
*
* @throws java.io.IOException if trouble reading test file
*/
private static void withBufferedReader( double ratio, int buffsize ) throws IOException
{
assert .1 <= ratio && ratio <= .9 : "ratio must be in range [0.1,0.9].";
long prevTime = System.nanoTime();
final FileInputStream fis = new FileInputStream( sampleDataFile );
final BufferedInputStream bis = new BufferedInputStream( fis, ( int ) ( buffsize * ( 1 - ratio ) ) );
final InputStreamReader isr = new InputStreamReader( bis, charset );
final BufferedReader ibr = new BufferedReader( isr, ( int ) ( buffsize * ratio / 2 ) );
String line;
while ( ( line = ibr.readLine() ) != null )
{
}
ibr.close();
out.println( "BufferedReader backed with BufferedInputStream ratio " +
df2.format( ratio ) + " buffsize " + buffsize + " bytes " + asSeconds( System.nanoTime() - prevTime ) );
}
/**
* read test file with a HunkIO
*
* @throws java.io.IOException if trouble reading test file
*/
private static void withHunkIO() throws IOException
{
long prevTime = System.nanoTime();
@SuppressWarnings( "UnusedAssignment" ) String contents = HunkIO.readEntireFile( sampleDataFile, charset );
out.println( "HunkIO " + asSeconds( System.nanoTime() - prevTime ) );
}
/**
* read test file with a withBufferedReader
*
* @param buffsize total buffer space to allocate in bytes.
*
* @throws java.io.IOException if trouble reading test file
*/
private static void withPlainBufferedReader( int buffsize ) throws IOException
{
long prevTime = System.nanoTime();
final BufferedReader ibr = new BufferedReader( new FileReader( sampleDataFile ), buffsize / 2 );
String line;
while ( ( line = ibr.readLine() ) != null )
{
}
ibr.close();
out.println( "Unbacked BufferedReader default encoding buffsize " + buffsize + " bytes " + asSeconds( 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
{
generateSampleData();
out.println( "Using a random sample data file of "
+ df0.format( FILESIZE )
+ " chars "
+ df0.format( sampleDataFile.length() )
+ " bytes." );
out.println( "Using charset " + charset );
int buffSize = 64 * 1024;
out.println( "Using aggregate buffersize of " + df0.format( buffSize ) + " bytes." );
for ( int i = 0; i < TRIALS; i++ )
{
withPlainBufferedReader( buffSize );
withBufferedReader( .1, buffSize );
withBufferedReader( .2, buffSize );
withBufferedReader( .3, buffSize );
withBufferedReader( .4, buffSize );
withBufferedReader( .5, buffSize );
withBufferedReader( .6, buffSize );
withBufferedReader( .7, buffSize );
withBufferedReader( .8, buffSize );
withBufferedReader( .9, buffSize );
withHunkIO();
}
sampleDataFile.delete();
}
}