Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 135992

Files.newInputStream creates slow InputStream

On my Windows 7 Files.newInputStream returns sun.nio.ch.ChannelInputStream. When I tested its performance vs FileInputStream I was surprised to know that FileInputStream is faster.

This test

    InputStream in = new FileInputStream("test");
    long t0 = System.currentTimeMillis();
    byte[] a = new byte[16 * 1024];
    for (int n; (n = in.read(a)) != -1;) {
    }
    System.out.println(System.currentTimeMillis() - t0);

reads 100mb file in 125 ms. If I replace the first line with

InputStream in = Files.newInputStream(Paths.get("test"));

I get 320ms.

If Files.newInputStream is slower what advantages it has over FileInputStream?

Upvotes: 9

Views: 6145

Answers (4)

duvanjamid
duvanjamid

Reputation: 604

Your FileInputStream and FileOutputstreams might introduce long GC pauses

Every time you create either a FileInputStream or a FileOutputStream, you are creating an object. Even if you close it correctly and promptly, it will be put into a special category that only gets cleaned up when the garbage collector does a full GC. Sadly, due to backwards compatibility constraints, this is not something that can be fixed in the JDK anytime soon as there could be some code out there where somebody has extended FileInputStream / FileOutputStream and is relying on those finalize() methods to ensure the call to close().

The solution (at least if you are using Java 7 or newer) is not too hard — just switch to Files.newInputStream(...) and Files.newOutputStream(...)

https://dzone.com/articles/fileinputstream-fileoutputstream-considered-harmful

Upvotes: 3

魏經軒
魏經軒

Reputation: 17

The document said

"The stream will not be buffered"

It's because Files.newInputStream(Paths) support non-blocking IO.

You can try in debug mode, you can open non blocking inputstream and in the same time modify the file, but if you use FileInputStream, you cannot do such things.

FileInputStream will require "write lock" of file, so it can buffer the content of file, increase the speed of reading.

But ChannelInputStream cannot. It must guaranteed that it is reading the "current" content of file.

Above is my experience, I didn't check every point in Java doc.

Upvotes: -2

user207421
user207421

Reputation: 310860

If you tested new FileInputStream second, you are probably just seeing the effect of cache priming by the operating system. It isn't plausible that Java is causing any significant difference to an I/O-bound process. Try it the other way around, and on a much larger dataset.

Upvotes: 10

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279890

I don't want to be the buzzkill, but the javadoc doesn't state any advantages, nor does any documentation I could find

Opens a file, returning an input stream to read from the file. The stream will not be buffered, and is not required to support the mark or reset methods. The stream will be safe for access by multiple concurrent threads. Reading commences at the beginning of the file. Whether the returned stream is asynchronously closeable and/or interruptible is highly file system provider specific and therefore not specified.

I think the method is just a utility method not necessarily meant to replace or improve on FileInputStream. Note that the concurrency point might explain some slow down.

Upvotes: 2

Related Questions