BufferedReader vs NIO Buffer

A

arun.darra

Hi,

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.
 
A

Arne Vajhøj

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 != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b);
}
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 != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b);
}
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 != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b);
}
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 != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b);
}
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 != (byte)(ix % 256)) {
throw new IOException("Bad data read - offset " +
ix + " expected " + (byte)(ix % 256) + " found " + b);
}
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";
}
}
 
M

Mike Amling

Hi,

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(....);

How do you get new BufferedReader(new FileInputStream(...)) to
compile? All the BufferedReader constructors require a Reader argument.
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.

Any Reader would have to attempt to parse an incoming byte sequence
into 16-bit chars according to an encoding. Your NIO example is not
doing any such parsing of the data.

--Mike Amling
 
E

EJP

Could someone pls tell me why is the NIO buffering faster than the IO
BufferedReader class.

Is it?
I agree NIO uses FileChannels to access the file.

And ByteBuffers.
> But it in turn uses the FileInputStream.

No it doesn't.
BufferedReader reader = new BufferedReader(new
FileInputStream("File.txt"));

Doesn't compile. Even if you fix that, you are introducing byte-to-char
overheads here that you don't have in your NIO test. So you are
comparing apples and oranges.
Keeping the fact in mind, in both cases the data is being buffered -
then how is the NIO method faster than IO Buffer.

I doubt that it is any faster at all, unless you use direct buffers, of
a much larger size.
 
R

Roedy Green

Could someone pls tell me why is the NIO buffering faster than the IO
BufferedReader class.

Except for the Mapped stuff, both use the same physical i/o.

nio offers a few benefits:

1. easier multithreading.

2. you can pluck a few bytes out of the buffer. With DataInputStream,
typically you read and process every byte. (Granted you can skip with
BufferedInputStream too.)

I asked myself the same question and did not come up with a
satisfactory answer. It seemed the added complexity would not provide
that much payback except for the Mapped stuff. Some benchmarks are in
order.
 
A

Arne Vajhøj

Isn't the main Payback of nio that you can use it non blocking mode...
You certainly don't want to have as many threads open as connections in
a setting where several hundred parallel connections are possible...

On high-end HW you can support hundreds of threads.

Go to thousands and something else is necessary.

Arne
 
E

EJP

Except for the Mapped stuff, both use the same physical i/o.

But with a ByteBuffer and FileChannel there is less implied data copying
than with e.g. a BufferedReader/InputStreamReader/FileInputStream.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top