netty5/codec-http2/src/main/java/io/netty/handler/codec/http2
Jakob Buchgraber 6fd0a0c55f Faster and more memory efficient headers for HTTP, HTTP/2, STOMP and SPYD. Fixes #3600
Motivation:

We noticed that the headers implementation in Netty for HTTP/2 uses quite a lot of memory
and that also at least the performance of randomly accessing a header is quite poor. The main
concern however was memory usage, as profiling has shown that a DefaultHttp2Headers
not only use a lot of memory it also wastes a lot due to the underlying hashmaps having
to be resized potentially several times as new headers are being inserted.

This is tracked as issue #3600.

Modifications:
We redesigned the DefaultHeaders to simply take a Map object in its constructor and
reimplemented the class using only the Map primitives. That way the implementation
is very concise and hopefully easy to understand and it allows each concrete headers
implementation to provide its own map or to even use a different headers implementation
for processing requests and writing responses i.e. incoming headers need to provide
fast random access while outgoing headers need fast insertion and fast iteration. The
new implementation can support this with hardly any code changes. It also comes
with the advantage that if the Netty project decides to add a third party collections library
as a dependency, one can simply plug in one of those very fast and memory efficient map
implementations and get faster and smaller headers for free.

For now, we are using the JDK's TreeMap for HTTP and HTTP/2 default headers.

Result:

- Significantly fewer lines of code in the implementation. While the total commit is still
  roughly 400 lines less, the actual implementation is a lot less. I just added some more
  tests and microbenchmarks.

- Overall performance is up. The current implementation should be significantly faster
  for insertion and retrieval. However, it is slower when it comes to iteration. There is simply
  no way a TreeMap can have the same iteration performance as a linked list (as used in the
  current headers implementation). That's totally fine though, because when looking at the
  benchmark results @ejona86 pointed out that the performance of the headers is completely
  dominated by insertion, that is insertion is so significantly faster in the new implementation
  that it does make up for several times the iteration speed. You can't iterate what you haven't
  inserted. I am demonstrating that in this spreadsheet [1]. (Actually, iteration performance is
  only down for HTTP, it's significantly improved for HTTP/2).

- Memory is down. The implementation with TreeMap uses on avg ~30% less memory. It also does not
  produce any garbage while being resized. In load tests for GRPC we have seen a memory reduction
  of up to 1.2KB per RPC. I summarized the memory improvements in this spreadsheet [1]. The data
  was generated by [2] using JOL.

- While it was my original intend to only improve the memory usage for HTTP/2, it should be similarly
  improved for HTTP, SPDY and STOMP as they all share a common implementation.

[1] https://docs.google.com/spreadsheets/d/1ck3RQklyzEcCLlyJoqDXPCWRGVUuS-ArZf0etSXLVDQ/edit#gid=0
[2] https://gist.github.com/buchgr/4458a8bdb51dd58c82b4
2015-08-04 17:12:24 -07:00
..
CompressorHttp2ConnectionEncoder.java HTTP/2 CompressorHttp2ConnectionEncoder bug 2015-07-17 09:59:55 -07:00
DecoratingHttp2ConnectionDecoder.java Cleaning up the initialization of Http2ConnectionHandler 2015-03-30 11:23:02 -07:00
DecoratingHttp2ConnectionEncoder.java Cleaning up the initialization of Http2ConnectionHandler 2015-03-30 11:23:02 -07:00
DecoratingHttp2FrameWriter.java Cleaning up the initialization of Http2ConnectionHandler 2015-03-30 11:23:02 -07:00
DefaultHttp2Connection.java Make PrimitiveCollections generated for all primitive maps. 2015-07-27 06:59:23 -07:00
DefaultHttp2ConnectionDecoder.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
DefaultHttp2ConnectionEncoder.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
DefaultHttp2FrameReader.java Make IntObjectHashMap extend Map 2015-07-22 15:52:27 -07:00
DefaultHttp2FrameWriter.java Make PrimitiveCollections generated for all primitive maps. 2015-07-27 06:59:23 -07:00
DefaultHttp2Headers.java Faster and more memory efficient headers for HTTP, HTTP/2, STOMP and SPYD. Fixes #3600 2015-08-04 17:12:24 -07:00
DefaultHttp2HeadersDecoder.java HTTP/2 limit header accumulated size 2015-07-07 13:25:03 -07:00
DefaultHttp2HeadersEncoder.java Faster and more memory efficient headers for HTTP, HTTP/2, STOMP and SPYD. Fixes #3600 2015-08-04 17:12:24 -07:00
DefaultHttp2HeaderTableListSize.java Accept over 2^31-1 MAX_HEADER_LIST_SIZE 2015-07-10 10:58:41 -07:00
DefaultHttp2LocalFlowController.java HTTP/2 Thread Context Interface Clarifications 2015-07-17 12:40:36 -07:00
DefaultHttp2RemoteFlowController.java HTTP/2 Thread Context Interface Clarifications 2015-07-17 12:40:36 -07:00
DelegatingDecompressorFrameListener.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
EmptyHttp2Headers.java ByteString introduced as AsciiString super class 2015-04-14 16:35:17 -07:00
Http2ClientUpgradeCodec.java Make IntObjectHashMap extend Map 2015-07-22 15:52:27 -07:00
Http2CodecUtil.java Porting BufferingHttp2ConnectionEncoder from gRPC 2015-06-05 05:51:16 -07:00
Http2Connection.java [#3724] HTTP/2 Headers END_STREAM results in RST_STREAM 2015-05-07 08:31:05 -07:00
Http2ConnectionAdapter.java Include error code and message in GOAWAY events. 2015-03-31 09:18:26 -07:00
Http2ConnectionDecoder.java Cleaning up the initialization of Http2ConnectionHandler 2015-03-30 11:23:02 -07:00
Http2ConnectionEncoder.java Cleaning up the initialization of Http2ConnectionHandler 2015-03-30 11:23:02 -07:00
Http2ConnectionHandler.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
Http2DataWriter.java Http2DefaultFrameWriter direct write instead of copy 2015-02-06 11:56:14 -08:00
Http2Error.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2EventAdapter.java Include error code and message in GOAWAY events. 2015-03-31 09:18:26 -07:00
Http2Exception.java Http/2 Priority on CLOSED stream 2015-03-28 19:10:43 -07:00
Http2Flags.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2FlowController.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
Http2FrameAdapter.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2FrameListener.java Ignore frames for streams that may have previously existed. 2015-04-21 20:47:01 -07:00
Http2FrameListenerDecorator.java HTTP/2 Decoder reduce preface conditional checks 2015-03-28 18:52:35 -07:00
Http2FrameLogger.java Use standard syntax for logging HTTP/2 stream ID. 2015-07-28 09:54:14 -07:00
Http2FrameReader.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2FrameSizePolicy.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2FrameTypes.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2FrameWriter.java Http2DefaultFrameWriter direct write instead of copy 2015-02-06 11:56:14 -08:00
Http2Headers.java Faster and more memory efficient headers for HTTP, HTTP/2, STOMP and SPYD. Fixes #3600 2015-08-04 17:12:24 -07:00
Http2HeadersDecoder.java HTTP/2 limit header accumulated size 2015-07-07 13:25:03 -07:00
Http2HeadersEncoder.java ByteString introduced as AsciiString super class 2015-04-14 16:35:17 -07:00
Http2HeaderTable.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2InboundFrameLogger.java HTTP/2 Decoder reduce preface conditional checks 2015-03-28 18:52:35 -07:00
Http2LifecycleManager.java HTTP/2 Sending a GO_AWAY with an error code should close conneciton 2015-04-29 11:16:21 -07:00
Http2LocalFlowController.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
Http2NoMoreStreamIdsException.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2OutboundFrameLogger.java Fixing logging of ping acks in Http2OutboundFrameLogger 2015-05-20 08:59:17 -07:00
Http2PromisedRequestVerifier.java Http2 draft 17 2015-03-25 09:02:15 -07:00
Http2RemoteFlowController.java HTTP/2 Flow Controller should use Channel.isWritable() 2015-07-16 14:38:48 -07:00
Http2SecurityUtil.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
Http2ServerUpgradeCodec.java Lazily instantiate HttpServerUpgradeHandler.UpgradeCodec 2015-06-10 12:06:27 +09:00
Http2Settings.java Make IntObjectHashMap extend Map 2015-07-22 15:52:27 -07:00
Http2Stream.java Optimizing user-defined stream properties. 2015-04-23 12:41:14 -07:00
Http2StreamVisitor.java Removing direct access to HTTP/2 child streams. 2015-04-10 08:52:26 -07:00
HttpToHttp2ConnectionHandler.java Support conversion of HttpMessage and HttpContent to HTTP/2 Frames 2015-07-21 20:17:27 +02:00
HttpUtil.java Faster and more memory efficient headers for HTTP, HTTP/2, STOMP and SPYD. Fixes #3600 2015-08-04 17:12:24 -07:00
InboundHttp2ToHttpAdapter.java Include error code and message in GOAWAY events. 2015-03-31 09:18:26 -07:00
InboundHttp2ToHttpPriorityAdapter.java Faster and more memory efficient headers for HTTP, HTTP/2, STOMP and SPYD. Fixes #3600 2015-08-04 17:12:24 -07:00
package-info.java Back port HTTP/2 codec from master to 4.1 2015-01-23 11:06:11 -05:00
StreamBufferingEncoder.java Proper shutdown of HTTP2 encoder when channelInactive 2015-07-09 07:36:42 -07:00