8286677: [BACKOUT] (fc) Tune FileChannel.transferFrom()

Reviewed-by: dholmes, mikael
This commit is contained in:
Brian Burkhalter 2022-05-12 22:37:42 +00:00
parent 4b8a66a5ff
commit 369611ea34
4 changed files with 15 additions and 132 deletions

View File

@ -541,9 +541,9 @@ public class FileChannelImpl
}
// Assume at first that the underlying kernel supports sendfile();
// set this to true if we find out later that it doesn't
// set this to false if we find out later that it doesn't
//
private static volatile boolean transferToNotSupported;
private static volatile boolean transferSupported = true;
// Assume that the underlying kernel sendfile() will work if the target
// fd is a pipe; set this to false if we find out later that it doesn't
@ -587,7 +587,7 @@ public class FileChannelImpl
}
if (n == IOStatus.UNSUPPORTED) {
// Don't bother trying again
transferToNotSupported = true;
transferSupported = false;
return IOStatus.UNSUPPORTED;
}
return IOStatus.normalize(n);
@ -601,7 +601,7 @@ public class FileChannelImpl
WritableByteChannel target)
throws IOException
{
if (transferToNotSupported)
if (!transferSupported)
return IOStatus.UNSUPPORTED;
FileDescriptor targetFD = null;
@ -646,9 +646,8 @@ public class FileChannelImpl
}
// Size threshold above which to use a mapped buffer;
// transferToArbitraryChannel() and transferFromArbitraryChannel()
// are faster for smaller transfers
private static final long MAPPED_TRANSFER_THRESHOLD = 16L*1024L;
// transferToArbitraryChannel() is faster for smaller transfers
private static final long TRUSTED_TRANSFER_THRESHOLD = 16L*1024L;
// Maximum size to map when using a mapped buffer
private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L;
@ -657,7 +656,7 @@ public class FileChannelImpl
WritableByteChannel target)
throws IOException
{
if (count < MAPPED_TRANSFER_THRESHOLD)
if (count < TRUSTED_TRANSFER_THRESHOLD)
return IOStatus.UNSUPPORTED_CASE;
boolean isSelChImpl = (target instanceof SelChImpl);
@ -782,66 +781,12 @@ public class FileChannelImpl
return transferToArbitraryChannel(position, count, target);
}
// Assume at first that the underlying kernel supports copy_file_range();
// set this to true if we find out later that it doesn't
//
private static volatile boolean transferFromNotSupported;
private long transferFromDirectlyInternal(FileDescriptor srcFD,
long position, long count)
throws IOException
{
long n = -1;
int ti = -1;
try {
beginBlocking();
ti = threads.add();
if (!isOpen())
return -1;
do {
long comp = Blocker.begin();
try {
n = transferFrom0(srcFD, fd, position, count);
} finally {
Blocker.end(comp);
}
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n == IOStatus.UNSUPPORTED) {
// Don't bother trying again
transferFromNotSupported = true;
return IOStatus.UNSUPPORTED;
}
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
end (n > -1);
}
}
private long transferFromDirectly(FileChannelImpl src,
long position, long count)
throws IOException
{
if (!src.readable)
throw new NonReadableChannelException();
if (transferFromNotSupported)
return IOStatus.UNSUPPORTED;
FileDescriptor srcFD = src.fd;
if (srcFD == null)
return IOStatus.UNSUPPORTED_CASE;
return transferFromDirectlyInternal(srcFD, position, count);
}
private long transferFromFileChannel(FileChannelImpl src,
long position, long count)
throws IOException
{
if (!src.readable)
throw new NonReadableChannelException();
if (count < MAPPED_TRANSFER_THRESHOLD)
return IOStatus.UNSUPPORTED_CASE;
synchronized (src.positionLock) {
long pos = src.position();
long max = Math.min(count, src.size() - pos);
@ -931,10 +876,8 @@ public class FileChannelImpl
return 0;
if (src instanceof FileChannelImpl fci) {
long n;
if ((n = transferFromDirectly(fci, position, count)) >= 0)
return n;
if ((n = transferFromFileChannel(fci, position, count)) >= 0)
long n = transferFromFileChannel(fci, position, count);
if (n >= 0)
return n;
}
@ -1568,10 +1511,6 @@ public class FileChannelImpl
private static native long transferTo0(FileDescriptor src, long position,
long count, FileDescriptor dst);
private static native long transferFrom0(FileDescriptor src,
FileDescriptor dst,
long position, long count);
// Retrieves the maximum size of a transfer
private static native int maxDirectTransferSize0();

View File

@ -31,7 +31,6 @@
#if defined(__linux__)
#include <sys/sendfile.h>
#include <dlfcn.h>
#elif defined(_AIX)
#include <string.h>
#include <sys/socket.h>
@ -53,21 +52,11 @@
static jfieldID chan_fd; /* jobject 'fd' in sun.nio.ch.FileChannelImpl */
#if defined(__linux__)
typedef ssize_t copy_file_range_func(int, loff_t*, int, loff_t*, size_t,
unsigned int);
static copy_file_range_func* my_copy_file_range_func = NULL;
#endif
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz)
{
jlong pageSize = sysconf(_SC_PAGESIZE);
chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");
#if defined(__linux__)
my_copy_file_range_func =
(copy_file_range_func*) dlsym(RTLD_DEFAULT, "copy_file_range");
#endif
return pageSize;
}
@ -263,38 +252,6 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
#endif
}
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferFrom0(JNIEnv *env, jobject this,
jobject srcFDO, jobject dstFDO,
jlong position, jlong count)
{
#if defined(__linux__)
if (my_copy_file_range_func == NULL)
return IOS_UNSUPPORTED;
jint srcFD = fdval(env, srcFDO);
jint dstFD = fdval(env, dstFDO);
off64_t offset = (off64_t)position;
jlong n = my_copy_file_range_func(srcFD, NULL, dstFD, &offset, count, 0);
if (n < 0) {
if (errno == EAGAIN)
return IOS_UNAVAILABLE;
if ((errno == EINVAL || errno == EXDEV) && ((ssize_t)count >= 0))
return IOS_UNSUPPORTED_CASE;
if (errno == EINTR) {
return IOS_INTERRUPTED;
}
JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
return IOS_THROWN;
}
return n;
#else
return IOS_UNSUPPORTED;
#endif
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_FileChannelImpl_maxDirectTransferSize0(JNIEnv* env, jobject this)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -193,13 +193,6 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
return chunkSize;
}
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferFrom0(JNIEnv *env, jobject this,
jobject srcFDO, jobject dstFDO,
jlong position, jlong count)
{
return IOS_UNSUPPORTED;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_FileChannelImpl_maxDirectTransferSize0(JNIEnv* env, jobject this)

View File

@ -23,7 +23,7 @@
/* @test
* @summary Comprehensive test for FileChannel.transfer{From,To}
* @bug 4708120 8274113
* @bug 4708120
* @author Mark Reinhold
* @run main/timeout=300 Transfers
*/
@ -468,16 +468,10 @@ public class Transfers {
int pos = (int)seed & 0xfff;
fc.position(pos);
long position = off;
long count = len;
while (count > 0) {
int n = (int)fc.transferFrom(src.channel(), position, count);
if (n < 0 || n > count)
throw new Failure("Incorrect transfer length n = : " + n
+ " (expected 0 <= n <= " + len + ")");
position += n;
count -= n;
}
int n = (int)fc.transferFrom(src.channel(), off, len);
if (n != len)
throw new Failure("Incorrect transfer length: " + n
+ " (expected " + len + ")");
// Check that source didn't change, and was read correctly
src.verify();