Search code examples
javaionio

Download a file without buffer: Nio is faster than io?


I'm developping an updater for my project, and i want to download files quickly. Per update, there are some files, which have a different size. So i think i don't needed a Buffer, or surely not defined. I've so write that:

File file = new File..
InputStream input = new InputStream...
OutputStream output = new OutputStream(..).write(input.read());

This one running perfectly ! But my friend said to me; "hey, we've got FileChannel from jdk7". I've then thought about it, but we can't create & import data into a FileChannel without a ByteBuffer.

FileChannel channel = new FileOutputStream(file).getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(..);
buffer.putInt(inputstream.read());

channel.write(buffer);

So what's faster ? Better ? Thank you !

UPDATE: (best solution i think, very quickly)

URLConnection connection = new URL(url).openConnection();

File file = new File(connection.getURL().getPath().substring(1));
if (file.getParentFile() != null)
    file.getParentFile().mkdirs();

FileChannel output = new FileOutputStream(file).getChannel();
output.transferFrom(Channels.newChannel(connection.getInputStream()), 0, connection.getContentLengthLong());

It works !


Solution

  • Download a file without buffer: Nio is faster than io?

    It is unlikely to make any difference to download times whether you use classical I/O streams, or the NIO APIs.

    The speed of downloads is usually limited by the network. Things like:

    • the raw data rate of the slowest link,
    • the end-to-end network latency,
    • the amount of congestion over the entire route (which affects the chance of packets being dropped),
    • the absence of other factors (e.g. route instability, unreliable links / hardware, "shaping").

    Then, there is the issue of whether "the other end" can provide (or consume) the data at the rate that "the network" is capable of carrying. That typically depends on disc and network I/O bandwidth and load at the other end.

    Generally speaking, your client's ability to move the data from the memory buffer to the local destination file are not the issue.


    Before you (IMO) waste more time on this, I recommend that you implement the download code "the simple way". Then benchmark / profile it (with real downloads) to determine whether the performance bottleneck is in the code or (as I suspect) in "the network". Only go to the effort of optimizing your code if your measurements suggest that it could be worthwhile.


    UPDATE - I just noticed that in your original version, you are reading data a byte at a time (using read() from an unbuffered input stream. This definitely is inefficient, and it may be bad enough to impact on download speeds. If you are going to read from a stream (or write to a stream) in small chunks (e.g. one byte at a time), then you should wrap it with the corresponding buffered stream; e.g. BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter.

    The performance difference between using buffered versus unbuffered streams (for small I/O ops) is orders of magnitude more significant than the difference between classic streams versus NIO.