ebiggers / libdeflate

Heavily optimized library for DEFLATE/zlib/gzip compression and decompression
MIT License
969 stars 164 forks source link

Allow controlling the setting at which libdeflate only emits an uncompressed deflate stream #67

Open astei opened 4 years ago

astei commented 4 years ago

libdeflate has truly entered the mainstream when it pops up in Minecraft, as I do in Velocity 1.1.0. In Minecraft, there is a need for fast, real-time compression, and libdeflate fills an important need for accelerating the zlib/deflate-based compression used by the game's protocol.

I recently ran across a need to use libdeflate in the protocol of Minecraft: Bedrock Edition. This game is... strange, and it's not a natural fit for libdeflate's block-based decompression. In this particular edition of the game, though, everything is deflate-compressed and this wastes CPU. While libdeflate by default only emits uncompressed deflate streams for inputs that are less than 16 bytes in length, this still wastes quite a bit of CPU on our end for the small packets the game often sends and we had a need to raise this to 128 bytes. For now, we run a modified libdeflate where we patched the relevant check but we'd like to make it configurable if possible so we can run vanilla libdeflate.

Thanks for making this library, it's greatly appreciated.

ebiggers commented 4 years ago

Which compression level are you using? I think the cutoff to skip compression shouldn't be fixed at 16 bytes, but rather it should depend on the compression level. The lower (faster) the level, the higher the cutoff should be. That would be an easy change to make.

But, presumably you're interested in minimizing decompression time too, not just compression time. So that would be an argument for also making this configurable independent of compression level.

There's also been a request to allow user control over the minimum match length (https://github.com/ebiggers/libdeflate/issues/57). Probably the way to go to support both of these requests would be to add a new function to allocate a libdeflate_compressor which allows for future extension, e.g.:

    struct libdeflate_compression_params {
            uint32_t level;
            uint32_t min_match_len;
            uint32_t min_compressed_block_len;
    };

    LIBDEFLATEEXPORT struct libdeflate_compressor * LIBDEFLATEAPI
    libdeflate_alloc_compressor_ex(const struct libdeflate_compression_params *params,
                                   size_t params_size);
astei commented 4 years ago

We currently use compression level 4 (planning to raise this to 6). Compression time and decompression time are important, since a lot of people play on lower-end devices (though we don't control the clients at all).

A libdeflate_alloc_compressor_ex function sounds like something that would be a good idea.