[RFC] gzip: Default compress level changeable at build time.

Kang-Che Sung explorer09 at gmail.com
Thu Sep 5 17:46:16 UTC 2019


This introduces GZIP_DEFAULT_LEVEL macro so that builders can easily
change it by overriding (e.g. "-DGZIP_DEFAULT_LEVEL=8").

Currently, this patch is ugly. I apologize. (Because I utilize a lot
of preprocessor tricks in order to implement a build-time constant
table lookup.)

This is how I proposed letting the user change the compression level
when GZIP_LEVELS is turned off, when discussing about gzip default
compression level. This patch is a proof of concept of that.
<http://lists.busybox.net/pipermail/busybox/2019-September/087442.html>

Signed-off-by: Kang-Che Sung <explorer09 at gmail.com>
---
 archival/gzip.c | 50 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/archival/gzip.c b/archival/gzip.c
index 3966a06b4..10cf2f884 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -251,6 +251,17 @@ typedef unsigned IPos;
  * save space in the various tables. IPos is used only for parameter passing.
  */
 
+#define LEVEL_CONFIG_LIST \
+	/*             (level, good, chain_shift, lazy, nice) */ \
+	LEVEL_CONFIG_DEFINE(4,    4,           4,    4,   16) \
+	LEVEL_CONFIG_DEFINE(5,    8,           5,   16,   32) \
+	LEVEL_CONFIG_DEFINE(6,    8,           7,   16,  128) \
+	LEVEL_CONFIG_DEFINE(7,    8,           8,   32,  128) \
+	LEVEL_CONFIG_DEFINE(8,   32,          10,  128,  258) \
+	LEVEL_CONFIG_DEFINE(9,   32,          12,  258,  258)
+
+#define GZIP_DEFAULT_LEVEL 6
+
 enum {
 	WINDOW_SIZE = 2 * WSIZE,
 /* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
@@ -258,14 +269,25 @@ enum {
  */
 
 #if !ENABLE_FEATURE_GZIP_LEVELS
+# define LEVEL_CONFIG_DEFINE(level, good, chain_shift, lazy, nice) \
+	l##level##_chain = (1 << (chain_shift)), \
+	l##level##_lazy = (lazy), \
+	l##level##_good = (good), \
+	l##level##_nice = (nice),
+
+	LEVEL_CONFIG_LIST
+
+# define LEVEL_CONFIG_(level, suffix) l##level##suffix
+# define LEVEL_CONFIG(level, name) LEVEL_CONFIG_(level, _##name)
+
+	comp_level_minus4 = (GZIP_DEFAULT_LEVEL - 4),
 
-	comp_level_minus4 = 6 - 4,
-	max_chain_length = 128,
+	max_chain_length = LEVEL_CONFIG(GZIP_DEFAULT_LEVEL, chain),
 /* To speed up deflation, hash chains are never searched beyond this length.
  * A higher limit improves compression ratio but degrades the speed.
  */
 
-	max_lazy_match = 16,
+	max_lazy_match = LEVEL_CONFIG(GZIP_DEFAULT_LEVEL, lazy),
 /* Attempt to find a better match only when the current match is strictly
  * smaller than this value. This mechanism is used only for compression
  * levels >= 4.
@@ -277,7 +299,7 @@ enum {
  * max_insert_length is used only for compression levels <= 3.
  */
 
-	good_match = 8,
+	good_match = LEVEL_CONFIG(GZIP_DEFAULT_LEVEL, good),
 /* Use a faster search when the previous match is longer than this */
 
 /* Values for max_lazy_match, good_match and max_chain_length, depending on
@@ -286,12 +308,16 @@ enum {
  * found for specific files.
  */
 
-	nice_match = 128,	/* Stop searching when current match exceeds this */
+	nice_match = LEVEL_CONFIG(GZIP_DEFAULT_LEVEL, nice)
+/* Stop searching when current match exceeds this */
 /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
  * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
  * meaning.
  */
-#endif /* ENABLE_FEATURE_GZIP_LEVELS */
+# undef LEVEL_CONFIG_DEFINE
+# undef LEVEL_CONFIG_
+# undef LEVEL_CONFIG
+#endif /* !ENABLE_FEATURE_GZIP_LEVELS */
 };
 
 struct globals {
@@ -2204,12 +2230,10 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
 		uint8_t lazy2;
 		uint8_t nice2;
 	} gzip_level_config[6] = {
-		{4,   4,   4/2,  16/2}, /* Level 4 */
-		{8,   5,  16/2,  32/2}, /* Level 5 */
-		{8,   7,  16/2, 128/2}, /* Level 6 */
-		{8,   8,  32/2, 128/2}, /* Level 7 */
-		{32, 10, 128/2, 258/2}, /* Level 8 */
-		{32, 12, 258/2, 258/2}, /* Level 9 */
+# define LEVEL_CONFIG_DEFINE(level, good, chain_shift, lazy, nice) \
+		{(good), (chain_shift), (lazy)/2, (nice)/2},
+		LEVEL_CONFIG_LIST
+# undef LEVEL_CONFIG_DEFINE
 	};
 #endif
 
@@ -2229,7 +2253,7 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
 #if ENABLE_FEATURE_GZIP_LEVELS
 	opt >>= (BBUNPK_OPTSTRLEN IF_FEATURE_GZIP_DECOMPRESS(+ 2) + 1); /* drop cfkvq[dt]n bits */
 	if (opt == 0)
-		opt = 1 << 5; /* default: 6 */
+		opt = 1 << (GZIP_DEFAULT_LEVEL - 1);
 	opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */
 
 	comp_level_minus4 = opt;
-- 
2.18.0



More information about the busybox mailing list