I've been trying to write a simple HTTP-based RPC server using Netty 3.2.1. I basically took the Snoop example server and deleted code from it :-)<div><br></div><div>I profiled my application and found that a lot of time was being spent in HttpRequestDecoder.decode. More specifically, it seems to be spinning on ReplayingDecoderBuffer.readUnsignedByte (and its callee checkReadableBytes). Has anyone run into this before?</div>
<div><br></div><div>This is my pipeline:</div><div><br></div><div>ChannelPipeline pipeline = pipeline();</div><div><div>pipeline.addLast("decoder", new HttpRequestDecoder());</div><div>pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));</div>
<div>pipeline.addLast("encoder", new HttpResponseEncoder());</div><div>pipeline.addLast("deflater", new HttpContentCompressor());</div><div>HTTPRequestHandler handler = new HTTPRequestHandler();</div><div>
handler.setBridge(bridge);</div><div>pipeline.addLast("handler", handler);</div></div><div><br></div><div>And this is the relevant part of my handler:</div><div><br></div><div><div>public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) throws Exception {</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>HttpRequest request = (HttpRequest) event.getMessage();</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>ChannelBuffer content = request.getContent();</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>String contentString = content.toString(CharsetUtil.UTF_8);</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>String rpcResponse = bridge.performRPC(contentString);</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Decide whether to close the connection or not.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>boolean keepAlive = isKeepAlive(request);</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Build the response object.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>response.setContent(ChannelBuffers.copiedBuffer(rpcResponse, CharsetUtil.UTF_8));</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if (keepAlive) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Add 'Content-Length' header only for a keep-alive connection.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div>
<br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Write the response.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>ChannelFuture future = event.getChannel().write(response);</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Close the non-keep-alive connection after the write operation is done.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if (!keepAlive) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>future.addListener(ChannelFutureListener.CLOSE);</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div>}</div></div><div><br>
</div><div>The expensive code path goes through future.addListener(); I've attached a clumsy pair of screenshots from my profiler (YourKit 8.x).</div><div><br></div><div>Thanks very much for your time.</div>