From: Aurelien DARRAGON Date: Tue, 11 Aug 2026 16:41:42 +0000 (+0200) Subject: IMPORT: slz/uslz: inline the bit reader and the huffman decoders X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3c9a9c6b56ff06d6430d06ff84569f6224f56cc;p=thirdparty%2Fhaproxy.git IMPORT: slz/uslz: inline the bit reader and the huffman decoders gethuff(), gethuff_fixed() and bit_accumulate() were all purposely marked noinline due to tests showing a significant performance decrease and code increase by inlining them. That's annoying because most of the arguments they need can easily be optimized once the compiler has a full view of them, and it's quite visible with perf top when decompressing an slz stream that 30% of the CPU is spent in gethuff_fixed() and bit_accumulate(), and that when decompressing a gzip stream, it's 62% in gethuff() alone! It turns out that it's only combinations of 1 or 2 of them inlined that ruins the performance, but inlining the 3 at once instead shrinks the code and boosts the performance by letting the compiler keep all these local variables in registers. As a proof, the code is now ~352 bytes smaller, and 13 to 17% faster (respectively for slz and gzip streams). That's one example of situations where individual changes bring nothing good. This is libslz upstream commit d1e73bed32b47ee43e91255126ab7fcf82a1e21b --- diff --git a/src/uslz.c b/src/uslz.c index f8e9db05c..a6be64ce5 100644 --- a/src/uslz.c +++ b/src/uslz.c @@ -214,7 +214,7 @@ static inline void uslz_update_crc(struct uslz_stream *state, const unsigned cha * * Returns 1 on success and 0 if more data is needed. */ -__attribute__((noinline)) static int bit_accumulate(const unsigned char **in_ptr, const unsigned char *in_top, unsigned char *num_bits, uint64_t *bit_accum) +static inline int bit_accumulate(const unsigned char **in_ptr, const unsigned char *in_top, unsigned char *num_bits, uint64_t *bit_accum) { if (*in_ptr >= in_top) return 0; @@ -233,7 +233,7 @@ __attribute__((noinline)) static int bit_accumulate(const unsigned char **in_ptr * * The decoded symbol is stored in . */ -__attribute__((noinline)) static int gethuff(unsigned int *huff_index, +static inline int gethuff(unsigned int *huff_index, const unsigned char **in_ptr, const unsigned char *in_top, unsigned char *num_bits, uint64_t *bit_accum, unsigned int *var, short *table) @@ -284,7 +284,7 @@ __attribute__((noinline)) static int gethuff(unsigned int *huff_index, * As with gethuff(), returns 1 when decoding is complete and 0 if it * needs more input data. */ -__attribute__((noinline)) static int gethuff_fixed(const unsigned char **in_ptr, const unsigned char *in_top, +static inline int gethuff_fixed(const unsigned char **in_ptr, const unsigned char *in_top, unsigned char *num_bits, uint64_t *bit_accum, unsigned int *var) {