我应该重用 DatagramPacket 吗?
Should I reuse DatagramPacket?
我正在构建一个基于 UDP 的应用程序来接收和发送多个数据包。
我可以为每次发送构建一个新的 DatagramPacket
,或者在我的应用程序的生命周期中回收一个实例。
- 重用
DatagramPacket
有什么好处吗? (例如内存分配)
- 有什么潜在的问题吗? (例如线程安全)
看来你做不到。我只是尝试发送相同的 DatagramPacket
两次,我得到以下行为:
- 数据包只发送一次
- Netty 记录以下警告
因此,您可以重用传递给 DatagramPacket
构造函数的参数,而不是重用 DatagramPacket
,主要是缓冲区。
2018-10-18 09:29:11.103 WARN 5468 --- [nioEventLoopGroup-2-1]
i.n.c.AbstractChannelHandlerContext : Failed to mark a promise as
failure because it has failed already:
DefaultChannelPromise@748a9b0e(failure:
java.lang.IndexOutOfBoundsException: srcIndex: 0), unnotified cause:
java.lang.IndexOutOfBoundsException: srcIndex: 0
at io.netty.buffer.UnsafeByteBufUtil.setBytes(UnsafeByteBufUtil.java:519)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:260)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1080)
at io.netty.channel.nio.AbstractNioChannel.newDirectBuffer(AbstractNioChannel.java:481)
at io.netty.channel.socket.nio.NioDatagramChannel.filterOutboundMessage(NioDatagramChannel.java:308)
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:877)
at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1391)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
at io.netty.channel.AbstractChannelHandlerContext.access00(AbstractChannelHandlerContext.java:38)
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1081)
at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1128)
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1070)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446)
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:884)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.buffer.AbstractReferenceCountedByteBuf.release0(AbstractReferenceCountedByteBuf.java:100)
~[netty-buffer-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:84)
~[netty-buffer-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88)
~[netty-common-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.DefaultAddressedEnvelope.release(DefaultAddressedEnvelope.java:101)
~[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88)
~[netty-common-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:884)
~[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1391)
~[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannelHandlerContext.access00(AbstractChannelHandlerContext.java:38)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1081)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1128)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1070)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
[netty-common-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
[netty-common-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446)
[netty-transport-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:884)
[netty-common-4.1.29.Final.jar!/:4.1.29.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
[netty-common-4.1.29.Final.jar!/:4.1.29.Final]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
我正在构建一个基于 UDP 的应用程序来接收和发送多个数据包。
我可以为每次发送构建一个新的 DatagramPacket
,或者在我的应用程序的生命周期中回收一个实例。
- 重用
DatagramPacket
有什么好处吗? (例如内存分配) - 有什么潜在的问题吗? (例如线程安全)
看来你做不到。我只是尝试发送相同的 DatagramPacket
两次,我得到以下行为:
- 数据包只发送一次
- Netty 记录以下警告
因此,您可以重用传递给 DatagramPacket
构造函数的参数,而不是重用 DatagramPacket
,主要是缓冲区。
2018-10-18 09:29:11.103 WARN 5468 --- [nioEventLoopGroup-2-1] i.n.c.AbstractChannelHandlerContext : Failed to mark a promise as failure because it has failed already: DefaultChannelPromise@748a9b0e(failure: java.lang.IndexOutOfBoundsException: srcIndex: 0), unnotified cause: java.lang.IndexOutOfBoundsException: srcIndex: 0 at io.netty.buffer.UnsafeByteBufUtil.setBytes(UnsafeByteBufUtil.java:519) at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:260) at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1080) at io.netty.channel.nio.AbstractNioChannel.newDirectBuffer(AbstractNioChannel.java:481) at io.netty.channel.socket.nio.NioDatagramChannel.filterOutboundMessage(NioDatagramChannel.java:308) at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:877) at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1391) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730) at io.netty.channel.AbstractChannelHandlerContext.access00(AbstractChannelHandlerContext.java:38) at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1081) at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1128) at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1070) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446) at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:884) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748)
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 at io.netty.buffer.AbstractReferenceCountedByteBuf.release0(AbstractReferenceCountedByteBuf.java:100) ~[netty-buffer-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:84) ~[netty-buffer-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88) ~[netty-common-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.DefaultAddressedEnvelope.release(DefaultAddressedEnvelope.java:101) ~[netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88) ~[netty-common-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:884) ~[netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1391) ~[netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.access00(AbstractChannelHandlerContext.java:38) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1081) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1128) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1070) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) [netty-common-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) [netty-common-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446) [netty-transport-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:884) [netty-common-4.1.29.Final.jar!/:4.1.29.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.29.Final.jar!/:4.1.29.Final] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]