Add PooledSlicedByteBuf and PooledDuplicatedByteBuf
Motivation: At the moment when calling slice(...) or duplicate(...) on a Pooled*ByteBuf a new SlicedByteBuf or DuplicatedByteBuf. This can create a lot of GC. Modifications: Add PooledSlicedByteBuf and PooledDuplicatedByteBuf which will be used when a PooledByteBuf is used. Result: Less GC.
This commit is contained in:
parent
a73a3ce7a6
commit
627831d658
@ -59,12 +59,20 @@ public abstract class AbstractDerivedByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean release() {
|
public final boolean release() {
|
||||||
return unwrap().release();
|
if (unwrap().release()) {
|
||||||
|
deallocate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean release(int decrement) {
|
public final boolean release(int decrement) {
|
||||||
return unwrap().release(decrement);
|
if (unwrap().release(decrement)) {
|
||||||
|
deallocate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,4 +84,9 @@ public abstract class AbstractDerivedByteBuf extends AbstractByteBuf {
|
|||||||
public ByteBuffer nioBuffer(int index, int length) {
|
public ByteBuffer nioBuffer(int index, int length) {
|
||||||
return unwrap().nioBuffer(index, length);
|
return unwrap().nioBuffer(index, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the wrapped {@link ByteBuf} was released due calling of {@link #release()} or {@link #release(int)}.
|
||||||
|
*/
|
||||||
|
protected void deallocate() { }
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,19 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
*/
|
*/
|
||||||
public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
||||||
|
|
||||||
private final ByteBuf buffer;
|
private ByteBuf buffer;
|
||||||
|
|
||||||
public DuplicatedByteBuf(ByteBuf buffer) {
|
public DuplicatedByteBuf(ByteBuf buffer) {
|
||||||
super(buffer.maxCapacity());
|
super(buffer.maxCapacity());
|
||||||
|
init(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
DuplicatedByteBuf(int maxCapacity) {
|
||||||
|
super(maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
final void init(ByteBuf buffer) {
|
||||||
|
maxCapacity(buffer.maxCapacity());
|
||||||
if (buffer instanceof DuplicatedByteBuf) {
|
if (buffer instanceof DuplicatedByteBuf) {
|
||||||
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
||||||
} else {
|
} else {
|
||||||
@ -45,6 +53,8 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||||
|
markReaderIndex();
|
||||||
|
markWriterIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,6 +70,16 @@ abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
|
|||||||
initThread = Thread.currentThread();
|
initThread = Thread.currentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf slice(int index, int length) {
|
||||||
|
return PooledSlicedByteBuf.newInstance(this, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf duplicate() {
|
||||||
|
return PooledDuplicatedByteBuf.newInstance(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int capacity() {
|
public final int capacity() {
|
||||||
return length;
|
return length;
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import io.netty.util.Recycler;
|
||||||
|
|
||||||
|
final class PooledDuplicatedByteBuf extends DuplicatedByteBuf {
|
||||||
|
|
||||||
|
private static final Recycler<PooledDuplicatedByteBuf> RECYCLER = new Recycler<PooledDuplicatedByteBuf>() {
|
||||||
|
@Override
|
||||||
|
protected PooledDuplicatedByteBuf newObject(Handle handle) {
|
||||||
|
return new PooledDuplicatedByteBuf(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PooledDuplicatedByteBuf newInstance(ByteBuf buffer) {
|
||||||
|
PooledDuplicatedByteBuf buf = RECYCLER.get();
|
||||||
|
buf.init(buffer);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Recycler.Handle recyclerHandle;
|
||||||
|
|
||||||
|
private PooledDuplicatedByteBuf(Recycler.Handle recyclerHandle) {
|
||||||
|
super(0);
|
||||||
|
this.recyclerHandle = recyclerHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf slice(int index, int length) {
|
||||||
|
return PooledSlicedByteBuf.newInstance(this, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf duplicate() {
|
||||||
|
return newInstance(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deallocate() {
|
||||||
|
RECYCLER.recycle(this, recyclerHandle);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import io.netty.util.Recycler;
|
||||||
|
|
||||||
|
final class PooledSlicedByteBuf extends SlicedByteBuf {
|
||||||
|
|
||||||
|
private static final Recycler<PooledSlicedByteBuf> RECYCLER = new Recycler<PooledSlicedByteBuf>() {
|
||||||
|
@Override
|
||||||
|
protected PooledSlicedByteBuf newObject(Handle handle) {
|
||||||
|
return new PooledSlicedByteBuf(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PooledSlicedByteBuf newInstance(ByteBuf buffer, int index, int length) {
|
||||||
|
PooledSlicedByteBuf buf = RECYCLER.get();
|
||||||
|
buf.init(buffer, index, length);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Recycler.Handle recyclerHandle;
|
||||||
|
|
||||||
|
private PooledSlicedByteBuf(Recycler.Handle recyclerHandle) {
|
||||||
|
super(0);
|
||||||
|
this.recyclerHandle = recyclerHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf slice(int index, int length) {
|
||||||
|
return newInstance(this, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf duplicate() {
|
||||||
|
return PooledDuplicatedByteBuf.newInstance(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deallocate() {
|
||||||
|
RECYCLER.recycle(this, recyclerHandle);
|
||||||
|
}
|
||||||
|
}
|
@ -34,12 +34,20 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
*/
|
*/
|
||||||
public class SlicedByteBuf extends AbstractDerivedByteBuf {
|
public class SlicedByteBuf extends AbstractDerivedByteBuf {
|
||||||
|
|
||||||
private final ByteBuf buffer;
|
private ByteBuf buffer;
|
||||||
private final int adjustment;
|
private int adjustment;
|
||||||
private final int length;
|
private int length;
|
||||||
|
|
||||||
public SlicedByteBuf(ByteBuf buffer, int index, int length) {
|
public SlicedByteBuf(ByteBuf buffer, int index, int length) {
|
||||||
super(length);
|
super(length);
|
||||||
|
init(buffer, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
SlicedByteBuf(int length) {
|
||||||
|
super(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
final void init(ByteBuf buffer, int index, int length) {
|
||||||
if (index < 0 || index > buffer.capacity() - length) {
|
if (index < 0 || index > buffer.capacity() - length) {
|
||||||
throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')');
|
throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')');
|
||||||
}
|
}
|
||||||
@ -55,8 +63,9 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
|
|||||||
adjustment = index;
|
adjustment = index;
|
||||||
}
|
}
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
maxCapacity(length);
|
||||||
writerIndex(length);
|
setIndex(0, length);
|
||||||
|
discardMarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user