Skip to content

Commit 7085a30

Browse files
committed
Improve capacity calculcation in DefaultDataBuffer
This commit improves the capacity calculation for the DefaultDataBuffer, so that the capacity typically doubles instead of improving by the minimal required amount. Issue: SPR-15647
1 parent 3373a3f commit 7085a30

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

spring-core/src/main/java/org/springframework/core/io/buffer/DefaultDataBuffer.java

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,11 @@
3939
*/
4040
public class DefaultDataBuffer implements DataBuffer {
4141

42+
private static final int MAX_CAPACITY = Integer.MAX_VALUE;
43+
44+
private static final int CAPACITY_THRESHOLD = 1024 * 1024 * 4;
45+
46+
4247
private final DefaultDataBufferFactory dataBufferFactory;
4348

4449
private ByteBuffer byteBuffer;
@@ -259,17 +264,45 @@ public OutputStream asOutputStream() {
259264
}
260265

261266
private void ensureExtraCapacity(int extraCapacity) {
262-
int neededCapacity = this.writePosition + extraCapacity;
267+
int neededCapacity = calculateCapacity(this.writePosition + extraCapacity);
263268
if (neededCapacity > this.byteBuffer.capacity()) {
264269
grow(neededCapacity);
265270
}
266271
}
267272

268-
void grow(int minCapacity) {
273+
/**
274+
* @see io.netty.buffer.AbstractByteBufAllocator#calculateNewCapacity(int, int)
275+
*/
276+
private int calculateCapacity(int neededCapacity) {
277+
Assert.isTrue(neededCapacity >= 0, "'neededCapacity' must >= 0");
278+
279+
if (neededCapacity == CAPACITY_THRESHOLD) {
280+
return CAPACITY_THRESHOLD;
281+
}
282+
else if (neededCapacity > CAPACITY_THRESHOLD) {
283+
int newCapacity = neededCapacity / CAPACITY_THRESHOLD * CAPACITY_THRESHOLD;
284+
if (newCapacity > MAX_CAPACITY - CAPACITY_THRESHOLD) {
285+
newCapacity = MAX_CAPACITY;
286+
}
287+
else {
288+
newCapacity += CAPACITY_THRESHOLD;
289+
}
290+
return newCapacity;
291+
}
292+
else {
293+
int newCapacity = 64;
294+
while (newCapacity < neededCapacity) {
295+
newCapacity <<= 1;
296+
}
297+
return Math.min(newCapacity, MAX_CAPACITY);
298+
}
299+
}
300+
301+
void grow(int capacity) {
269302
ByteBuffer oldBuffer = this.byteBuffer;
270303
ByteBuffer newBuffer =
271-
(oldBuffer.isDirect() ? ByteBuffer.allocateDirect(minCapacity) :
272-
ByteBuffer.allocate(minCapacity));
304+
(oldBuffer.isDirect() ? ByteBuffer.allocateDirect(capacity) :
305+
ByteBuffer.allocate(capacity));
273306

274307
// Explicit cast for compatibility with covariant return type on JDK 9's ByteBuffer
275308
final int remaining = readableByteCount();
@@ -362,7 +395,7 @@ private static class SlicedDefaultDataBuffer extends DefaultDataBuffer {
362395
}
363396

364397
@Override
365-
void grow(int minCapacity) {
398+
void grow(int capacity) {
366399
throw new UnsupportedOperationException(
367400
"Growing the capacity of a sliced buffer is not supported");
368401
}

0 commit comments

Comments
 (0)