From f0ad07973797592b741dd97c6137b2097bc71b5e Mon Sep 17 00:00:00 2001 From: Luke Wood Date: Mon, 17 Jun 2013 20:35:17 +0100 Subject: [PATCH] SCTP: Reduce object allocation overhead and fix receive buffer allocation There are a couple of changes here all related to making the SCTP transport less garbage-heavy: - Remove the SctpNotificationEvent and just passes along the JDK NIO Notification, as passing the Notification and always null inside a wrapped object seemed a little bit superfluous - Apply @trustin's changes to receive buffer allocation to SCTP transport, and also makes the SCTP transport use the configured buffer allocator rather than always creating a direct buffer (which seems like a bug) --- .../channel/sctp/SctpNotificationEvent.java | 105 ------------------ .../channel/sctp/SctpNotificationHandler.java | 14 +-- .../channel/sctp/nio/NioSctpChannel.java | 12 +- .../channel/sctp/oio/OioSctpChannel.java | 11 +- .../sctp/oio/OioSctpServerChannel.java | 4 +- 5 files changed, 30 insertions(+), 116 deletions(-) delete mode 100644 transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationEvent.java diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationEvent.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationEvent.java deleted file mode 100644 index 75529debdb..0000000000 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationEvent.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2011 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.channel.sctp; - -import com.sun.nio.sctp.Notification; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; - -/** - * A Notification event which carries a {@link Notification} from the SCTP stack to a SCTP {@link ChannelPipeline}. - *

- * Following notifications may be supported by a {@link SctpChannel}; - * AssociationChangeNotification, PeerAddressChangeNotification, SendFailedNotification, ShutdownNotification and - * additional implementation specific notifications. - *

- * - *

- * User can handle the notification events of a {@link SctpChannel} by override the following method - * {@link ChannelHandler#userEventTriggered(ChannelHandlerContext, Object)}. - *

- */ -public final class SctpNotificationEvent { - private final Notification notification; - private final Object attachment; - - /** - * Create a new instance - * - * @param notification the {@link Notification} which triggered this event - * @param attachment the attachment or {@code null} if non is attached. - */ - public SctpNotificationEvent(Notification notification, Object attachment) { - if (notification == null) { - throw new NullPointerException("notification"); - } - this.notification = notification; - this.attachment = attachment; - } - - /** - * Return the {@link Notification} - */ - public Notification notification() { - return notification; - } - - /** - * Return the attachment of this {@link SctpNotificationEvent}, or - * {@code null} if no attachment was provided - */ - public Object attachment() { - return attachment; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - SctpNotificationEvent that = (SctpNotificationEvent) o; - - if (!attachment.equals(that.attachment)) { - return false; - } - - if (!notification.equals(that.notification)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = notification.hashCode(); - result = 31 * result + attachment.hashCode(); - return result; - } - - @Override - public String toString() { - return "SctpNotification{" + - "notification=" + notification + - ", attachment=" + attachment + - '}'; - } -} diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationHandler.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationHandler.java index e88d37c8bc..11a52720ad 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationHandler.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpNotificationHandler.java @@ -28,7 +28,7 @@ import io.netty.channel.ChannelPipeline; /** * {@link AbstractNotificationHandler} implementation which will handle all {@link Notification}s by trigger a - * {@link SctpNotificationEvent} in the {@link ChannelPipeline} of a {@link SctpChannel}. + * {@link Notification} user event in the {@link ChannelPipeline} of a {@link SctpChannel}. */ public final class SctpNotificationHandler extends AbstractNotificationHandler { @@ -43,31 +43,31 @@ public final class SctpNotificationHandler extends AbstractNotificationHandler notificationHandler; + private RecvByteBufAllocator.Handle allocHandle; + private static SctpChannel newSctpChannel() { try { return SctpChannel.open(); @@ -260,7 +263,12 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett @Override protected int doReadMessages(MessageList buf) throws Exception { SctpChannel ch = javaChannel(); - ByteBuf buffer = alloc().directBuffer(config().getReceiveBufferSize()); + + RecvByteBufAllocator.Handle allocHandle = this.allocHandle; + if (allocHandle == null) { + this.allocHandle = allocHandle = config().getRecvByteBufAllocator().newHandle(); + } + ByteBuf buffer = allocHandle.allocate(config().getAllocator()); boolean free = true; try { ByteBuffer data = buffer.nioBuffer(buffer.writerIndex(), buffer.writableBytes()); @@ -277,6 +285,8 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett PlatformDependent.throwException(cause); return -1; } finally { + int bytesRead = buffer.readableBytes(); + allocHandle.record(bytesRead); if (free) { buffer.release(); } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpChannel.java b/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpChannel.java index b818673285..09ac4d09d4 100755 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpChannel.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpChannel.java @@ -26,6 +26,7 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelMetadata; import io.netty.channel.ChannelPromise; import io.netty.channel.MessageList; +import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.oio.AbstractOioMessageChannel; import io.netty.channel.sctp.DefaultSctpChannelConfig; import io.netty.channel.sctp.SctpChannelConfig; @@ -72,6 +73,8 @@ public class OioSctpChannel extends AbstractOioMessageChannel private final NotificationHandler notificationHandler; + private RecvByteBufAllocator.Handle allocHandle; + private static SctpChannel openChannel() { try { return SctpChannel.open(); @@ -182,7 +185,11 @@ public class OioSctpChannel extends AbstractOioMessageChannel Set reableKeys = readSelector.selectedKeys(); try { for (SelectionKey ignored : reableKeys) { - ByteBuf buffer = alloc().directBuffer(config().getReceiveBufferSize()); + RecvByteBufAllocator.Handle allocHandle = this.allocHandle; + if (allocHandle == null) { + this.allocHandle = allocHandle = config().getRecvByteBufAllocator().newHandle(); + } + ByteBuf buffer = allocHandle.allocate(config().getAllocator()); boolean free = true; try { @@ -199,6 +206,8 @@ public class OioSctpChannel extends AbstractOioMessageChannel } catch (Throwable cause) { PlatformDependent.throwException(cause); } finally { + int bytesRead = buffer.readableBytes(); + allocHandle.record(bytesRead); if (free) { buffer.release(); } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpServerChannel.java b/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpServerChannel.java index 85b0d5b514..f3673f424f 100755 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpServerChannel.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpServerChannel.java @@ -17,7 +17,6 @@ package io.netty.channel.sctp.oio; import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpServerChannel; -import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelException; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelMetadata; @@ -26,6 +25,7 @@ import io.netty.channel.MessageList; import io.netty.channel.oio.AbstractOioMessageChannel; import io.netty.channel.sctp.DefaultSctpServerChannelConfig; import io.netty.channel.sctp.SctpServerChannelConfig; +import io.netty.util.ReferenceCountUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -299,7 +299,7 @@ public class OioSctpServerChannel extends AbstractOioMessageChannel protected int doWrite(MessageList msgs, int index) throws Exception { int size = msgs.size(); for (int i = index; i < size; i ++) { - ByteBufUtil.release(msgs.get(i)); + ReferenceCountUtil.release(msgs.get(i)); } throw new UnsupportedOperationException(); }