From 8a1a0b2c1ecb145266e0a9ca66578811171a374d Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Mon, 11 May 2015 08:35:12 +0200 Subject: [PATCH] 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. --- .../netty/buffer/AbstractDerivedByteBuf.java | 17 +++++- .../io/netty/buffer/DuplicatedByteBuf.java | 12 +++- .../java/io/netty/buffer/PooledByteBuf.java | 10 ++++ .../netty/buffer/PooledDuplicatedByteBuf.java | 56 +++++++++++++++++++ .../io/netty/buffer/PooledSlicedByteBuf.java | 56 +++++++++++++++++++ .../java/io/netty/buffer/SlicedByteBuf.java | 19 +++++-- 6 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 buffer/src/main/java/io/netty/buffer/PooledDuplicatedByteBuf.java create mode 100644 buffer/src/main/java/io/netty/buffer/PooledSlicedByteBuf.java diff --git a/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java index d4d24f11b7..0573240d5b 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java @@ -47,12 +47,20 @@ public abstract class AbstractDerivedByteBuf extends AbstractByteBuf { @Override public final boolean release() { - return unwrap().release(); + if (unwrap().release()) { + deallocate(); + return true; + } + return false; } @Override public final boolean release(int decrement) { - return unwrap().release(decrement); + if (unwrap().release(decrement)) { + deallocate(); + return true; + } + return false; } @Override @@ -64,4 +72,9 @@ public abstract class AbstractDerivedByteBuf extends AbstractByteBuf { public ByteBuffer nioBuffer(int index, int 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() { } } diff --git a/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java b/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java index 43ff8b895c..55c4dd5bee 100644 --- a/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java @@ -31,11 +31,19 @@ import java.nio.channels.ScatteringByteChannel; */ public class DuplicatedByteBuf extends AbstractDerivedByteBuf { - private final ByteBuf buffer; + private ByteBuf buffer; public DuplicatedByteBuf(ByteBuf buffer) { super(buffer.maxCapacity()); + init(buffer); + } + DuplicatedByteBuf(int maxCapacity) { + super(maxCapacity); + } + + final void init(ByteBuf buffer) { + maxCapacity(buffer.maxCapacity()); if (buffer instanceof DuplicatedByteBuf) { this.buffer = ((DuplicatedByteBuf) buffer).buffer; } else { @@ -43,6 +51,8 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf { } setIndex(buffer.readerIndex(), buffer.writerIndex()); + markReaderIndex(); + markWriterIndex(); } @Override diff --git a/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java b/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java index d59916ddbe..069c6fd438 100644 --- a/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java @@ -68,6 +68,16 @@ abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { 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 public final int capacity() { return length; diff --git a/buffer/src/main/java/io/netty/buffer/PooledDuplicatedByteBuf.java b/buffer/src/main/java/io/netty/buffer/PooledDuplicatedByteBuf.java new file mode 100644 index 0000000000..ec6156b39e --- /dev/null +++ b/buffer/src/main/java/io/netty/buffer/PooledDuplicatedByteBuf.java @@ -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 RECYCLER = new Recycler() { + @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); + } +} diff --git a/buffer/src/main/java/io/netty/buffer/PooledSlicedByteBuf.java b/buffer/src/main/java/io/netty/buffer/PooledSlicedByteBuf.java new file mode 100644 index 0000000000..15932f9289 --- /dev/null +++ b/buffer/src/main/java/io/netty/buffer/PooledSlicedByteBuf.java @@ -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 RECYCLER = new Recycler() { + @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); + } +} diff --git a/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java b/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java index 4c109fe62e..5b87717e8d 100644 --- a/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java @@ -32,12 +32,20 @@ import java.nio.channels.ScatteringByteChannel; */ public class SlicedByteBuf extends AbstractDerivedByteBuf { - private final ByteBuf buffer; - private final int adjustment; - private final int length; + private ByteBuf buffer; + private int adjustment; + private int length; public SlicedByteBuf(ByteBuf buffer, int index, int 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) { throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')'); } @@ -53,8 +61,9 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf { adjustment = index; } this.length = length; - - writerIndex(length); + maxCapacity(length); + setIndex(0, length); + discardMarks(); } @Override