From a8e364db33c9d5db171f95ce3bd1ae81ff8b69f4 Mon Sep 17 00:00:00 2001 From: Takahiro Ueda Date: Tue, 18 Jun 2024 21:32:22 +0900 Subject: [PATCH 1/5] build: configure to use the zstd library - Add zstd as a submodule at extern/zstd. Use only zstd/zlibWrapper. Clone during configuration if not already cloned. - Add a new configure option --with-zstd (default: check). Define WITHZSTD and build zstd/zlibWrapper. - Use the subdir-objects Automake option if appropriate. --- .gitmodules | 3 +++ configure.ac | 46 ++++++++++++++++++++++++++++++++++++++++++++- extern/zstd | 1 + sources/Makefile.am | 27 ++++++++++++++++++++------ 4 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 .gitmodules create mode 160000 extern/zstd diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..9a2894c81 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "extern/zstd"] + path = extern/zstd + url = https://github.com/facebook/zstd diff --git a/configure.ac b/configure.ac index a42e22d9e..8b08d024d 100644 --- a/configure.ac +++ b/configure.ac @@ -66,6 +66,12 @@ m4_define([serial_tests], [m4_esyscmd_s([ ${AUTOMAKE:-automake} --version | head -1 | awk '{split ($NF,a,"."); if (a[1] >= 2 || (a[1] == 1 && a[2] >= 13)) { print "serial-tests" }}' ])]) +# If automake >= 1.14, use the subdir-objects option of AM_INIT_AUTOMAKE (available in automake >= 1.13) +# to suppress the "possible forward-incompatibility" warning. +m4_define([subdir_objects], [m4_esyscmd_s([ + ${AUTOMAKE:-automake} --version | head -1 | + awk '{split ($NF,a,"."); if (a[1] >= 2 || (a[1] == 1 && a[2] >= 14)) { print "subdir-objects" }}' +])]) AC_PREREQ([2.59]) AC_INIT([FORM], [FORM_VERSION], [https://github.com/vermaseren/form/issues]) @@ -73,7 +79,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([sources/form3.h]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([build-aux]) -AM_INIT_AUTOMAKE([1.7 foreign -Wall dist-bzip2] serial_tests) +AM_INIT_AUTOMAKE([1.7 foreign -Wall dist-bzip2] serial_tests subdir_objects) # Check for .version file AM_CONDITIONAL([FIXED_VERSION], [test -f $srcdir/.version]) @@ -350,6 +356,40 @@ AS_IF([test "x$with_zlib" != xno], AC_MSG_NOTICE([zlib is not available]) with_zlib=no])]) +# Check for zstd +AC_ARG_WITH([zstd], + [AS_HELP_STRING([--with-zstd@<:@=DIR@:>@], + [use zstd for compression (installed in prefix DIR) @<:@default=check@:>@])], + [AS_IF([test "x$withval" != xyes && test "x$withval" != xno && test "x$withval" != xcheck], + [with_zstd=yes + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib"])], + [with_zstd=check]) +AS_IF([test "x$with_zstd" != xno], + [flag=: + AS_IF([$flag], [AS_IF([test "x$with_zlib" = xno], + [AC_MSG_NOTICE([using zstd requires zlib]) + flag=false])]) + AS_IF([$flag], [AC_CHECK_HEADER([zstd.h], [], [flag=false])]) + AS_IF([$flag], [AC_CHECK_LIB([zstd], [ZSTD_versionNumber], [LIBS="-lzstd $LIBS"], [flag=false])]) + AS_IF([$flag], + [AC_DEFINE(WITHZSTD, [], [Define to use zstd for compression.]) + with_zstd=yes], + [AS_IF([test "x$with_zstd" = xyes], + [AC_MSG_FAILURE([test for zstd failed. Give --without-zstd if you want to compile without zstd])]) + AC_MSG_NOTICE([zstd is not available]) + with_zstd=no])]) +AM_CONDITIONAL([WITHZSTD], [test "x$with_zstd" = xyes]) + +# Ensure zstd/zlibWrapper +AS_IF([test -f "$srcdir/extern/zstd/zlibWrapper/zstd_zlibwrapper.h"], [], + [AC_PATH_PROG([GIT], [git]) + AS_IF([test -n "$GIT"], [(cd "$srcdir" && "$GIT" submodule update --init)])]) +AS_IF([test -f "$srcdir/extern/zstd/zlibWrapper/zstd_zlibwrapper.h"], [], + [AS_IF([test -d "$srcdir/.git"], + [AC_MSG_FAILURE([$srcdir/extern/zstd/zlibWrapper does not exist. Run git submodule update --init in the repository directory])], + [AC_MSG_FAILURE([$srcdir/extern/zstd/zlibWrapper does not exist])])]) + # enable-scalar/threaded/parform/debug/float AC_ARG_ENABLE([scalar], [AS_HELP_STRING([--enable-scalar], @@ -1063,6 +1103,10 @@ if test "x$with_zlib" = xyes; then echo " zlib" atleastone=yes fi +if test "x$with_zstd" = xyes; then + echo " zstd" + atleastone=yes +fi if test $atleastone = no; then echo " " fi diff --git a/extern/zstd b/extern/zstd new file mode 160000 index 000000000..794ea1b0a --- /dev/null +++ b/extern/zstd @@ -0,0 +1 @@ +Subproject commit 794ea1b0afca0f020f4e57b6732332231fb23c70 diff --git a/sources/Makefile.am b/sources/Makefile.am index 7e420cef8..ad835dad5 100644 --- a/sources/Makefile.am +++ b/sources/Makefile.am @@ -71,6 +71,8 @@ SRCBASE = \ vector.h \ wildcard.c +INCBASE = + if ONUNIX SRCBASE += \ unixfile.c \ @@ -88,6 +90,19 @@ SRCBASE += \ float.c endif +if WITHZSTD +SRCBASE += \ + $(top_srcdir)/extern/zstd/zlibWrapper/gzclose.c \ + $(top_srcdir)/extern/zstd/zlibWrapper/gzcompatibility.h \ + $(top_srcdir)/extern/zstd/zlibWrapper/gzguts.h \ + $(top_srcdir)/extern/zstd/zlibWrapper/gzlib.c \ + $(top_srcdir)/extern/zstd/zlibWrapper/gzread.c \ + $(top_srcdir)/extern/zstd/zlibWrapper/gzwrite.c \ + $(top_srcdir)/extern/zstd/zlibWrapper/zstd_zlibwrapper.c \ + $(top_srcdir)/extern/zstd/zlibWrapper/zstd_zlibwrapper.h +INCBASE += -I$(top_srcdir)/extern/zstd/zlibWrapper +endif + SRCPTHREAD = \ threads.c @@ -143,7 +158,7 @@ bin_PROGRAMS = if BUILD_FORM bin_PROGRAMS += form form_SOURCES = $(SRCBASE) -form_CPPFLAGS = +form_CPPFLAGS = $(INCBASE) form_CFLAGS = $(COMPILEFLAGS) form_CXXFLAGS = $(COMPILEFLAGS) form_LDFLAGS = $(LINKFLAGS) $(STATIC_LDFLAGS) @@ -158,7 +173,7 @@ endif if BUILD_VORM bin_PROGRAMS += vorm vorm_SOURCES = $(SRCBASE) -vorm_CPPFLAGS = -DDEBUGGING +vorm_CPPFLAGS = -DDEBUGGING $(INCBASE) vorm_CFLAGS = $(DEBUGCOMPILEFLAGS) vorm_CXXFLAGS = $(DEBUGCOMPILEFLAGS) vorm_LDFLAGS = $(DEBUGLINKFLAGS) @@ -173,7 +188,7 @@ endif if BUILD_TFORM bin_PROGRAMS += tform tform_SOURCES = $(SRCBASE) $(SRCPTHREAD) -tform_CPPFLAGS = -DWITHPTHREADS $(PTHREAD_CPPFLAGS) +tform_CPPFLAGS = -DWITHPTHREADS $(PTHREAD_CPPFLAGS) $(INCBASE) tform_CFLAGS = $(COMPILEFLAGS) $(PTHREAD_CFLAGS) tform_CXXFLAGS = $(COMPILEFLAGS) $(PTHREAD_CFLAGS) tform_LDFLAGS = $(LINKFLAGS) $(STATIC_LDFLAGS) @@ -188,7 +203,7 @@ endif if BUILD_TVORM bin_PROGRAMS += tvorm tvorm_SOURCES = $(SRCBASE) $(SRCPTHREAD) -tvorm_CPPFLAGS = -DWITHPTHREADS -DDEBUGGING $(PTHREAD_CPPFLAGS) +tvorm_CPPFLAGS = -DWITHPTHREADS -DDEBUGGING $(PTHREAD_CPPFLAGS) $(INCBASE) tvorm_CFLAGS = $(DEBUGCOMPILEFLAGS) $(PTHREAD_CFLAGS) tvorm_CXXFLAGS = $(DEBUGCOMPILEFLAGS) $(PTHREAD_CFLAGS) tvorm_LDFLAGS = $(DEBUGLINKFLAGS) @@ -203,7 +218,7 @@ endif if BUILD_PARFORM bin_PROGRAMS += parform parform_SOURCES = $(SRCBASE) $(SRCPARALLEL) -parform_CPPFLAGS = -DWITHMPI -DPF_WITHGETENV -DPF_WITHLOG $(MPI_CPPFLAGS) +parform_CPPFLAGS = -DWITHMPI -DPF_WITHGETENV -DPF_WITHLOG $(MPI_CPPFLAGS) $(INCBASE) parform_CFLAGS = $(COMPILEFLAGS) $(MPI_CFLAGS) parform_CXXFLAGS = $(COMPILEFLAGS) $(MPI_CXXFLAGS) parform_LDFLAGS = $(LINKFLAGS) $(MPI_STATIC_LDFLAGS) @@ -218,7 +233,7 @@ endif if BUILD_PARVORM bin_PROGRAMS += parvorm parvorm_SOURCES = $(SRCBASE) $(SRCPARALLEL) -parvorm_CPPFLAGS = -DWITHMPI -DPF_WITHGETENV -DPF_WITHLOG -DDEBUGGING $(MPI_CPPFLAGS) +parvorm_CPPFLAGS = -DWITHMPI -DPF_WITHGETENV -DPF_WITHLOG -DDEBUGGING $(MPI_CPPFLAGS) $(INCBASE) parvorm_CFLAGS = $(DEBUGCOMPILEFLAGS) $(MPI_CFLAGS) parvorm_CXXFLAGS = $(DEBUGCOMPILEFLAGS) $(MPI_CXXFLAGS) parvorm_LDFLAGS = $(DEBUGLINKFLAGS) From 44f50744ed5dfbb4dbd20a6b2cdd97c2fa03c150 Mon Sep 17 00:00:00 2001 From: Josh Davies Date: Tue, 18 Jun 2024 11:24:03 +0100 Subject: [PATCH 2/5] Add zstd to "On compress". Fix indentation. The default is to use zstd, if FORM is compiled with the wrapper. Specifying "On compress,gzip;" will still use zlib, via the zstd wrapper. --- sources/compcomm.c | 59 ++++++++++++++++++++++++++++------------------ sources/form3.h | 4 ++++ sources/startup.c | 4 ++++ 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/sources/compcomm.c b/sources/compcomm.c index d76973add..5dd76b31c 100644 --- a/sources/compcomm.c +++ b/sources/compcomm.c @@ -675,34 +675,47 @@ int CoOn(UBYTE *s) *s = c; while ( *s == ' ' || *s == ',' || *s == '\t' ) s++; if ( *s ) { - t = s; - while ( FG.cTable[*s] <= 1 ) s++; - c = *s; *s = 0; - if ( StrICmp(t,(UBYTE *)"gzip") == 0 ) {} - else { - MesPrint("&Unrecognized option in ON compress statement: %s",t); - return(-1); - } - *s = c; - while ( *s == ' ' || *s == ',' || *s == '\t' ) s++; + t = s; + while ( FG.cTable[*s] <= 1 ) s++; + c = *s; *s = 0; + if ( StrICmp(t,(UBYTE *)"gzip") == 0 ) { #ifndef WITHZLIB - Warning("gzip compression not supported on this platform"); + Warning("gzip compression not supported on this platform"); #endif - if ( FG.cTable[*s] == 1 ) { - AR.gzipCompress = *s++ - '0'; +#ifdef WITHZSTD + /* If gzip is specified, turn off zstd compression. zlib still goes via the wrapper. */ + ZWRAP_useZSTDcompression(0); +#endif + } + else if ( StrICmp(t,(UBYTE *)"zstd") == 0 ) { +#ifdef WITHZSTD + ZWRAP_useZSTDcompression(1); +#else + Warning("zstd compression not supported on this platform"); +#endif + } + else { + MesPrint("&Unrecognized option in ON compress statement: %s",t); + return(-1); + } + /* Whether we are using zlib or zstd, accept and use a compression level. */ + *s = c; while ( *s == ' ' || *s == ',' || *s == '\t' ) s++; - if ( *s ) { - MesPrint("&Unrecognized option in ON compress gzip statement: %s",t); + if ( FG.cTable[*s] == 1 ) { + AR.gzipCompress = *s++ - '0'; + while ( *s == ' ' || *s == ',' || *s == '\t' ) s++; + if ( *s ) { + MesPrint("&Unrecognized option in ON compress gzip/zstd statement: %s",t); + return(-1); + } + } + else if ( *s == 0 ) { + AR.gzipCompress = GZIPDEFAULT; + } + else { + MesPrint("&Unrecognized option in ON compress gzip/zstd statement: %s, single digit expected",t); return(-1); } - } - else if ( *s == 0 ) { - AR.gzipCompress = GZIPDEFAULT; - } - else { - MesPrint("&Unrecognized option in ON compress gzip statement: %s, single digit expected",t); - return(-1); - } } } else if ( StrICont(t,(UBYTE *)"checkpoint") == 0 ) { diff --git a/sources/form3.h b/sources/form3.h index 1f3f39262..85ffa8884 100644 --- a/sources/form3.h +++ b/sources/form3.h @@ -459,8 +459,12 @@ template struct calc { #include "unix.h" #endif #ifdef WITHZLIB +#ifdef WITHZSTD +#include +#else #include #endif +#endif #ifdef WITHPTHREADS #include #endif diff --git a/sources/startup.c b/sources/startup.c index 58e6ade46..27dcef4c1 100644 --- a/sources/startup.c +++ b/sources/startup.c @@ -1394,6 +1394,10 @@ WORD IniVars(VOID) AR.gzipCompress = GZIPDEFAULT; AR.FoStage4[0].ziobuffer = 0; AR.FoStage4[1].ziobuffer = 0; +#ifdef WITHZSTD + /* Zstd compression is on by default, if we have compiled with it */ + ZWRAP_useZSTDcompression(1); +#endif #endif AR.BracketOn = 0; AC.bracketindexflag = 0; From 8888c433af5a73d8dfdce838d6ac43a295371d3d Mon Sep 17 00:00:00 2001 From: Takahiro Ueda Date: Wed, 19 Jun 2024 12:23:18 +0900 Subject: [PATCH 3/5] ci: build with zstd Also fix "dubious ownership" in containers for Git operations. --- .github/workflows/deploy.yml | 15 ++++++++------ .github/workflows/test.yml | 39 +++++++++++++++--------------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e0c8b1a89..a29bf9303 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -75,7 +75,7 @@ jobs: if: runner.os == 'Linux' uses: awalsh128/cache-apt-pkgs-action@v1 with: - packages: libmpfr-dev + packages: libmpfr-dev libzstd-dev version: 1.0 - name: Install dependencies (Windows) @@ -103,7 +103,7 @@ jobs: - name: Configure run: | - opts='--disable-dependency-tracking --disable-scalar --disable-threaded --disable-native --enable-static-link --with-gmp --with-zlib' + opts='--disable-dependency-tracking --disable-scalar --disable-threaded --disable-native --enable-static-link --with-gmp --with-zlib --with-zstd' case ${{ matrix.bin }} in form) opts="$opts --enable-scalar";; tform) opts="$opts --enable-threaded";; @@ -113,19 +113,22 @@ jobs: # -l:libgmp.a to make partial static links possible. # As a workaround, we make a library directory with libgmp.a # but without libgmp.dylib so that the linker has to link libgmp.a. + # The same for other libraries. # Note that the Homebrew installation path for Apple Silicon (arm64) # differs from the one on macOS Intel (x86-64). - mkdir static-lib if [ "$RUNNER_OS" == "macOS" ]; then + mkdir static-lib if [ "$RUNNER_ARCH" == "ARM64" ]; then ln -s /opt/homebrew/opt/gmp/lib/libgmp.a static-lib/libgmp.a ln -s /opt/homebrew/opt/mpfr/lib/libmpfr.a static-lib/libmpfr.a - # The GMP and MPFR include directories, not located in the usual places, + ln -s /opt/homebrew/opt/zstd/lib/libzstd.a static-lib/libzstd.a + # Include directories, not located in the usual places, # must be explicitly appended to the include paths. - export CPATH="/opt/homebrew/opt/gmp/include:/opt/homebrew/opt/mpfr/include:${CPATH:-}" + export CPATH="/opt/homebrew/opt/gmp/include:/opt/homebrew/opt/mpfr/include:/opt/homebrew/opt/zstd/include:${CPATH:-}" else ln -s /usr/local/opt/gmp/lib/libgmp.a static-lib/libgmp.a ln -s /usr/local/opt/mpfr/lib/libmpfr.a static-lib/libmpfr.a + ln -s /usr/local/opt/zstd/lib/libzstd.a static-lib/libzstd.a fi export LIBRARY_PATH="$(pwd)/static-lib:${LIBRARY_PATH:-}" opts="$opts --disable-static-link" @@ -141,7 +144,7 @@ jobs: run: | if [ "$RUNNER_OS" == "macOS" ]; then if [ "$RUNNER_ARCH" == "ARM64" ]; then - export CPATH="/opt/homebrew/opt/gmp/include:/opt/homebrew/opt/mpfr/include:${CPATH:-}" + export CPATH="/opt/homebrew/opt/gmp/include:/opt/homebrew/opt/mpfr/include:/opt/homebrew/opt/zstd/include:${CPATH:-}" fi export LIBRARY_PATH="$(pwd)/static-lib:${LIBRARY_PATH:-}" fi diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dce6465ee..4a1fd9c56 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,10 +31,10 @@ jobs: with: fetch-depth: 0 # ensures a reachable tag - - name: Install MPFR + - name: Install dependencies uses: awalsh128/cache-apt-pkgs-action@v1 with: - packages: libmpfr-dev + packages: libmpfr-dev libzstd-dev version: 1.0 - name: Install MPI if necessary @@ -54,7 +54,7 @@ jobs: case ${{ matrix.bin }} in vorm|tvorm|parvorm) opts="$opts --enable-debug";; esac - opts="$opts --with-gmp --with-zlib" + opts="$opts --with-gmp --with-zlib --with-zstd" autoreconf -i ./configure $opts @@ -138,16 +138,10 @@ jobs: with: fetch-depth: 0 # ensures a reachable tag - - name: Install Valgrind - uses: awalsh128/cache-apt-pkgs-action@v1 - with: - packages: valgrind - version: 1.0 - - - name: Install MPFR + - name: Install dependencies uses: awalsh128/cache-apt-pkgs-action@v1 with: - packages: libmpfr-dev + packages: libmpfr-dev libzstd-dev valgrind version: 1.0 - name: Install MPI if necessary @@ -167,7 +161,7 @@ jobs: case ${{ matrix.bin }} in vorm|tvorm|parvorm) opts="$opts --enable-debug";; esac - opts="$opts --with-gmp --with-zlib" + opts="$opts --with-gmp --with-zlib --with-zstd" autoreconf -i ./configure $opts @@ -196,16 +190,10 @@ jobs: with: fetch-depth: 0 # ensures a reachable tag - - name: Install LCOV - uses: awalsh128/cache-apt-pkgs-action@v1 - with: - packages: lcov - version: 1.0 - - - name: Install MPFR + - name: Install dependencies uses: awalsh128/cache-apt-pkgs-action@v1 with: - packages: libmpfr-dev + packages: lcov libmpfr-dev libzstd-dev version: 1.0 - name: Install MPI if necessary @@ -222,7 +210,7 @@ jobs: tvorm) opts="$opts --disable-scalar --enable-threaded --disable-parform";; parvorm) opts="$opts --disable-scalar --disable-threaded --enable-parform";; esac - opts="$opts --enable-debug --enable-coverage --with-gmp --with-zlib" + opts="$opts --enable-debug --enable-coverage --with-gmp --with-zlib --with-zstd" autoreconf -i ./configure $opts @@ -275,7 +263,12 @@ jobs: - name: Install dependencies run: | apt-get update - apt-get -y install automake build-essential git libgmp-dev libmpfr-dev ruby zlib1g-dev + apt-get -y install automake build-essential git libgmp-dev libmpfr-dev libzstd-dev ruby zlib1g-dev + + # Fix dubious ownership for Git operations. + # See https://github.com/actions/runner/issues/2033#issuecomment-1204205989 + - name: Set ownership + run: chown -R $(id -u):$(id -g) $PWD - name: Configure run: | @@ -284,7 +277,7 @@ jobs: form) opts="$opts --enable-scalar --disable-threaded --disable-parform";; tform) opts="$opts --disable-scalar --enable-threaded --disable-parform";; esac - opts="$opts --disable-debug --with-gmp --with-zlib" + opts="$opts --disable-debug --with-gmp --with-zlib --with-zstd" autoreconf -i ./configure $opts From ef74609f40d5a9794926a449283871db35798d6b Mon Sep 17 00:00:00 2001 From: Josh Davies Date: Fri, 7 Mar 2025 13:55:22 +0000 Subject: [PATCH 4/5] fix: Force zlib when writing compressed tablebase entries Maintain portability of tablebase files between FORM binaries compiled with and without zstd support. --- sources/minos.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sources/minos.c b/sources/minos.c index 536d45a41..ebadb9aa6 100644 --- a/sources/minos.c +++ b/sources/minos.c @@ -1231,12 +1231,21 @@ int WriteObject(DBASE *d,MLONG tablenumber,char *arguments,char *rhs,MLONG numbe else buffer = 0; if ( buffer ) { ssize = size; +#ifdef WITHZSTD + // Force the use of zlib for compressed Tablebase entries, so that tablebases created + // with zstd-supported FORM builds can be used by zstd-unsupported FORM builds. + const int old_isUsingZSTDcompression = ZWRAP_isUsingZSTDcompression(); + ZWRAP_useZSTDcompression(0); +#endif if ( ( error = compress((Bytef *)buffer,&newsize,(Bytef *)rhs,ssize) ) != Z_OK ) { MesPrint("Error = %d\n",error); MesPrint("Due to error no compress used for element %s in file %s\n",arguments,d->name); M_free(buffer,"tb,WriteObject"); buffer = 0; } +#ifdef WITHZSTD + ZWRAP_useZSTDcompression(old_isUsingZSTDcompression); +#endif } if ( buffer ) { rhs = buffer; From 39b43b7e8315c30a2e0cdfd865dac24b40b1ec65 Mon Sep 17 00:00:00 2001 From: Josh Davies Date: Fri, 23 May 2025 21:18:08 +0100 Subject: [PATCH 5/5] doc: add On compress,zstd; description to the manual --- doc/manual/statements.tex | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/doc/manual/statements.tex b/doc/manual/statements.tex index 38a25bd74..92b260958 100644 --- a/doc/manual/statements.tex +++ b/doc/manual/statements.tex @@ -3903,14 +3903,28 @@ \section{on} \rightvitem{13cm}{Turns compression mode on. This compression is a relatively simple compression that hardly costs extra computer time but saves roughly a factor two in disk storage. The old statement was `compress -on' but this should be avoided in the future. This setting is the default.} +on' but this should be avoided in the future. This setting is the default if +\FORM\ has not been compiled with gzip or zstd support.} \leftvitem{3.5cm}{compress,gzip\index{gzip}} -\rightvitem{13cm}{This option should be followed by a comma or a space and +\rightvitem{13cm}{This setting is the default, if \FORM\ has been compiled +with gzip support but not with zstd support. +This option may be followed by a comma or a space and a single digit. It activates the gzip compression for the sort file. This compression can make the intermediate sort file considerably shorter at the -cost of some CPU time. This option can be used when disk space is at a -premium. The digit indicates the compression level. Zero means no +cost of some CPU time. +The digit indicates the compression level. Zero means no +compression and 9 is the highest level. The default level is 6. Above that +the compression becomes very slow and doesn't gain very much extra.} + +\leftvitem{3.5cm}{compress,zstd\index{zstd}} +\rightvitem{13cm}{This setting is the default, if \FORM\ has been compiled with +zstd support. +This option may be followed by a comma or a space and +a single digit. It activates the zstd compression for the sort file. This +compression performs better than gzip, both in terms of compression/ +decompression rates and compression ratio. +The digit indicates the compression level. Zero means no compression and 9 is the highest level. The default level is 6. Above that the compression becomes very slow and doesn't gain very much extra.}