8286677: [BACKOUT] (fc) Tune FileChannel.transferFrom()
Reviewed-by: dholmes, mikael
This commit is contained in:
parent
4b8a66a5ff
commit
369611ea34
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user