From f8b15699d654c8ace6819287dcdd3c8e493b7f6c Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Fri, 3 Jun 2022 13:47:34 -0300 Subject: [PATCH] Reduce the scope for SW usage on length threshold When compressing/decompressing large amounts of data, the first call to deflate()/inflate() may not have data enough to pass the threshold, causing libnxz to fallback to software prematurely. We can only take that decision if the software indicates that all the input has been made available, i.e. when flush == Z_FINISH. Signed-off-by: Tulio Magno Quites Machado Filho --- lib/nx_deflate.c | 3 ++- lib/nx_inflate.c | 3 ++- lib/nx_zlib.h | 27 +++++++++++++++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/nx_deflate.c b/lib/nx_deflate.c index f2d5222..05b3580 100644 --- a/lib/nx_deflate.c +++ b/lib/nx_deflate.c @@ -1534,7 +1534,8 @@ int nx_deflate(z_streamp strm, int flush) return Z_STREAM_ERROR; /* check for sw deflate first */ - if( (has_nx_state(strm)) && s->switchable && (0 == use_nx_deflate(strm))){ + if (has_nx_state(strm) && s->switchable + && (0 == use_nx_deflate(strm, flush))) { /* Use software zlib, switch the sw and hw state */ s = (nx_streamp) strm->state; s->switchable = 0; /* decided to use sw zlib and not switchable */ diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c index 6dac0ad..d59d5db 100644 --- a/lib/nx_inflate.c +++ b/lib/nx_inflate.c @@ -289,7 +289,8 @@ int nx_inflate(z_streamp strm, int flush) if (s == NULL) return Z_STREAM_ERROR; /* check for sw deflate first*/ - if(has_nx_state(strm) && s->switchable && (0 == use_nx_inflate(strm))){ + if (has_nx_state(strm) && s->switchable + && (0 == use_nx_inflate(strm, flush))) { /*Use software zlib, switch the sw and hw state*/ s = (nx_streamp) strm->state; s->switchable = 0; /* decided to use sw zlib and not switchable */ diff --git a/lib/nx_zlib.h b/lib/nx_zlib.h index 7550c65..2c0bdb5 100644 --- a/lib/nx_zlib.h +++ b/lib/nx_zlib.h @@ -341,7 +341,7 @@ static inline int has_nx_state(z_streamp strm) return (nx_state->magic1 == MAGIC1); } -static inline int use_nx_inflate(z_streamp strm) +static inline int use_nx_inflate(z_streamp strm, int flush) { uint64_t rnd; assert(strm != NULL); @@ -349,8 +349,13 @@ static inline int use_nx_inflate(z_streamp strm) if(nx_config.mode.inflate == GZIP_NX) return 1; if(nx_config.mode.inflate == GZIP_SW) return 0; - /* #1 Threshold */ - if(strm->avail_in <= DECOMPRESS_THRESHOLD) return 0; + /* #2 Length threshold + Even when decompressing a large amount of data, the first call to + inflate() may not have enough input. So, avoid switching to software + decompression prematurely unless there is a guarantee that all the + input has been provided, i.e. when using Z_FINISH. */ + if(flush == Z_FINISH && strm->avail_in <= DECOMPRESS_THRESHOLD) + return 0; if(nx_config.mode.inflate == GZIP_AUTO) return 1; @@ -363,15 +368,21 @@ static inline int use_nx_inflate(z_streamp strm) } } -static inline int use_nx_deflate(z_streamp strm) +static inline int use_nx_deflate(z_streamp strm, int flush) { assert(strm != NULL); - if(nx_config.mode.deflate == GZIP_NX) return 1; - if(nx_config.mode.deflate == GZIP_SW) return 0; + if(nx_config.mode.deflate == GZIP_NX) return 1; + if(nx_config.mode.deflate == GZIP_SW) return 0; + + /* #2 Length threshold + Even when compressing a large amount of data, the first call to + deflate() may not have enough input. So, avoid switching to software + compression prematurely unless there is a guarantee that all the + input has been provided, i.e. when using Z_FINISH. */ + if(flush == Z_FINISH && strm->avail_in <= COMPRESS_THRESHOLD) + return 0; - /* #1 Threshold */ - if(strm->avail_in <= COMPRESS_THRESHOLD) return 0; return 1; } -- 2.35.3