1

I was under the impression that using FileChannel and BytBuffer would speed the read time but it seems to be significantly slower than reading from a filestream. Am I doing something wrong here?

FileInputStream fis = new FileInputStream("C:\\Users\\blah\\Desktop\\del\\pg28054.txt");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\blah\\Desktop\\del\\readme.txt");

        FileChannel fcin = fis.getChannel();
        FileChannel fcout = fos.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long startTime = System.currentTimeMillis();
        long endtime = System.currentTimeMillis();
        while(true){
            buffer.clear();
            int r = fcin.read(buffer);
            if(r==-1){
                break;
            }
            buffer.flip();
            fcout.write(buffer);
        }
        endtime = System.currentTimeMillis();
        System.out.println("time to read and write(ms) " + (endtime - startTime));

The above completes in 108 ms where are the below implementation does it in 43 ms

        long startTime;
        long endtime;
        FileInputStream fis1 = new FileInputStream("C:\\Users\\blah\\Desktop\\del\\pg28054.txt");
        FileOutputStream fos1 = new FileOutputStream("C:\\Users\\blah\\Desktop\\del\\readme1.txt");

        byte b[] = null;

        startTime = System.currentTimeMillis();
        while(true){
            b = new byte[1024];
            int r = fis1.read(b);
            if(r==-1){
                break;
            }
            fos1.write(b);
        }

        endtime = System.currentTimeMillis();
        System.out.println("time to read and write(ms) " + (endtime - startTime));
jtkSource
  • 675
  • 9
  • 21
  • The usual questions apply to microbenchmarks: did you run the experiments multiple times in the JVM, giving ample time for the JIT to do its work? Did you use `--XX:+PrintCompilation` to confirm that the JIT was quiet for the runs whose values you used? One immediate thought is that the first block of code may bring in more classes (which requires greater overhead), even if those classes result in faster code once they've been JIT'ed and such. – yshavit Feb 10 '15 at 00:35
  • This is a borderline dupe of http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – yshavit Feb 10 '15 at 00:36
  • A bit more info would be good - what sizes are your files. How are you running your benchmarks. – Michael Anderson Feb 10 '15 at 01:13
  • 1
    Where exactly did you get the impresssion that this case should be faster? NB your copy loops are both invalid. The NIO loop should call `compact()` instead of `clear(),` and the `java.io` loop should call `fos1.write(b, 0, r)`. There's a risk of data loss otherwise. – user207421 Feb 10 '15 at 01:16
  • In your second test you do not necessarily write out the correct data. Instead of `fos1.write(b)`, you should call `fos1.write(b,0,r)`. – Brett Okken Feb 10 '15 at 01:20
  • Thanks I will have to do more reading :( – jtkSource Feb 10 '15 at 23:52

1 Answers1

2

Aside from the very accurate comments about the quality of your benchmark, there is nothing about Channels or ByteBuffers that is inherently faster than streams. There are options which can make things perform faster. For example, you could use the FileChannel.transferFrom method to transfer the content. Another example would be to use a direct ByteBuffer to transfer the content.

Brett Okken
  • 6,210
  • 1
  • 19
  • 25