RFR: 8265891: ChannelInputStream.transferTo() uses FileChannel.transferTo()

Alan Bateman alanb at openjdk.java.net
Thu Aug 19 13:13:25 UTC 2021


On Thu, 19 Aug 2021 06:16:42 GMT, Markus KARG <github.com+1701815+mkarg at openjdk.org> wrote:

> As proposed in JDK-8265891, this PR provides an implementation for `Channels.newInputStream().transferTo()` which provide superior performance compared to the current implementation. This PR is a spin-off from https://github.com/openjdk/jdk/pull/4263 and deliberately concentrates **only** on `FileChannel`s. Other types of channels will be discussed in future PRs.
> 
> * Prevents transfers through the JVM heap as much as possibly by offloading to deeper levels via NIO, hence allowing the operating system to optimize the transfer.
> 
> Using JMH I have benchmarked both, the original implementation and this implementation, and (depending on the used hardware and use case) performance change was approx. doubled performance. A rather similar approach in different use casse was recently implemented by https://github.com/openjdk/jdk/pull/5097 which was reported by even provide 5x performance (https://github.com/openjdk/jdk/pull/5097#issuecomment-897271997).

Thanks for the update. I see you've kept the code for the file -> socket scenario but there aren't any tests for this. If you do want to include this scenario then we'll need at least a test for the case where the output stream wraps a socket channel that is configured blocking. The test/jdk/java/nio/channels/Channels directory would be a good location for the new test because it is testing the input stream returned by the Channels API.

As regards ChannelInputStream then I had hoped that ThrowingLongSupplier would go away. If you keep your 2-arg transfer method then we should be able to implementation transferTo very simply, something like


        public long transferTo(OutputStream out) throws IOException {
            if (ch instanceof FileChannel fc
                    && out instanceof ChannelOutputStream cos) {
                WritableByteChannel target = cos.channel();
                if (target instanceof SelectableChannel sc) {
                    synchronized (sc.blockingLock()) {
                        if (!sc.isBlocking())
                            throw new IllegalBlockingModeException();
                        return transfer(fc, target);
                    }
                }
                return transfer(fc, target);
            }
            return super.transferTo(out);
        }

-------------

PR: https://git.openjdk.java.net/jdk/pull/5179


More information about the nio-dev mailing list