8193832: Performance of InputStream.readAllBytes() could be improved
Read into a list of fixed-size buffers which are gathered at the end Reviewed-by: alanb, chegar, plevart, jrose, psandoz
This commit is contained in:
parent
d32979d771
commit
1209c4bcb3
@ -25,7 +25,9 @@
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -229,30 +231,55 @@ public abstract class InputStream implements Closeable {
|
||||
* @since 9
|
||||
*/
|
||||
public byte[] readAllBytes() throws IOException {
|
||||
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
|
||||
int capacity = buf.length;
|
||||
int nread = 0;
|
||||
List<byte[]> bufs = null;
|
||||
byte[] result = null;
|
||||
int total = 0;
|
||||
int n;
|
||||
for (;;) {
|
||||
// read to EOF which may read more or less than initial buffer size
|
||||
while ((n = read(buf, nread, capacity - nread)) > 0)
|
||||
do {
|
||||
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
|
||||
int nread = 0;
|
||||
|
||||
// read to EOF which may read more or less than buffer size
|
||||
while ((n = read(buf, nread, buf.length - nread)) > 0) {
|
||||
nread += n;
|
||||
|
||||
// if the last call to read returned -1, then we're done
|
||||
if (n < 0)
|
||||
break;
|
||||
|
||||
// need to allocate a larger buffer
|
||||
if (capacity <= MAX_BUFFER_SIZE - capacity) {
|
||||
capacity = capacity << 1;
|
||||
} else {
|
||||
if (capacity == MAX_BUFFER_SIZE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
capacity = MAX_BUFFER_SIZE;
|
||||
}
|
||||
buf = Arrays.copyOf(buf, capacity);
|
||||
|
||||
if (nread > 0) {
|
||||
if (MAX_BUFFER_SIZE - total < nread) {
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
}
|
||||
total += nread;
|
||||
if (result == null) {
|
||||
result = buf;
|
||||
} else {
|
||||
if (bufs == null) {
|
||||
bufs = new ArrayList<>();
|
||||
bufs.add(result);
|
||||
}
|
||||
bufs.add(buf);
|
||||
}
|
||||
}
|
||||
} while (n >= 0); // if the last call to read returned -1, then break
|
||||
|
||||
if (bufs == null) {
|
||||
if (result == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
return result.length == total ?
|
||||
result : Arrays.copyOf(result, total);
|
||||
}
|
||||
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
|
||||
|
||||
result = new byte[total];
|
||||
int offset = 0;
|
||||
int remaining = total;
|
||||
for (byte[] b : bufs) {
|
||||
int len = Math.min(b.length, remaining);
|
||||
System.arraycopy(b, 0, result, offset, len);
|
||||
offset += len;
|
||||
remaining -= len;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ import jdk.test.lib.RandomFactory;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8080835
|
||||
* @bug 8080835 8193832
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main ReadAllBytes
|
||||
@ -47,15 +47,11 @@ public class ReadAllBytes {
|
||||
test(new byte[]{});
|
||||
test(new byte[]{1, 2, 3});
|
||||
test(createRandomBytes(1024));
|
||||
test(createRandomBytes((1 << 13) - 1));
|
||||
test(createRandomBytes((1 << 13)));
|
||||
test(createRandomBytes((1 << 13) + 1));
|
||||
test(createRandomBytes((1 << 15) - 1));
|
||||
test(createRandomBytes((1 << 15)));
|
||||
test(createRandomBytes((1 << 15) + 1));
|
||||
test(createRandomBytes((1 << 17) - 1));
|
||||
test(createRandomBytes((1 << 17)));
|
||||
test(createRandomBytes((1 << 17) + 1));
|
||||
for (int shift : new int[] {13, 14, 15, 17}) {
|
||||
for (int offset : new int[] {-1, 0, 1}) {
|
||||
test(createRandomBytes((1 << shift) + offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test(byte[] expectedBytes) throws IOException {
|
||||
|
Loading…
x
Reference in New Issue
Block a user