Re: BufferedReader vs NIO Buffer
On 28-03-2010 12:15, arun.darra@gmail.com wrote:
Could someone pls tell me why is the NIO buffering faster than the IO
BufferedReader class.
I agree NIO uses FileChannels to access the file. But it in turn uses
the FileInputStream.
Example 1: BufferedReader
BufferedReader reader = new BufferedReader(new
FileInputStream("File.txt"));
reader.read(....);
Example 2: NIO Bufferes
FileChannel fc = new FileInputStream("File.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
fc.read(buffer);
Keeping the fact in mind, in both cases the data is being buffered -
then how is the NIO method faster than IO Buffer.
My expectation would be that:
- the difference is very small
- NIO may be slightly faster because it was designed later
and performance could have been a design criteria possibly
resulting in a faster implementation
Actual difference will depend on Java vendor, Java version,
OS, CPU, IO system etc..
For SUN Java 1.6, WinXP and my PC:
Unbuffered small reads : 26844
Unbuffered large reads : 687
Buffered small reads : 1406
Buffered large reads : 688
Nio map small reads : 3656
Nio map large reads : 563
Nio read small reads : 3547
Nio read large reads : 531
Random access small reads : 26359
Random access large reads : 656
Unbuffered small reads : 26875
Unbuffered large reads : 500
Buffered small reads : 938
Buffered large reads : 469
Nio map small reads : 3453
Nio map large reads : 328
Nio read small reads : 3437
Nio read large reads : 375
Random access small reads : 26125
Random access large reads : 469
Unbuffered small reads : 26313
Unbuffered large reads : 453
Buffered small reads : 937
Buffered large reads : 485
Nio map small reads : 3406
Nio map large reads : 328
Nio read small reads : 3469
Nio read large reads : 437
Random access small reads : 26719
Random access large reads : 734
(see code below)
Arne
=======================
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ReadTest {
static final int TOT = 100000000;
static final int SMALL = 10;
static final int LARGE = 1000000;
static final String FILE_NAME = "C:/readtest.dat";
private static final int REP = 3;
public static void main(String[] args) throws Exception {
createFile();
for(int i = 0; i < REP; i++) {
(new UnbufferedSmallReadTest()).doTest();
(new UnbufferedLargeReadTest()).doTest();
(new BufferedSmallReadTest()).doTest();
(new BufferedLargeReadTest()).doTest();
(new NioMapSmallReadTest()).doTest();
(new NioMapLargeReadTest()).doTest();
(new NioReadSmallReadTest()).doTest();
(new NioReadLargeReadTest()).doTest();
(new RandomAccessSmallReadTest()).doTest();
(new RandomAccessLargeReadTest()).doTest();
}
}
private static void createFile() throws IOException {
OutputStream f = new FileOutputStream(FILE_NAME);
for(int i = 0; i < TOT; i++) {
f.write((i % 256));
}
}
}
abstract class GenericReadTest {
public void doTest() throws Exception {
long t1 = System.currentTimeMillis();
readAndCheck();
long t2 = System.currentTimeMillis();
System.out.println(getType() + " : " + (t2 - t1));
}
protected abstract void readAndCheck() throws Exception;
protected abstract int getReadSize();
public abstract String getType();
}
abstract class UnbufferedReadTest extends GenericReadTest {
protected void readAndCheck() throws IOException {
InputStream f = new FileInputStream(ReadTest.FILE_NAME);
byte[] b = new byte[getReadSize()];
int n;
int ix = 0;
while((n = f.read(b)) >= 0) {
for(int i = 0; i < n; i++) {
if(b[i] != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b[i]);
}
ix++;
}
}
}
}
abstract class BufferedReadTest extends GenericReadTest {
protected void readAndCheck() throws IOException {
BufferedInputStream f = new BufferedInputStream(new
FileInputStream(ReadTest.FILE_NAME));
byte[] b = new byte[getReadSize()];
int n;
int ix = 0;
while((n = f.read(b)) >= 0) {
for(int i = 0; i < n; i++) {
if(b[i] != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b[i]);
}
ix++;
}
}
}
}
abstract class NioMapReadTest extends GenericReadTest {
protected void readAndCheck() throws IOException {
FileChannel f2 = (new
FileInputStream(ReadTest.FILE_NAME)).getChannel();
ByteBuffer f = f2.map(FileChannel.MapMode.READ_ONLY, 0,
ReadTest.TOT);
byte[] b = new byte[getReadSize()];
int ix = 0;
while(ix < ReadTest.TOT) {
f.get(b);
for(int i = 0; i < b.length; i++) {
if(b[i] != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b[i]);
}
ix++;
}
}
}
}
abstract class NioReadReadTest extends GenericReadTest {
protected void readAndCheck() throws IOException {
FileChannel f = (new
FileInputStream(ReadTest.FILE_NAME)).getChannel();
ByteBuffer b2 = ByteBuffer.allocate(getReadSize());
byte[] b = new byte[getReadSize()];
int n;
int ix = 0;
while((n = f.read(b2)) >= 0) {
b2.get(b);
for(int i = 0; i < n; i++) {
if(b[i] != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b[i]);
}
ix++;
}
}
}
}
abstract class RandomAccessReadTest extends GenericReadTest {
protected void readAndCheck() throws IOException {
RandomAccessFile f = new RandomAccessFile(ReadTest.FILE_NAME, "r");
byte[] b = new byte[getReadSize()];
int n;
int ix = 0;
while((n = f.read(b)) >= 0) {
for(int i = 0; i < n; i++) {
if(b[i] != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b[i]);
}
ix++;
}
}
}
}
class UnbufferedSmallReadTest extends UnbufferedReadTest {
protected int getReadSize() {
return ReadTest.SMALL;
}
public String getType() {
return "Unbuffered small reads";
}
}
class UnbufferedLargeReadTest extends UnbufferedReadTest {
protected int getReadSize() {
return ReadTest.LARGE;
}
public String getType() {
return "Unbuffered large reads";
}
}
class BufferedSmallReadTest extends BufferedReadTest {
protected int getReadSize() {
return ReadTest.SMALL;
}
public String getType() {
return "Buffered small reads";
}
}
class BufferedLargeReadTest extends BufferedReadTest {
protected int getReadSize() {
return ReadTest.LARGE;
}
public String getType() {
return "Buffered large reads";
}
}
class NioMapSmallReadTest extends NioMapReadTest {
protected int getReadSize() {
return ReadTest.SMALL;
}
public String getType() {
return "Nio map small reads";
}
}
class NioMapLargeReadTest extends NioMapReadTest {
protected int getReadSize() {
return ReadTest.LARGE;
}
public String getType() {
return "Nio map large reads";
}
}
class NioReadSmallReadTest extends NioMapReadTest {
protected int getReadSize() {
return ReadTest.SMALL;
}
public String getType() {
return "Nio read small reads";
}
}
class NioReadLargeReadTest extends NioMapReadTest {
protected int getReadSize() {
return ReadTest.LARGE;
}
public String getType() {
return "Nio read large reads";
}
}
class RandomAccessSmallReadTest extends RandomAccessReadTest {
protected int getReadSize() {
return ReadTest.SMALL;
}
public String getType() {
return "Random access small reads";
}
}
class RandomAccessLargeReadTest extends RandomAccessReadTest {
protected int getReadSize() {
return ReadTest.LARGE;
}
public String getType() {
return "Random access large reads";
}
}