Skip to content

Commit 54b8663

Browse files
authored
Remove unnecessary allocations and abstractions in HttpContentCompressor (#16211)
Motivation: When `HttpContentCompressor` is created, it allocates a map `Map<String, CompressionEncoderFactory> factories` and allocates decoder factories, which are used only for the factory method pattern and don't hold any state. <img width="472" height="90" alt="image" src="https://github.com/user-attachments/assets/48832492-be18-4cc0-8ffe-c593bf2799ce" /> Modification: - Removed `Map<String, CompressionEncoderFactory> factories` variable and code that filled it in the `HttpContentCompressor` constructor - Replaced `factories.get()` invocation with a switch statement and inlined factory methods `CompressionEncoderFactory.createEncoder()` calls in it - Removed `CompressionEncoderFactory` Result: No more unnecessary allocations in `HttpContentCompressor`.
1 parent 961f427 commit 54b8663

2 files changed

Lines changed: 47 additions & 120 deletions

File tree

codec-http/src/main/java/io/netty/handler/codec/http/CompressionEncoderFactory.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java

Lines changed: 47 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,14 @@
3030
import io.netty.handler.codec.compression.SnappyOptions;
3131
import io.netty.handler.codec.compression.StandardCompressionOptions;
3232
import io.netty.handler.codec.compression.ZlibCodecFactory;
33-
import io.netty.handler.codec.compression.ZlibEncoder;
3433
import io.netty.handler.codec.compression.ZlibWrapper;
3534
import io.netty.handler.codec.compression.Zstd;
3635
import io.netty.handler.codec.compression.ZstdEncoder;
3736
import io.netty.handler.codec.compression.ZstdOptions;
3837
import io.netty.util.internal.ObjectUtil;
3938

4039
import java.util.ArrayList;
41-
import java.util.HashMap;
4240
import java.util.List;
43-
import java.util.Map;
4441

4542
import static io.netty.util.internal.ObjectUtil.checkInRange;
4643

@@ -61,7 +58,6 @@ public class HttpContentCompressor extends HttpContentEncoder {
6158

6259
private final int contentSizeThreshold;
6360
private ChannelHandlerContext ctx;
64-
private final Map<String, CompressionEncoderFactory> factories;
6561

6662
private static final CompressionOptions[] DEFAULT_COMPRESSION_OPTIONS;
6763
static {
@@ -228,24 +224,6 @@ public HttpContentCompressor(int contentSizeThreshold, CompressionOptions... com
228224
this.brotliOptions = brotliOptions;
229225
this.zstdOptions = zstdOptions;
230226
this.snappyOptions = snappyOptions;
231-
232-
this.factories = new HashMap<>();
233-
234-
if (this.gzipOptions != null) {
235-
this.factories.put("gzip", new GzipEncoderFactory());
236-
}
237-
if (this.deflateOptions != null) {
238-
this.factories.put("deflate", new DeflateEncoderFactory());
239-
}
240-
if (Brotli.isAvailable() && this.brotliOptions != null) {
241-
this.factories.put("br", new BrEncoderFactory());
242-
}
243-
if (this.zstdOptions != null) {
244-
this.factories.put("zstd", new ZstdEncoderFactory());
245-
}
246-
if (this.snappyOptions != null) {
247-
this.factories.put("snappy", new SnappyEncoderFactory());
248-
}
249227
}
250228

251229
@Deprecated
@@ -291,22 +269,62 @@ protected Result beginEncode(HttpResponse httpResponse, String acceptEncoding) t
291269
return null;
292270
}
293271

294-
CompressionEncoderFactory encoderFactory = factories.get(targetContentEncoding);
295-
296-
if (encoderFactory == null) {
297-
throw new IllegalStateException("Couldn't find CompressionEncoderFactory: " + targetContentEncoding);
298-
}
299-
300272
Channel channel = ctx.channel();
301273
return new Result(targetContentEncoding,
302274
EmbeddedChannel.builder()
303275
.channelId(channel.id())
304276
.hasDisconnect(channel.metadata().hasDisconnect())
305277
.config(channel.config())
306-
.handlers(encoderFactory.createEncoder())
278+
.handlers(createEncoderFor(targetContentEncoding))
307279
.build());
308280
}
309281

282+
private MessageToByteEncoder<ByteBuf> createEncoderFor(String targetContentEncoding) {
283+
switch (targetContentEncoding) {
284+
case "br":
285+
if (brotliOptions == null || !Brotli.isAvailable()) {
286+
throw new IllegalStateException("Brotli not configured");
287+
}
288+
return new BrotliEncoder(brotliOptions.parameters());
289+
case "zstd":
290+
if (zstdOptions == null) {
291+
throw new IllegalStateException("Zstd not configured");
292+
}
293+
return new ZstdEncoder(
294+
zstdOptions.compressionLevel(),
295+
zstdOptions.blockSize(),
296+
zstdOptions.maxEncodeSize()
297+
);
298+
case "snappy":
299+
if (snappyOptions == null) {
300+
throw new IllegalStateException("Snappy not configured");
301+
}
302+
return new SnappyFrameEncoder();
303+
case "gzip":
304+
if (gzipOptions == null) {
305+
throw new IllegalStateException("Gzip not configured");
306+
}
307+
return ZlibCodecFactory.newZlibEncoder(
308+
ZlibWrapper.GZIP,
309+
gzipOptions.compressionLevel(),
310+
gzipOptions.windowBits(),
311+
gzipOptions.memLevel()
312+
);
313+
case "deflate":
314+
if (deflateOptions == null) {
315+
throw new IllegalStateException("Deflate not configured");
316+
}
317+
return ZlibCodecFactory.newZlibEncoder(
318+
ZlibWrapper.ZLIB,
319+
deflateOptions.compressionLevel(),
320+
deflateOptions.windowBits(),
321+
deflateOptions.memLevel()
322+
);
323+
default:
324+
throw new IllegalStateException("Unknown encoding: " + targetContentEncoding);
325+
}
326+
}
327+
310328
@SuppressWarnings("FloatingPointEquality")
311329
protected String determineEncoding(String acceptEncoding) {
312330
float starQ = -1.0f;
@@ -425,68 +443,4 @@ protected ZlibWrapper determineWrapper(String acceptEncoding) {
425443
return null;
426444
}
427445

428-
/**
429-
* Compression Encoder Factory that creates {@link ZlibEncoder}s
430-
* used to compress http content for gzip content encoding
431-
*/
432-
private final class GzipEncoderFactory implements CompressionEncoderFactory {
433-
434-
@Override
435-
public MessageToByteEncoder<ByteBuf> createEncoder() {
436-
return ZlibCodecFactory.newZlibEncoder(
437-
ZlibWrapper.GZIP, gzipOptions.compressionLevel(),
438-
gzipOptions.windowBits(), gzipOptions.memLevel());
439-
}
440-
}
441-
442-
/**
443-
* Compression Encoder Factory that creates {@link ZlibEncoder}s
444-
* used to compress http content for deflate content encoding
445-
*/
446-
private final class DeflateEncoderFactory implements CompressionEncoderFactory {
447-
448-
@Override
449-
public MessageToByteEncoder<ByteBuf> createEncoder() {
450-
return ZlibCodecFactory.newZlibEncoder(
451-
ZlibWrapper.ZLIB, deflateOptions.compressionLevel(),
452-
deflateOptions.windowBits(), deflateOptions.memLevel());
453-
}
454-
}
455-
456-
/**
457-
* Compression Encoder Factory that creates {@link BrotliEncoder}s
458-
* used to compress http content for br content encoding
459-
*/
460-
private final class BrEncoderFactory implements CompressionEncoderFactory {
461-
462-
@Override
463-
public MessageToByteEncoder<ByteBuf> createEncoder() {
464-
return new BrotliEncoder(brotliOptions.parameters());
465-
}
466-
}
467-
468-
/**
469-
* Compression Encoder Factory for create {@link ZstdEncoder}
470-
* used to compress http content for zstd content encoding
471-
*/
472-
private final class ZstdEncoderFactory implements CompressionEncoderFactory {
473-
474-
@Override
475-
public MessageToByteEncoder<ByteBuf> createEncoder() {
476-
return new ZstdEncoder(zstdOptions.compressionLevel(),
477-
zstdOptions.blockSize(), zstdOptions.maxEncodeSize());
478-
}
479-
}
480-
481-
/**
482-
* Compression Encoder Factory for create {@link SnappyFrameEncoder}
483-
* used to compress http content for snappy content encoding
484-
*/
485-
private static final class SnappyEncoderFactory implements CompressionEncoderFactory {
486-
487-
@Override
488-
public MessageToByteEncoder<ByteBuf> createEncoder() {
489-
return new SnappyFrameEncoder();
490-
}
491-
}
492446
}

0 commit comments

Comments
 (0)