From 65ab6c267e74eb715f383763d8b9898c780ed5ab Mon Sep 17 00:00:00 2001 From: ManuelBlanc Date: Sat, 23 Mar 2024 08:44:52 -0400 Subject: [PATCH 001/405] Use vswhere to find MSBuild; add VS2022 support See: https://github.com/microsoft/vswhere/wiki/Find-MSBuild --- build/VS_scripts/build.generic.cmd | 34 ++++++++++++------------------ 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/build/VS_scripts/build.generic.cmd b/build/VS_scripts/build.generic.cmd index b24e6ed4b..d9a8b1602 100644 --- a/build/VS_scripts/build.generic.cmd +++ b/build/VS_scripts/build.generic.cmd @@ -2,7 +2,7 @@ IF "%1%" == "" GOTO display_help -SETLOCAL +SETLOCAL ENABLEDELAYEDEXPANSION SET msbuild_version=%1 @@ -29,29 +29,23 @@ EXIT /B 1 :build SET msbuild="%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" -SET msbuild_vs2017community="%programfiles(x86)%\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" -SET msbuild_vs2017professional="%programfiles(x86)%\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" -SET msbuild_vs2017enterprise="%programfiles(x86)%\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe" IF %msbuild_version% == VS2013 SET msbuild="%programfiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe" IF %msbuild_version% == VS2015 SET msbuild="%programfiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe" -IF %msbuild_version% == VS2017Community SET msbuild=%msbuild_vs2017community% -IF %msbuild_version% == VS2017Professional SET msbuild=%msbuild_vs2017professional% -IF %msbuild_version% == VS2017Enterprise SET msbuild=%msbuild_vs2017enterprise% -IF %msbuild_version% == VS2017 ( - IF EXIST %msbuild_vs2017community% SET msbuild=%msbuild_vs2017community% - IF EXIST %msbuild_vs2017professional% SET msbuild=%msbuild_vs2017professional% - IF EXIST %msbuild_vs2017enterprise% SET msbuild=%msbuild_vs2017enterprise% -) +IF %msbuild_version% == VS2017 SET vswhere_version=[15,16) +IF %msbuild_version% == VS2017Community SET vswhere_version=[15,16) & SET vswhere_products=Community +IF %msbuild_version% == VS2017Enterprise SET vswhere_version=[15,16) & SET vswhere_products=Enterprise +IF %msbuild_version% == VS2017Professional SET vswhere_version=[15,16) & SET vswhere_products=Professional +IF %msbuild_version% == VS2019 SET vswhere_version=[16,17) +IF %msbuild_version% == VS2022 SET vswhere_version=[17,18) +REM Add the next Visual Studio version here. -:: VS2019 -SET msbuild_vs2019community="%programfiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" -SET msbuild_vs2019professional="%programfiles(x86)%\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" -SET msbuild_vs2019enterprise="%programfiles(x86)%\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe" -IF %msbuild_version% == VS2019 ( - IF EXIST %msbuild_vs2019community% SET msbuild=%msbuild_vs2019community% - IF EXIST %msbuild_vs2019professional% SET msbuild=%msbuild_vs2019professional% - IF EXIST %msbuild_vs2019enterprise% SET msbuild=%msbuild_vs2019enterprise% +IF NOT DEFINED vswhere_version GOTO skip_vswhere +IF NOT DEFINED vswhere_products SET vswhere_products=* +SET vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +FOR /F "USEBACKQ TOKENS=*" %%F IN (`%vswhere% -utf8 -property installationPath -products !vswhere_products! -version !vswhere_version!`) DO ( + SET msbuild="%%F\MSBuild\Current\Bin\MSBuild.exe" ) +:skip_vswhere SET project="%~p0\..\VS2010\zstd.sln" From 9c442d6fc28e55e5379598d18082f8a31dd4931b Mon Sep 17 00:00:00 2001 From: ManuelBlanc Date: Sat, 23 Mar 2024 18:34:07 -0400 Subject: [PATCH 002/405] Improve MSBuild search; add latest option --- build/VS_scripts/build.generic.cmd | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/build/VS_scripts/build.generic.cmd b/build/VS_scripts/build.generic.cmd index d9a8b1602..6597d79ca 100644 --- a/build/VS_scripts/build.generic.cmd +++ b/build/VS_scripts/build.generic.cmd @@ -19,7 +19,7 @@ GOTO build :display_help echo Syntax: build.generic.cmd msbuild_version msbuild_platform msbuild_configuration msbuild_toolset -echo msbuild_version: VS installed version (VS2012, VS2013, VS2015, VS2017, VS2019, ...) +echo msbuild_version: VS installed version (latest, VS2012, VS2013, VS2015, VS2017, VS2019, ...) echo msbuild_platform: Platform (x64 or Win32) echo msbuild_configuration: VS configuration (Release or Debug) echo msbuild_toolset: Platform Toolset (v100, v110, v120, v140, v141, v142, ...) @@ -31,19 +31,19 @@ EXIT /B 1 SET msbuild="%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" IF %msbuild_version% == VS2013 SET msbuild="%programfiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe" IF %msbuild_version% == VS2015 SET msbuild="%programfiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe" -IF %msbuild_version% == VS2017 SET vswhere_version=[15,16) -IF %msbuild_version% == VS2017Community SET vswhere_version=[15,16) & SET vswhere_products=Community -IF %msbuild_version% == VS2017Enterprise SET vswhere_version=[15,16) & SET vswhere_products=Enterprise -IF %msbuild_version% == VS2017Professional SET vswhere_version=[15,16) & SET vswhere_products=Professional -IF %msbuild_version% == VS2019 SET vswhere_version=[16,17) -IF %msbuild_version% == VS2022 SET vswhere_version=[17,18) -REM Add the next Visual Studio version here. +IF %msbuild_version% == VS2017 SET vswhere_params=-version [15,16) -products * +IF %msbuild_version% == VS2017Community SET vswhere_params=-version [15,16) -products Community +IF %msbuild_version% == VS2017Enterprise SET vswhere_params=-version [15,16) -products Enterprise +IF %msbuild_version% == VS2017Professional SET vswhere_params=-version [15,16) -products Professional +IF %msbuild_version% == VS2019 SET vswhere_params=-version [16,17) -products * +IF %msbuild_version% == VS2022 SET vswhere_params=-version [17,18) -products * +REM Add the next Visual Studio version here. +IF %msbuild_version% == latest SET vswhere_params=-latest -products * -IF NOT DEFINED vswhere_version GOTO skip_vswhere -IF NOT DEFINED vswhere_products SET vswhere_products=* +IF NOT DEFINED vswhere_params GOTO skip_vswhere SET vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -FOR /F "USEBACKQ TOKENS=*" %%F IN (`%vswhere% -utf8 -property installationPath -products !vswhere_products! -version !vswhere_version!`) DO ( - SET msbuild="%%F\MSBuild\Current\Bin\MSBuild.exe" +FOR /F "USEBACKQ TOKENS=*" %%F IN (`%vswhere% !vswhere_params! -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe`) DO ( + SET msbuild="%%F" ) :skip_vswhere From 101e601c793e9d4dbdffaf05331774bca2aa12be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 05:31:42 +0000 Subject: [PATCH 003/405] Bump github/codeql-action from 3.24.7 to 3.24.9 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.7 to 3.24.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/3ab4101902695724f9365a384f86c1074d94e18c...1b1aada464948af03b950897e5eb522f92603cc2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index a5d5f02a3..e91461280 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3ab4101902695724f9365a384f86c1074d94e18c # tag=v3.24.7 + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # tag=v3.24.9 with: sarif_file: results.sarif From 81a5e5d4384342c0312198f4db35b8cdabc30d96 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 26 Mar 2024 10:01:19 -0700 Subject: [PATCH 004/405] [fuzz] Turn off -Werror by default This was causing OSS-Fuzz errors, due to compiler differences. * Fix the issue * Also turn off -Werror so we don't fail fuzzer builds for warnings * Turn on -Werror in our CI --- Makefile | 4 ++-- tests/fuzz/fuzz.py | 1 - tests/fuzz/sequence_compression_api.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 11eca19ce..b2d985feb 100644 --- a/Makefile +++ b/Makefile @@ -293,10 +293,10 @@ regressiontest: $(MAKE) -C $(FUZZDIR) regressiontest uasanregressiontest: - $(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS="-O3 -fsanitize=address,undefined" CXXFLAGS="-O3 -fsanitize=address,undefined" + $(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS="-O3 -fsanitize=address,undefined -Werror" CXXFLAGS="-O3 -fsanitize=address,undefined -Werror" msanregressiontest: - $(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS="-O3 -fsanitize=memory" CXXFLAGS="-O3 -fsanitize=memory" + $(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS="-O3 -fsanitize=memory -Werror" CXXFLAGS="-O3 -fsanitize=memory -Werror" update_regressionResults : REGRESS_RESULTS_DIR := /tmp/regress_results_dir/ update_regressionResults: diff --git a/tests/fuzz/fuzz.py b/tests/fuzz/fuzz.py index d59df9261..492be3486 100755 --- a/tests/fuzz/fuzz.py +++ b/tests/fuzz/fuzz.py @@ -408,7 +408,6 @@ def build(args): mflags = shlex.split(args.mflags) # Flags to be added to both cflags and cxxflags common_flags = [ - '-Werror', '-Wno-error=declaration-after-statement', '-Wno-error=c++-compat', '-Wno-error=deprecated' # C files are sometimes compiled with CXX diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index ec0106c18..3c60f42c6 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -127,7 +127,7 @@ static size_t decodeSequences(void* dst, size_t nbSequences, FUZZ_ASSERT(litPtr <= litEnd); if (mode == ZSTD_sf_noBlockDelimiters) { const uint32_t lastLLSize = (uint32_t)(litEnd - litPtr); - if (lastLLSize <= oend - op) { + if (lastLLSize <= (uint32_t)(oend - op)) { memcpy(op, litPtr, lastLLSize); generatedSrcBufferSize += lastLLSize; } } From 103a85e6f64f305684db354a0eb9a10d5c586d5c Mon Sep 17 00:00:00 2001 From: Po-Chuan Hsieh Date: Wed, 27 Mar 2024 20:53:52 +0800 Subject: [PATCH 005/405] Use md5sum rather than gmd5sum for FreeBSD Reference: https://man.freebsd.org/cgi/man.cgi?query=md5sum --- lib/libzstd.mk | 2 -- tests/cli-tests/common/platform.sh | 1 - tests/playTests.sh | 1 - 3 files changed, 4 deletions(-) diff --git a/lib/libzstd.mk b/lib/libzstd.mk index a308a6ef6..14b3b11d6 100644 --- a/lib/libzstd.mk +++ b/lib/libzstd.mk @@ -213,8 +213,6 @@ ifeq ($(UNAME), Darwin) ifeq ($(shell md5 < /dev/null > /dev/null; echo $$?), 0) HASH ?= md5 endif -else ifeq ($(UNAME), FreeBSD) - HASH ?= gmd5sum else ifeq ($(UNAME), NetBSD) HASH ?= md5 -n else ifeq ($(UNAME), OpenBSD) diff --git a/tests/cli-tests/common/platform.sh b/tests/cli-tests/common/platform.sh index 6eb45eab9..a07f229dc 100644 --- a/tests/cli-tests/common/platform.sh +++ b/tests/cli-tests/common/platform.sh @@ -18,7 +18,6 @@ esac case "$UNAME" in Darwin) MD5SUM="md5 -r" ;; - FreeBSD) MD5SUM="gmd5sum" ;; NetBSD) MD5SUM="md5 -n" ;; OpenBSD) MD5SUM="md5" ;; *) MD5SUM="md5sum" ;; diff --git a/tests/playTests.sh b/tests/playTests.sh index e2a0694f5..026490051 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -123,7 +123,6 @@ esac case "$UNAME" in Darwin) MD5SUM="md5 -r" ;; - FreeBSD) MD5SUM="gmd5sum" ;; NetBSD) MD5SUM="md5 -n" ;; OpenBSD) MD5SUM="md5" ;; *) MD5SUM="md5sum" ;; From ebf24b7b77ed3b4430e7dd3ef45104d05d3585a6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 27 Mar 2024 16:10:15 -0700 Subject: [PATCH 006/405] fix nodejs deprecation warning by updating msys2 action --- .github/workflows/windows-artifacts.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-artifacts.yml b/.github/workflows/windows-artifacts.yml index 52bc90a49..60c163123 100644 --- a/.github/workflows/windows-artifacts.yml +++ b/.github/workflows/windows-artifacts.yml @@ -24,7 +24,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3 - - uses: msys2/setup-msys2@5beef6d11f48bba68b9eb503e3adc60b23c0cc36 # tag=v2 + - uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # tag=v2.22.0 with: msystem: ${{ matrix.msystem }} install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc From e0ee0fccf8c591465be4c3f4872ef550e7939f73 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 27 Mar 2024 18:19:31 -0700 Subject: [PATCH 007/405] updated benchmarks for v1.5.6 --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0f7478e10..54dfd4065 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,10 @@ a list of known ports and bindings is provided on [Zstandard homepage](https://f ## Benchmarks For reference, several fast compression algorithms were tested and compared -on a desktop running Ubuntu 20.04 (`Linux 5.11.0-41-generic`), -with a Core i7-9700K CPU @ 4.9GHz, +on a desktop featuring a Core i7-9700K CPU @ 4.9GHz +and running Ubuntu 20.04 (`Linux ubu20 5.15.0-101-generic`), using [lzbench], an open-source in-memory benchmark by @inikep -compiled with [gcc] 9.3.0, +compiled with [gcc] 9.4.0, on the [Silesia compression corpus]. [lzbench]: https://github.com/inikep/lzbench @@ -41,24 +41,23 @@ on the [Silesia compression corpus]. | Compressor name | Ratio | Compression| Decompress.| | --------------- | ------| -----------| ---------- | -| **zstd 1.5.1 -1** | 2.887 | 530 MB/s | 1700 MB/s | +| **zstd 1.5.6 -1** | 2.887 | 510 MB/s | 1580 MB/s | | [zlib] 1.2.11 -1 | 2.743 | 95 MB/s | 400 MB/s | -| brotli 1.0.9 -0 | 2.702 | 395 MB/s | 450 MB/s | -| **zstd 1.5.1 --fast=1** | 2.437 | 600 MB/s | 2150 MB/s | -| **zstd 1.5.1 --fast=3** | 2.239 | 670 MB/s | 2250 MB/s | -| quicklz 1.5.0 -1 | 2.238 | 540 MB/s | 760 MB/s | -| **zstd 1.5.1 --fast=4** | 2.148 | 710 MB/s | 2300 MB/s | -| lzo1x 2.10 -1 | 2.106 | 660 MB/s | 845 MB/s | -| [lz4] 1.9.3 | 2.101 | 740 MB/s | 4500 MB/s | -| lzf 3.6 -1 | 2.077 | 410 MB/s | 830 MB/s | -| snappy 1.1.9 | 2.073 | 550 MB/s | 1750 MB/s | +| brotli 1.0.9 -0 | 2.702 | 395 MB/s | 430 MB/s | +| **zstd 1.5.6 --fast=1** | 2.437 | 545 MB/s | 1890 MB/s | +| **zstd 1.5.6 --fast=3** | 2.239 | 650 MB/s | 2000 MB/s | +| quicklz 1.5.0 -1 | 2.238 | 525 MB/s | 750 MB/s | +| lzo1x 2.10 -1 | 2.106 | 650 MB/s | 825 MB/s | +| [lz4] 1.9.4 | 2.101 | 700 MB/s | 4000 MB/s | +| lzf 3.6 -1 | 2.077 | 420 MB/s | 830 MB/s | +| snappy 1.1.9 | 2.073 | 530 MB/s | 1660 MB/s | [zlib]: https://www.zlib.net/ [lz4]: https://lz4.github.io/lz4/ The negative compression levels, specified with `--fast=#`, offer faster compression and decompression speed -at the cost of compression ratio (compared to level 1). +at the cost of compression ratio. Zstd can also offer stronger compression ratios at the cost of compression speed. Speed vs Compression trade-off is configurable by small increments. From 72c16b187d27016b7634f5c6b7290e7c66ba44b3 Mon Sep 17 00:00:00 2001 From: Yuriy Chernyshov Date: Thu, 28 Mar 2024 11:54:53 +0100 Subject: [PATCH 008/405] Fix building on windows-x86 if clang already includes [D101338](https://reviews.llvm.org/D101338) landed in 2021, so clang16 should have it --- lib/common/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/cpu.h b/lib/common/cpu.h index 0e684d9ad..d9cdf8feb 100644 --- a/lib/common/cpu.h +++ b/lib/common/cpu.h @@ -35,7 +35,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) { U32 f7b = 0; U32 f7c = 0; #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) -#if !defined(__clang__) +#if !defined(__clang__) || __clang_major__ >= 16 int reg[4]; __cpuid((int*)reg, 0); { From a2f145f059150744132639cf30a918ceadac9b77 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 1 Apr 2024 11:12:26 -0700 Subject: [PATCH 009/405] decompression errors always display the full origin filename instead of the truncated size-limited version. --- programs/fileio.c | 27 ++++++++++----------------- programs/fileio_asyncio.c | 2 +- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index e3012a716..c6af36fbd 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1494,7 +1494,7 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx, int compressionLevel, U64* readsize) { cRess_t const ress = *ressPtr; - IOJob_t *writeJob = AIO_WritePool_acquireJob(ressPtr->writeCtx); + IOJob_t* writeJob = AIO_WritePool_acquireJob(ressPtr->writeCtx); U64 compressedfilesize = 0; ZSTD_EndDirective directive = ZSTD_e_continue; @@ -1526,8 +1526,7 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx, CHECK( ZSTD_CCtx_setPledgedSrcSize(ress.cctx, prefs->streamSrcSize) ); } - { - int windowLog; + { int windowLog; UTIL_HumanReadableSize_t windowSize; CHECK(ZSTD_CCtx_getParameter(ress.cctx, ZSTD_c_windowLog, &windowLog)); if (windowLog == 0) { @@ -1542,7 +1541,6 @@ FIO_compressZstdFrame(FIO_ctx_t* const fCtx, windowSize = UTIL_makeHumanReadableSize(MAX(1ULL, MIN(1ULL << windowLog, pledgedSrcSize))); DISPLAYLEVEL(4, "Decompression will require %.*f%s of memory\n", windowSize.precision, windowSize.value, windowSize.suffix); } - (void)srcFileName; /* Main compression loop */ do { @@ -2439,12 +2437,14 @@ FIO_decompressZstdFrame(FIO_ctx_t* const fCtx, dRess_t* ress, U64 alreadyDecoded) /* for multi-frames streams */ { U64 frameSize = 0; - IOJob_t *writeJob = AIO_WritePool_acquireJob(ress->writeCtx); + const char* srcFName20 = srcFileName; + IOJob_t* writeJob = AIO_WritePool_acquireJob(ress->writeCtx); + assert(writeJob); /* display last 20 characters only when not --verbose */ { size_t const srcFileLength = strlen(srcFileName); if ((srcFileLength>20) && (g_display_prefs.displayLevel<3)) - srcFileName += srcFileLength-20; + srcFName20 += srcFileLength-20; } ZSTD_DCtx_reset(ress->dctx, ZSTD_reset_session_only); @@ -2471,19 +2471,12 @@ FIO_decompressZstdFrame(FIO_ctx_t* const fCtx, dRess_t* ress, AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob); frameSize += outBuff.pos; if (fCtx->nbFilesTotal > 1) { - size_t srcFileNameSize = strlen(srcFileName); - if (srcFileNameSize > 18) { - const char* truncatedSrcFileName = srcFileName + srcFileNameSize - 15; - DISPLAYUPDATE_PROGRESS( - "\rDecompress: %2u/%2u files. Current: ...%s : %.*f%s... ", - fCtx->currFileIdx+1, fCtx->nbFilesTotal, truncatedSrcFileName, hrs.precision, hrs.value, hrs.suffix); - } else { - DISPLAYUPDATE_PROGRESS("\rDecompress: %2u/%2u files. Current: %s : %.*f%s... ", - fCtx->currFileIdx+1, fCtx->nbFilesTotal, srcFileName, hrs.precision, hrs.value, hrs.suffix); - } + DISPLAYUPDATE_PROGRESS( + "\rDecompress: %2u/%2u files. Current: %s : %.*f%s... ", + fCtx->currFileIdx+1, fCtx->nbFilesTotal, srcFName20, hrs.precision, hrs.value, hrs.suffix); } else { DISPLAYUPDATE_PROGRESS("\r%-20.20s : %.*f%s... ", - srcFileName, hrs.precision, hrs.value, hrs.suffix); + srcFName20, hrs.precision, hrs.value, hrs.suffix); } AIO_ReadPool_consumeBytes(ress->readCtx, inBuff.pos); diff --git a/programs/fileio_asyncio.c b/programs/fileio_asyncio.c index ae6db69e0..42a472016 100644 --- a/programs/fileio_asyncio.c +++ b/programs/fileio_asyncio.c @@ -268,7 +268,7 @@ static void AIO_IOPool_destroy(IOPoolCtx_t* ctx) { /* AIO_IOPool_acquireJob: * Returns an available io job to be used for a future io. */ static IOJob_t* AIO_IOPool_acquireJob(IOPoolCtx_t* ctx) { - IOJob_t *job; + IOJob_t* job; assert(ctx->file != NULL || ctx->prefs->testMode); AIO_IOPool_lockJobsMutex(ctx); assert(ctx->availableJobsCount > 0); From 8cff66f2f53fa41b8f5be65996600d88fbbe1a98 Mon Sep 17 00:00:00 2001 From: elasota <1137273+elasota@users.noreply.github.com> Date: Mon, 1 Apr 2024 20:08:42 -0400 Subject: [PATCH 010/405] Remove text specifying probability overflow as invalid, the variable-size value encoding scheme makes this impossible. --- doc/zstd_compression_format.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index 7955dae4a..5cae85524 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -1125,8 +1125,6 @@ If it is a 3, another 2-bits repeat flag follows, and so on. When last symbol reaches cumulated total of `1 << Accuracy_Log`, decoding is complete. -If the last symbol makes cumulated total go above `1 << Accuracy_Log`, -distribution is considered corrupted. If this process results in a non-zero probability for a value outside of the valid range of values that the FSE table is defined for, even if that value is not used, then the data is considered corrupted. From c54f4783d0cd51d8aad1c0a4fd9fe564d461aae4 Mon Sep 17 00:00:00 2001 From: elasota <1137273+elasota@users.noreply.github.com> Date: Mon, 1 Apr 2024 20:13:18 -0400 Subject: [PATCH 011/405] Specify that decoders may reject non-zero probabilities for larger offset codes than supported by the implementation --- doc/zstd_compression_format.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index 7955dae4a..8a60e56df 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -1129,7 +1129,10 @@ If the last symbol makes cumulated total go above `1 << Accuracy_Log`, distribution is considered corrupted. If this process results in a non-zero probability for a value outside of the valid range of values that the FSE table is defined for, even if that value is -not used, then the data is considered corrupted. +not used, then the data is considered corrupted. In the case of offset codes, +a decoder implementation may reject a frame containing a non-zero probability +for an offset code larger than the largest offset code supported by the decoder +implementation. Then the decoder can tell how many bytes were used in this process, and how many symbols are present. From fd5f8106a58601a963ee816e6a57aa7c61fafc53 Mon Sep 17 00:00:00 2001 From: BadWolf Date: Sat, 6 Apr 2024 00:05:58 +0200 Subject: [PATCH 012/405] fix missing include folder for resource compiler --- build/cmake/lib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 5d514ccb2..43b14d175 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -118,7 +118,7 @@ endmacro () # Define directories containing the library's public headers set(PUBLIC_INCLUDE_DIRS ${LIBRARY_DIR}) - +set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} /I ${LIBRARY_DIR}") # Split project to static and shared libraries build set(library_targets) if (ZSTD_BUILD_SHARED) From 71def598906637866f1b165bc9113defdd36983c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Pawe=C5=82=20Stefaniak?= <3462925+pstef@users.noreply.github.com> Date: Sun, 7 Apr 2024 13:04:26 +0200 Subject: [PATCH 013/405] Fix zlibWrapper build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just after a clone I'm getting this: ~/zstd/zlibWrapper$ cc -c zstd_zlibwrapper.o gz*.c -lz -lzstd -DSTDC gzwrite.c: In function ‘gz_write’: gzwrite.c:226:43: error: ‘z_uInt’ undeclared (first use in this function); did you mean ‘uInt’? 226 | state.state->strm.avail_in = (z_uInt)n; | ^~~~~~ | uInt gzwrite.c:226:43: note: each undeclared identifier is reported only once for each function it appears in gzwrite.c:226:50: error: expected ‘;’ before ‘n’ 226 | state.state->strm.avail_in = (z_uInt)n; | ^ | ; z_uInt is never used directly, zconf.h redefines uInt to z_uInt under the condition that Z_PREFIX is set. All examples use uInt, and the type of avail_in is also uInt. In this commit I modify the cast to refer to the same type as the type of lvalue. Arguably, the real fix here is to handle possible overflows, but that's beyond the scope of this commit. --- zlibWrapper/gzwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zlibWrapper/gzwrite.c b/zlibWrapper/gzwrite.c index 81da15314..67f5eda6c 100644 --- a/zlibWrapper/gzwrite.c +++ b/zlibWrapper/gzwrite.c @@ -223,7 +223,7 @@ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { z_size_t n = (unsigned)-1; if (n > len) n = len; - state.state->strm.avail_in = (z_uInt)n; + state.state->strm.avail_in = (uInt)n; state.state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; From 7968c661af8ec976782ddcfde3ea609d9353a0cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 05:47:58 +0000 Subject: [PATCH 014/405] Bump github/codeql-action from 3.24.9 to 3.24.10 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.9 to 3.24.10. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/1b1aada464948af03b950897e5eb522f92603cc2...4355270be187e1b672a7a1c7c7bae5afdc1ab94a) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index e91461280..7a7750026 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # tag=v3.24.9 + uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # tag=v3.24.10 with: sarif_file: results.sarif From f1f1ae369a4cefd3474b3528e8d1847b18750605 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 6 Apr 2024 14:41:54 +0200 Subject: [PATCH 015/405] Provide variant pkg-config file for multi-threaded static lib Multi-threaded static library require -pthread to correctly link and works. The pkg-config we provide tho only works with dynamic multi-threaded library and won't provide the correct libs and cflags values if lib-mt is used. To handle this, introduce an env variable MT to permit advanced user to install and generate a correct pkg-config file for lib-mt or detect if lib-mt target is called. With MT env set on calling make install-pc, libzstd.pc.in is a pkg-config file for a multi-threaded static library. On calling make lib-mt, a libzstd.pc is generated for a multi-threaded static library as it's what asked by the user by forcing it. libzstd.pc is changed to PHONY to force regeneration of it on calling lib targets or install-pc to handle case where the same directory is used for mixed compilation. This was notice while migrating from meson to make build system where meson generates a correct .pc file while make doesn't. Signed-off-by: Christian Marangi --- lib/Makefile | 20 +++++++++++++++++++- lib/README.md | 4 ++++ lib/libzstd.pc.in | 4 ++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 8bfdade9f..57097ce3f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -63,6 +63,8 @@ CPPFLAGS_DYNLIB += -DZSTD_MULTITHREAD # dynamic library build defaults to multi LDFLAGS_DYNLIB += -pthread CPPFLAGS_STATICLIB += # static library build defaults to single-threaded +# pkg-config Libs.private points to LDFLAGS_DYNLIB +PCLIB := $(LDFLAGS_DYNLIB) ifeq ($(findstring GCC,$(CCVER)),GCC) decompress/zstd_decompress_block.o : CFLAGS+=-fno-tree-vectorize @@ -186,12 +188,15 @@ lib : libzstd.a libzstd %-mt : CPPFLAGS_DYNLIB := -DZSTD_MULTITHREAD %-mt : CPPFLAGS_STATICLIB := -DZSTD_MULTITHREAD %-mt : LDFLAGS_DYNLIB := -pthread +%-mt : PCLIB := +%-mt : PCMTLIB := $(LDFLAGS_DYNLIB) %-mt : % @echo multi-threaded build completed %-nomt : CPPFLAGS_DYNLIB := %-nomt : LDFLAGS_DYNLIB := %-nomt : CPPFLAGS_STATICLIB := +%-nomt : PCLIB := %-nomt : % @echo single-threaded build completed @@ -292,6 +297,14 @@ PCLIBPREFIX := $(if $(findstring $(LIBDIR),$(PCLIBDIR)),,$${exec_prefix}) # to PREFIX, rather than as a resolved value. PCEXEC_PREFIX := $(if $(HAS_EXPLICIT_EXEC_PREFIX),$(EXEC_PREFIX),$${prefix}) + +ifneq ($(MT),) + PCLIB := + PCMTLIB := $(LDFLAGS_DYNLIB) +else + PCLIB := $(LDFLAGS_DYNLIB) +endif + ifneq (,$(filter $(UNAME),FreeBSD NetBSD DragonFly)) PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig else @@ -308,6 +321,10 @@ INSTALL_PROGRAM ?= $(INSTALL) INSTALL_DATA ?= $(INSTALL) -m 644 +# pkg-config library define. +# For static single-threaded library declare -pthread in Libs.private +# For static multi-threaded library declare -pthread in Libs and Cflags +.PHONY: libzstd.pc libzstd.pc: libzstd.pc.in @echo creating pkgconfig @sed \ @@ -316,7 +333,8 @@ libzstd.pc: libzstd.pc.in -e 's|@INCLUDEDIR@|$(PCINCPREFIX)$(PCINCDIR)|' \ -e 's|@LIBDIR@|$(PCLIBPREFIX)$(PCLIBDIR)|' \ -e 's|@VERSION@|$(VERSION)|' \ - -e 's|@LIBS_PRIVATE@|$(LDFLAGS_DYNLIB)|' \ + -e 's|@LIBS_MT@|$(PCMTLIB)|' \ + -e 's|@LIBS_PRIVATE@|$(PCLIB)|' \ $< >$@ .PHONY: install diff --git a/lib/README.md b/lib/README.md index a560f06ca..0f6c64745 100644 --- a/lib/README.md +++ b/lib/README.md @@ -27,12 +27,16 @@ Enabling multithreading requires 2 conditions : For convenience, we provide a build target to generate multi and single threaded libraries: - Force enable multithreading on both dynamic and static libraries by appending `-mt` to the target, e.g. `make lib-mt`. + Note that the `.pc` generated on calling `make lib-mt` will already include the require Libs and Cflags. - Force disable multithreading on both dynamic and static libraries by appending `-nomt` to the target, e.g. `make lib-nomt`. - By default, as mentioned before, dynamic library is multithreaded, and static library is single-threaded, e.g. `make lib`. When linking a POSIX program with a multithreaded version of `libzstd`, note that it's necessary to invoke the `-pthread` flag during link stage. +The `.pc` generated from `make install` or `make install-pc` always assume a single-threaded static library +is compiled. To correctly generate a `.pc` for the multi-threaded static library, set `MT=1` as ENV variable. + Multithreading capabilities are exposed via the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.4.3/lib/zstd.h#L351). diff --git a/lib/libzstd.pc.in b/lib/libzstd.pc.in index d5cc0270c..d7b6c8582 100644 --- a/lib/libzstd.pc.in +++ b/lib/libzstd.pc.in @@ -11,6 +11,6 @@ Name: zstd Description: fast lossless compression algorithm library URL: https://facebook.github.io/zstd/ Version: @VERSION@ -Libs: -L${libdir} -lzstd +Libs: -L${libdir} -lzstd @LIBS_MT@ Libs.private: @LIBS_PRIVATE@ -Cflags: -I${includedir} +Cflags: -I${includedir} @LIBS_MT@ From 5be2a8721d527ae349539b459b35fb628467e00d Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Thu, 7 Mar 2024 21:40:27 +0900 Subject: [PATCH 016/405] meson: don't add -pthread to static linking flags on Windows Meson always returns -pthread in dependency('threads') on non-MSVC compilers. On Windows we use Windows threading primitives, so we don't need this. Avoid adding -pthread to libzstd's link flags, either as a Meson subproject or via pkg-config Libs.private, so the application doesn't inadvertently depend on winpthreads. Add a Meson MinGW cross-compile CI test that checks for this. It turns out that pzstd fails to build in that environment, so have the test skip building contrib for now. --- .github/workflows/dev-short-tests.yml | 44 +++++++++++++++++++++++++++ build/meson/meson.build | 9 ++++-- build/meson/meson_options.txt | 2 +- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 5324b38d9..b8afcb76b 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -237,6 +237,50 @@ jobs: meson test -C builddir/ --print-errorlogs meson install -C builddir --destdir staging/ + meson-mingw-cross-compilation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + - name: Install packages + run: | + sudo apt-get -qqq update + sudo apt-get -y install build-essential python3-pip ninja-build {gcc,g++}-mingw-w64-x86-64 + pip install --pre meson + - name: Build with Meson + run: | + cat > cross.ini < Date: Sat, 13 Apr 2024 02:24:14 +0700 Subject: [PATCH 017/405] fixed memory leaks and almost all undefined behaviour --- doc/educational_decoder/harness.c | 1 + lib/compress/zstd_compress.c | 2 +- lib/decompress/zstd_decompress.c | 2 +- programs/benchfn.c | 2 +- tests/bigdict.c | 11 ++++++++--- tests/paramgrill.c | 1 - tests/regression/result.c | 2 ++ tests/seqgen.c | 2 +- zlibWrapper/examples/minigzip.c | 4 ++-- zlibWrapper/gzwrite.c | 2 ++ 10 files changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/educational_decoder/harness.c b/doc/educational_decoder/harness.c index 12c5a801b..eb79ceacd 100644 --- a/doc/educational_decoder/harness.c +++ b/doc/educational_decoder/harness.c @@ -50,6 +50,7 @@ static buffer_s read_file(const char *path) fclose(f); buffer_s const b = { ptr, size }; + free(ptr); return b; } diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9284e2a48..d17182a46 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2764,7 +2764,7 @@ ZSTD_buildSequencesStatistics( const BYTE* const ofCodeTable = seqStorePtr->ofCode; const BYTE* const llCodeTable = seqStorePtr->llCode; const BYTE* const mlCodeTable = seqStorePtr->mlCode; - ZSTD_symbolEncodingTypeStats_t stats; + ZSTD_symbolEncodingTypeStats_t stats = {}; stats.lastCountSize = 0; /* convert length/distances into codes */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 2f03cf7b0..658cb2818 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -723,7 +723,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret) { - ZSTD_frameSizeInfo frameSizeInfo; + ZSTD_frameSizeInfo frameSizeInfo = {}; frameSizeInfo.compressedSize = ret; frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; return frameSizeInfo; diff --git a/programs/benchfn.c b/programs/benchfn.c index 3e042cf38..74cd21b20 100644 --- a/programs/benchfn.c +++ b/programs/benchfn.c @@ -91,7 +91,7 @@ static BMK_runOutcome_t BMK_runOutcome_error(size_t errorResult) static BMK_runOutcome_t BMK_setValid_runTime(BMK_runTime_t runTime) { - BMK_runOutcome_t outcome; + BMK_runOutcome_t outcome = {}; outcome.error_tag_never_ever_use_directly = 0; outcome.internal_never_ever_use_directly = runTime; return outcome; diff --git a/tests/bigdict.c b/tests/bigdict.c index ff2bb2d70..748b60e79 100644 --- a/tests/bigdict.c +++ b/tests/bigdict.c @@ -70,12 +70,14 @@ int main(int argc, const char** argv) char* buffer = (char*)malloc(bufferSize); void* out = malloc(outSize); void* roundtrip = malloc(dataSize); + int _exit_code = 0; (void)argc; (void)argv; if (!buffer || !out || !roundtrip || !cctx || !dctx) { fprintf(stderr, "Allocation failure\n"); - return 1; + _exit_code = 1; + goto cleanup; } if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 31))) @@ -119,10 +121,13 @@ int main(int argc, const char** argv) fprintf(stderr, "Success!\n"); + goto cleanup; + +cleanup: free(roundtrip); free(out); free(buffer); - ZSTD_freeDCtx(dctx); ZSTD_freeCCtx(cctx); - return 0; + ZSTD_freeDCtx(dctx); + return _exit_code; } diff --git a/tests/paramgrill.c b/tests/paramgrill.c index 8971c65d6..869e966e0 100644 --- a/tests/paramgrill.c +++ b/tests/paramgrill.c @@ -1273,7 +1273,6 @@ static int createBuffers(buffers_t* buff, const char* const * const fileNamesTab f = fopen(fileNamesTable[n], "rb"); if (f==NULL) { DISPLAY("impossible to open file %s\n", fileNamesTable[n]); - fclose(f); ret = 10; goto _cleanUp; } diff --git a/tests/regression/result.c b/tests/regression/result.c index 8ccb8751e..84a8a044d 100644 --- a/tests/regression/result.c +++ b/tests/regression/result.c @@ -24,5 +24,7 @@ char const* result_get_error_string(result_t result) { return "decompression error"; case result_error_round_trip_error: return "round trip error"; + default: + return "unknown error - " + result_get_error(result); } } diff --git a/tests/seqgen.c b/tests/seqgen.c index 0d8a766c8..efd528baa 100644 --- a/tests/seqgen.c +++ b/tests/seqgen.c @@ -31,7 +31,7 @@ static BYTE SEQ_randByte(unsigned* src) SEQ_stream SEQ_initStream(unsigned seed) { - SEQ_stream stream; + SEQ_stream stream = {}; stream.state = 0; XXH64_reset(&stream.xxh, 0); stream.seed = seed; diff --git a/zlibWrapper/examples/minigzip.c b/zlibWrapper/examples/minigzip.c index 1af815207..a06554212 100644 --- a/zlibWrapper/examples/minigzip.c +++ b/zlibWrapper/examples/minigzip.c @@ -234,7 +234,7 @@ int gzwrite _Z_OF((gzFile, const void *, unsigned)); int gzwrite(gzFile gz, const void *buf, unsigned len) { z_stream *strm; - unsigned char out[BUFLEN]; + unsigned char out[BUFLEN] = 0; if (gz == NULL || !gz->write) return 0; @@ -287,7 +287,7 @@ int gzclose _Z_OF((gzFile)); int gzclose(gzFile gz) { z_stream *strm; - unsigned char out[BUFLEN]; + unsigned char out[BUFLEN] = 0; if (gz == NULL) return Z_STREAM_ERROR; diff --git a/zlibWrapper/gzwrite.c b/zlibWrapper/gzwrite.c index 67f5eda6c..0a89c8d75 100644 --- a/zlibWrapper/gzwrite.c +++ b/zlibWrapper/gzwrite.c @@ -64,6 +64,8 @@ local int gz_init(gz_statep state) { strm->next_out = state.state->out; state.state->x.next = strm->next_out; } + + free(state.state); return 0; } From 4f41631aa4fffffac511d484ad10d603650e0156 Mon Sep 17 00:00:00 2001 From: Alex Murkoff <413x1nkp@gmail.com> Date: Sat, 13 Apr 2024 02:35:32 +0700 Subject: [PATCH 018/405] fixed ISO C incompatibility --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d17182a46..9284e2a48 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2764,7 +2764,7 @@ ZSTD_buildSequencesStatistics( const BYTE* const ofCodeTable = seqStorePtr->ofCode; const BYTE* const llCodeTable = seqStorePtr->llCode; const BYTE* const mlCodeTable = seqStorePtr->mlCode; - ZSTD_symbolEncodingTypeStats_t stats = {}; + ZSTD_symbolEncodingTypeStats_t stats; stats.lastCountSize = 0; /* convert length/distances into codes */ From 01cea2e1e2cf1cafa4b61e1bc8eb85618cf18c76 Mon Sep 17 00:00:00 2001 From: Alex Murkoff <413x1nkp@gmail.com> Date: Sat, 13 Apr 2024 02:37:13 +0700 Subject: [PATCH 019/405] fixed ISO C incompatibility for good this time... probably --- lib/decompress/zstd_decompress.c | 2 +- programs/benchfn.c | 2 +- tests/seqgen.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 658cb2818..2f03cf7b0 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -723,7 +723,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret) { - ZSTD_frameSizeInfo frameSizeInfo = {}; + ZSTD_frameSizeInfo frameSizeInfo; frameSizeInfo.compressedSize = ret; frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; return frameSizeInfo; diff --git a/programs/benchfn.c b/programs/benchfn.c index 74cd21b20..3e042cf38 100644 --- a/programs/benchfn.c +++ b/programs/benchfn.c @@ -91,7 +91,7 @@ static BMK_runOutcome_t BMK_runOutcome_error(size_t errorResult) static BMK_runOutcome_t BMK_setValid_runTime(BMK_runTime_t runTime) { - BMK_runOutcome_t outcome = {}; + BMK_runOutcome_t outcome; outcome.error_tag_never_ever_use_directly = 0; outcome.internal_never_ever_use_directly = runTime; return outcome; diff --git a/tests/seqgen.c b/tests/seqgen.c index efd528baa..0d8a766c8 100644 --- a/tests/seqgen.c +++ b/tests/seqgen.c @@ -31,7 +31,7 @@ static BYTE SEQ_randByte(unsigned* src) SEQ_stream SEQ_initStream(unsigned seed) { - SEQ_stream stream = {}; + SEQ_stream stream; stream.state = 0; XXH64_reset(&stream.xxh, 0); stream.seed = seed; From 75d0f66c879451e20f62f07162a38af2b314262a Mon Sep 17 00:00:00 2001 From: Alex Murkoff <413x1nkp@gmail.com> Date: Sat, 13 Apr 2024 12:51:20 +0700 Subject: [PATCH 020/405] reverted the addition of free at the gz_init() --- zlibWrapper/gzwrite.c | 1 - 1 file changed, 1 deletion(-) diff --git a/zlibWrapper/gzwrite.c b/zlibWrapper/gzwrite.c index 0a89c8d75..85b776a94 100644 --- a/zlibWrapper/gzwrite.c +++ b/zlibWrapper/gzwrite.c @@ -65,7 +65,6 @@ local int gz_init(gz_statep state) { state.state->x.next = strm->next_out; } - free(state.state); return 0; } From b4ecf724b15f0ab21a996339112680d3f4ba33eb Mon Sep 17 00:00:00 2001 From: Alex Murkoff <413x1nkp@gmail.com> Date: Sun, 14 Apr 2024 17:45:53 +0700 Subject: [PATCH 021/405] made initialize out char array with all elements set to 0 fixed where i made it to init with just the first one being set to 0 --- zlibWrapper/examples/minigzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zlibWrapper/examples/minigzip.c b/zlibWrapper/examples/minigzip.c index a06554212..c4ce5f479 100644 --- a/zlibWrapper/examples/minigzip.c +++ b/zlibWrapper/examples/minigzip.c @@ -234,7 +234,7 @@ int gzwrite _Z_OF((gzFile, const void *, unsigned)); int gzwrite(gzFile gz, const void *buf, unsigned len) { z_stream *strm; - unsigned char out[BUFLEN] = 0; + unsigned char out[BUFLEN] = { 0 }; if (gz == NULL || !gz->write) return 0; From 0b24fc0a113c92c5ba5ec78f7169a2ddfe0d700f Mon Sep 17 00:00:00 2001 From: Alex Murkoff <413x1nkp@gmail.com> Date: Sun, 14 Apr 2024 17:57:53 +0700 Subject: [PATCH 022/405] init out char array with all members as 0 x2 --- zlibWrapper/examples/minigzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zlibWrapper/examples/minigzip.c b/zlibWrapper/examples/minigzip.c index c4ce5f479..ef48d74d2 100644 --- a/zlibWrapper/examples/minigzip.c +++ b/zlibWrapper/examples/minigzip.c @@ -287,7 +287,7 @@ int gzclose _Z_OF((gzFile)); int gzclose(gzFile gz) { z_stream *strm; - unsigned char out[BUFLEN] = 0; + unsigned char out[BUFLEN] = { 0 }; if (gz == NULL) return Z_STREAM_ERROR; From 849b2ad907070c6a46cc4679f4f831eaebacc715 Mon Sep 17 00:00:00 2001 From: Alex Murkoff <413x1nkp@gmail.com> Date: Sun, 14 Apr 2024 20:44:12 +0700 Subject: [PATCH 023/405] removed freeing of the ptr --- doc/educational_decoder/harness.c | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/educational_decoder/harness.c b/doc/educational_decoder/harness.c index eb79ceacd..12c5a801b 100644 --- a/doc/educational_decoder/harness.c +++ b/doc/educational_decoder/harness.c @@ -50,7 +50,6 @@ static buffer_s read_file(const char *path) fclose(f); buffer_s const b = { ptr, size }; - free(ptr); return b; } From ff7a151f2e6c009b657d9f798c2d9962b0e3feb5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 21 Apr 2024 10:44:50 -0700 Subject: [PATCH 024/405] update test name --- tests/Makefile | 10 ++-- tests/largeDictionary.c | 128 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 tests/largeDictionary.c diff --git a/tests/Makefile b/tests/Makefile index ed3692a24..c458b682a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -224,9 +224,9 @@ roundTripCrash : $(ZSTD_OBJECTS) roundTripCrash.c CLEAN += longmatch longmatch : $(ZSTD_OBJECTS) longmatch.c -CLEAN += bigdict -bigdict: CFLAGS += $(MULTITHREAD) -bigdict: $(ZSTDMT_OBJECTS) $(PRGDIR)/datagen.c bigdict.c +CLEAN += largeDictionary +largeDictionary: CFLAGS += $(MULTITHREAD) +largeDictionary: $(ZSTDMT_OBJECTS) $(PRGDIR)/datagen.c largeDictionary.c CLEAN += invalidDictionaries invalidDictionaries : $(ZSTD_OBJECTS) invalidDictionaries.c @@ -391,8 +391,8 @@ test-zstream32: zstreamtest32 test-longmatch: longmatch $(QEMU_SYS) ./longmatch -test-bigdict: bigdict - $(QEMU_SYS) ./bigdict +test-largeDictionary: largeDictionary + $(QEMU_SYS) ./largeDictionary test-invalidDictionaries: invalidDictionaries $(QEMU_SYS) ./invalidDictionaries diff --git a/tests/largeDictionary.c b/tests/largeDictionary.c new file mode 100644 index 000000000..ff2bb2d70 --- /dev/null +++ b/tests/largeDictionary.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include +#include +#include +#include +#include +#include "datagen.h" +#include "mem.h" +#define ZSTD_STATIC_LINKING_ONLY +#include "zstd.h" + +static int +compress(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + void const* src, size_t srcSize, + void* roundtrip, ZSTD_EndDirective end) +{ + ZSTD_inBuffer in = {src, srcSize, 0}; + ZSTD_outBuffer out = {dst, dstCapacity, 0}; + int ended = 0; + + while (!ended && (in.pos < in.size || out.pos > 0)) { + size_t rc; + out.pos = 0; + rc = ZSTD_compressStream2(cctx, &out, &in, end); + if (ZSTD_isError(rc)) + return 1; + if (end == ZSTD_e_end && rc == 0) + ended = 1; + { + ZSTD_inBuffer rtIn = {dst, out.pos, 0}; + ZSTD_outBuffer rtOut = {roundtrip, srcSize, 0}; + rc = 1; + while (rtIn.pos < rtIn.size || rtOut.pos > 0) { + rtOut.pos = 0; + rc = ZSTD_decompressStream(dctx, &rtOut, &rtIn); + if (ZSTD_isError(rc)) { + fprintf(stderr, "Decompression error: %s\n", ZSTD_getErrorName(rc)); + return 1; + } + if (rc == 0) + break; + } + if (ended && rc != 0) { + fprintf(stderr, "Frame not finished!\n"); + return 1; + } + } + } + + return 0; +} + +int main(int argc, const char** argv) +{ + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + ZSTD_DCtx* dctx = ZSTD_createDCtx(); + const size_t dataSize = (size_t)1 << 30; + const size_t outSize = ZSTD_compressBound(dataSize); + const size_t bufferSize = (size_t)1 << 31; + char* buffer = (char*)malloc(bufferSize); + void* out = malloc(outSize); + void* roundtrip = malloc(dataSize); + (void)argc; + (void)argv; + + if (!buffer || !out || !roundtrip || !cctx || !dctx) { + fprintf(stderr, "Allocation failure\n"); + return 1; + } + + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 31))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_overlapLog, 9))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btopt))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, 7))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, 1))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 10))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, 10))) + return 1; + + if (ZSTD_isError(ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 31))) + return 1; + + RDG_genBuffer(buffer, bufferSize, 1.0, 0.0, 0xbeefcafe); + + /* Compress 30 GB */ + { + int i; + for (i = 0; i < 10; ++i) { + fprintf(stderr, "Compressing 1 GB\n"); + if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_continue)) + return 1; + } + } + fprintf(stderr, "Compressing 1 GB\n"); + if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_end)) + return 1; + + fprintf(stderr, "Success!\n"); + + free(roundtrip); + free(out); + free(buffer); + ZSTD_freeDCtx(dctx); + ZSTD_freeCCtx(cctx); + return 0; +} From 68a6d9b9f6ce605010ea1164590e4e015567dee7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 05:20:46 +0000 Subject: [PATCH 025/405] Bump github/codeql-action from 3.24.10 to 3.25.1 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.10 to 3.25.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4355270be187e1b672a7a1c7c7bae5afdc1ab94a...c7f9125735019aa87cfc361530512d50ea439c71) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 7a7750026..e117798ea 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # tag=v3.24.10 + uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # tag=v3.25.1 with: sarif_file: results.sarif From a86f5f3f33f40945c0d1341827fabc6a22338499 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 23 Apr 2024 09:31:35 -0700 Subject: [PATCH 026/405] update documentation of ZSTD_decompressStream() slightly more precise, by recommending to check the return value. fix #4030 --- lib/zstd.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/zstd.h b/lib/zstd.h index 5d1fef8a6..b79f675c3 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -855,7 +855,7 @@ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); * * A ZSTD_DStream object is required to track streaming operations. * Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. -* ZSTD_DStream objects can be reused multiple times. +* ZSTD_DStream objects can be re-employed multiple times. * * Use ZSTD_initDStream() to start a new decompression operation. * @return : recommended first input size @@ -865,16 +865,21 @@ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); * The function will update both `pos` fields. * If `input.pos < input.size`, some input has not been consumed. * It's up to the caller to present again remaining data. +* * The function tries to flush all data decoded immediately, respecting output buffer size. * If `output.pos < output.size`, decoder has flushed everything it could. -* But if `output.pos == output.size`, there might be some data left within internal buffers., +* +* However, when `output.pos == output.size`, it's more difficult to know. +* If @return > 0, the frame is not complete, meaning +* either there is still some data left to flush within internal buffers, +* or there is more input to read to complete the frame (or both). * In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer. * Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX. * @return : 0 when a frame is completely decoded and fully flushed, * or an error code, which can be tested using ZSTD_isError(), * or any other value > 0, which means there is still some decoding or flushing to do to complete current frame : * the return value is a suggested next input size (just a hint for better latency) -* that will never request more than the remaining frame size. +* that will never request more than the remaining content of the compressed frame. * *******************************************************************************/ typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ @@ -901,9 +906,10 @@ ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); * Function will update both input and output `pos` fields exposing current state via these fields: * - `input.pos < input.size`, some input remaining and caller should provide remaining input * on the next call. - * - `output.pos < output.size`, decoder finished and flushed all remaining buffers. - * - `output.pos == output.size`, potentially uncflushed data present in the internal buffers, - * call ZSTD_decompressStream() again to flush remaining data to output. + * - `output.pos < output.size`, decoder flushed internal output buffer. + * - `output.pos == output.size`, unflushed data potentially present in the internal buffers, + * check ZSTD_decompressStream() @return value, + * if > 0, invoke it again to flush remaining data to output. * Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX. * * @return : 0 when a frame is completely decoded and fully flushed, From d7cb47036cb78b3681aee4725107381a1b69abfc Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Fri, 26 Apr 2024 13:48:49 -0700 Subject: [PATCH 027/405] Make zstd.h compatible with -Wzero-as-null-pointer-constant --- lib/zstd.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/zstd.h b/lib/zstd.h index b79f675c3..e4c9ffc87 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1802,7 +1802,11 @@ static #ifdef __GNUC__ __attribute__((__unused__)) #endif +// Disable diagnostic for C++ compatibility +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ +#pragma clang diagnostic pop ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); From 97291fc5020a8994019ab76cf0cda83a9824374c Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Fri, 26 Apr 2024 14:44:41 -0700 Subject: [PATCH 028/405] Increase x-compatibility --- lib/zstd.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/zstd.h b/lib/zstd.h index e4c9ffc87..aa4ea23af 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1802,11 +1802,15 @@ static #ifdef __GNUC__ __attribute__((__unused__)) #endif -// Disable diagnostic for C++ compatibility + +#if defined(__clang__) && __clang_major__ >= 5 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ +#if defined(__clang__) && __clang_major__ >= 5 #pragma clang diagnostic pop +#endif ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); From 4356192cb2a16975720a04ac5681a495e7ef1acc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 05:18:11 +0000 Subject: [PATCH 029/405] Bump msys2/setup-msys2 from 2.22.0 to 2.23.0 Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.22.0 to 2.23.0. - [Release notes](https://github.com/msys2/setup-msys2/releases) - [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md) - [Commits](https://github.com/msys2/setup-msys2/compare/cc11e9188b693c2b100158c3322424c4cc1dadea...d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8) --- updated-dependencies: - dependency-name: msys2/setup-msys2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dev-long-tests.yml | 2 +- .github/workflows/dev-short-tests.yml | 2 +- .github/workflows/windows-artifacts.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index eb8f40a9a..cf73acac1 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -247,7 +247,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # tag=v2.22.0 + - uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # tag=v2.23.0 with: msystem: MINGW64 install: make diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index b8afcb76b..e8c25d283 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -499,7 +499,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # tag=v2.22.0 + - uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # tag=v2.23.0 with: msystem: ${{ matrix.msystem }} install: make diffutils diff --git a/.github/workflows/windows-artifacts.yml b/.github/workflows/windows-artifacts.yml index 60c163123..761b6c854 100644 --- a/.github/workflows/windows-artifacts.yml +++ b/.github/workflows/windows-artifacts.yml @@ -24,7 +24,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3 - - uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # tag=v2.22.0 + - uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # tag=v2.23.0 with: msystem: ${{ matrix.msystem }} install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc From 2955d92ac02eb60b6d0d00e7c6cd3f013ac020e6 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Tue, 14 May 2024 16:51:10 +0800 Subject: [PATCH 030/405] Improve support for IAR compiler with attributes and intrinsics --- lib/common/bits.h | 8 ++++++++ lib/common/compiler.h | 10 ++++++---- lib/common/entropy_common.c | 4 ++++ lib/common/mem.h | 6 ++++++ lib/zstd.h | 2 +- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/common/bits.h b/lib/common/bits.h index def56c474..992cc6925 100644 --- a/lib/common/bits.h +++ b/lib/common/bits.h @@ -43,6 +43,8 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val) # endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (unsigned)__builtin_ctz(val); +# elif defined(__ICCARM__) + return (unsigned)__builtin_ctz(val); # else return ZSTD_countTrailingZeros32_fallback(val); # endif @@ -82,6 +84,8 @@ MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val) # endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (unsigned)__builtin_clz(val); +# elif defined(__ICCARM__) + return (unsigned)__builtin_clz(val); # else return ZSTD_countLeadingZeros32_fallback(val); # endif @@ -105,6 +109,8 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val) # endif # elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__) return (unsigned)__builtin_ctzll(val); +# elif defined(__ICCARM__) + return (unsigned)__builtin_ctzll(val); # else { U32 mostSignificantWord = (U32)(val >> 32); @@ -136,6 +142,8 @@ MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val) # endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (unsigned)(__builtin_clzll(val)); +# elif defined(__ICCARM__) + return (unsigned)(__builtin_clzll(val)); # else { U32 mostSignificantWord = (U32)(val >> 32); diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 31880ecbe..1371212ef 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -27,7 +27,7 @@ # define INLINE_KEYWORD #endif -#if defined(__GNUC__) || defined(__ICCARM__) +#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__) # define FORCE_INLINE_ATTR __attribute__((always_inline)) #elif defined(_MSC_VER) # define FORCE_INLINE_ATTR __forceinline @@ -54,7 +54,7 @@ #endif /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__) # define UNUSED_ATTR __attribute__((unused)) #else # define UNUSED_ATTR @@ -95,6 +95,8 @@ #ifndef MEM_STATIC /* already defined in Linux Kernel mem.h */ #if defined(__GNUC__) # define MEM_STATIC static __inline UNUSED_ATTR +#elif defined(__IAR_SYSTEMS_ICC__) +# define MEM_STATIC static inline UNUSED_ATTR #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define MEM_STATIC static inline #elif defined(_MSC_VER) @@ -108,7 +110,7 @@ #ifdef _MSC_VER # define FORCE_NOINLINE static __declspec(noinline) #else -# if defined(__GNUC__) || defined(__ICCARM__) +# if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__) # define FORCE_NOINLINE static __attribute__((__noinline__)) # else # define FORCE_NOINLINE static @@ -117,7 +119,7 @@ /* target attribute */ -#if defined(__GNUC__) || defined(__ICCARM__) +#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__) # define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) #else # define TARGET_ATTRIBUTE(target) diff --git a/lib/common/entropy_common.c b/lib/common/entropy_common.c index e2173afb0..abc8b543e 100644 --- a/lib/common/entropy_common.c +++ b/lib/common/entropy_common.c @@ -38,7 +38,11 @@ const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } /*-************************************************************** * FSE NCount encoding-decoding ****************************************************************/ +#if defined(__IAR_SYSTEMS_ICC__) +MEM_STATIC +#else FORCE_INLINE_TEMPLATE +#endif size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, const void* headerBuffer, size_t hbSize) { diff --git a/lib/common/mem.h b/lib/common/mem.h index 096f4be51..a02141c9d 100644 --- a/lib/common/mem.h +++ b/lib/common/mem.h @@ -30,6 +30,8 @@ extern "C" { #if defined(_MSC_VER) /* Visual Studio */ # include /* _byteswap_ulong */ # include /* _byteswap_* */ +#elif defined(__ICCARM__) +# include #endif /*-************************************************************** @@ -154,6 +156,8 @@ MEM_STATIC unsigned MEM_isLittleEndian(void) return 1; #elif defined(__DMC__) && defined(_M_IX86) return 1; +#elif defined(__IAR_SYSTEMS_ICC__) && __LITTLE_ENDIAN__ + return 1; #else const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ return one.c[0]; @@ -246,6 +250,8 @@ MEM_STATIC U32 MEM_swap32(U32 in) #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \ || (defined(__clang__) && __has_builtin(__builtin_bswap32)) return __builtin_bswap32(in); +#elif defined(__ICCARM__) + return __REV(in); #else return MEM_swap32_fallback(in); #endif diff --git a/lib/zstd.h b/lib/zstd.h index aa4ea23af..338bdb7ed 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -57,7 +57,7 @@ extern "C" { #else # if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ # define ZSTD_DEPRECATED(message) [[deprecated(message)]] -# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) +# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) || defined(__IAR_SYSTEMS_ICC__) # define ZSTD_DEPRECATED(message) __attribute__((deprecated(message))) # elif defined(__GNUC__) && (__GNUC__ >= 3) # define ZSTD_DEPRECATED(message) __attribute__((deprecated)) From 5fadd8e6b1229e3116ba53a8cd34b678df403d97 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Wed, 15 May 2024 10:47:50 +0800 Subject: [PATCH 031/405] revert FSE_readNCount_body attribute --- lib/common/entropy_common.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/common/entropy_common.c b/lib/common/entropy_common.c index abc8b543e..e2173afb0 100644 --- a/lib/common/entropy_common.c +++ b/lib/common/entropy_common.c @@ -38,11 +38,7 @@ const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } /*-************************************************************** * FSE NCount encoding-decoding ****************************************************************/ -#if defined(__IAR_SYSTEMS_ICC__) -MEM_STATIC -#else FORCE_INLINE_TEMPLATE -#endif size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, const void* headerBuffer, size_t hbSize) { From 1872688e0adb630e8710cb3d17846ca49f596e46 Mon Sep 17 00:00:00 2001 From: Adenilson Cavalcanti Date: Fri, 17 May 2024 13:37:55 -0700 Subject: [PATCH 032/405] [fix] Add check on failed allocation in legacy/zstd_v06 As reported by Ben Hawkes in #4026, a failure to allocate a zstd context would lead to a dereference of a NULL pointer due to a missing check on the returned result of ZSTDv06_createDCtx(). This patch fix the issue by adding a check for valid returned pointer. --- lib/legacy/zstd_v06.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index 00d6ef79a..3a8bd0c93 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -3919,6 +3919,10 @@ ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void) if (zbd==NULL) return NULL; memset(zbd, 0, sizeof(*zbd)); zbd->zd = ZSTDv06_createDCtx(); + if (zbd->zd==NULL) { + ZBUFFv06_freeDCtx(zbd); /* avoid leaking the context */ + return NULL; + } zbd->stage = ZBUFFds_init; return zbd; } From 4c6a519fdd8caef500244b838beab7f7a160f70f Mon Sep 17 00:00:00 2001 From: Jure Bajic Date: Sun, 26 May 2024 11:33:39 +0200 Subject: [PATCH 033/405] [fix] Add newline when file exceeds 128KB --- programs/dibio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/dibio.c b/programs/dibio.c index 26ebe5ca1..7ba22d15b 100644 --- a/programs/dibio.c +++ b/programs/dibio.c @@ -298,7 +298,7 @@ static fileStats DiB_fileStats(const char** fileNamesTable, int nbFiles, size_t fs.oneSampleTooLarge |= (fileSize > 2*SAMPLESIZE_MAX); /* Limit to the first SAMPLESIZE_MAX (128kB) of the file */ - DISPLAYLEVEL(3, "Sample file '%s' is too large, limiting to %d KB", + DISPLAYLEVEL(3, "Sample file '%s' is too large, limiting to %d KB\n", fileNamesTable[n], SAMPLESIZE_MAX / (1 KB)); } fs.nbSamples += 1; From 5e9a6c2fe4e4bfabeef750642871e3edcf6c6d79 Mon Sep 17 00:00:00 2001 From: Federico Maresca <62501138+Federico-Maresca@users.noreply.github.com> Date: Wed, 29 May 2024 18:35:24 +0200 Subject: [PATCH 034/405] Refactor dictionary matchfinder index safety check (#4039) --- lib/compress/zstd_compress_internal.h | 7 +++++++ lib/compress/zstd_double_fast.c | 8 ++++---- lib/compress/zstd_fast.c | 7 +++---- lib/compress/zstd_lazy.c | 16 ++++++++-------- lib/compress/zstd_opt.c | 4 ++-- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index e41d7b78e..f8ec1c82e 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1315,6 +1315,13 @@ MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, return matchLowest; } +/* index_safety_check: + * intentional underflow : ensure repIndex isn't overlapping dict + prefix + * @return 1 if values are not overlapping, + * 0 otherwise */ +MEM_STATIC int ZSTD_index_overlap_check(const U32 prefixLowestIndex, const U32 repIndex) { + return ((U32)((prefixLowestIndex-1) - repIndex) >= 3); +} /* debug functions */ diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index a4e9c50d3..1b5f64f20 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -392,7 +392,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( hashLong[h2] = hashSmall[h] = curr; /* update hash tables */ /* check repcode */ - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; @@ -513,7 +513,7 @@ _match_stored: const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ? dictBase + repIndex2 - dictIndexDelta : base + repIndex2; - if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) + if ( (ZSTD_index_overlap_check(prefixLowestIndex, repIndex2)) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend; size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4; @@ -651,7 +651,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( size_t mLength; hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */ - if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */ + if (((ZSTD_index_overlap_check(prefixStartIndex, repIndex)) & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; @@ -719,7 +719,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( U32 const current2 = (U32)(ip-base); U32 const repIndex2 = current2 - offset_2; const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; - if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */ + if ( ((ZSTD_index_overlap_check(prefixStartIndex, repIndex2)) & (offset_2 <= current2 - dictStartIndex)) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 6c4554cfc..c6baa49d4 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -546,8 +546,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( size_t const dictHashAndTag1 = ZSTD_hashPtr(ip1, dictHBits, mls); hashTable[hash0] = curr; /* update hash table */ - if (((U32) ((prefixStartIndex - 1) - repIndex) >= - 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */ + if ((ZSTD_index_overlap_check(prefixStartIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip0 + 1))) { const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip0 + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4; @@ -631,7 +630,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase - dictIndexDelta + repIndex2 : base + repIndex2; - if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) + if ( (ZSTD_index_overlap_check(prefixStartIndex, repIndex2)) && (MEM_read32(repMatch2) == MEM_read32(ip0))) { const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; @@ -925,7 +924,7 @@ _match: /* Requires: ip0, match0, offcode, matchEnd */ while (ip0 <= ilimit) { U32 const repIndex2 = (U32)(ip0-base) - offset_2; const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; - if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 > 0)) /* intentional underflow */ + if ( ((ZSTD_index_overlap_check(prefixStartIndex, repIndex2)) & (offset_2 > 0)) && (MEM_read32(repMatch2) == MEM_read32(ip0)) ) { const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 67dd55fdb..9efaf4b25 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -1590,7 +1590,7 @@ size_t ZSTD_compressBlock_lazy_generic( && repIndex < prefixLowestIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; @@ -1642,7 +1642,7 @@ size_t ZSTD_compressBlock_lazy_generic( const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip)) ) { const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; @@ -1678,7 +1678,7 @@ size_t ZSTD_compressBlock_lazy_generic( const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip)) ) { const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; @@ -1740,7 +1740,7 @@ _storeSequence: const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase - dictIndexDelta + repIndex : base + repIndex; - if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */) + if ( (ZSTD_index_overlap_check(prefixLowestIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip)) ) { const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend; matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4; @@ -1986,7 +1986,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const U32 repIndex = (U32)(curr+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ + if ( (ZSTD_index_overlap_check(dictLimit, repIndex)) & (offset_1 <= curr+1 - windowLow) ) /* note: we are searching at curr+1 */ if (MEM_read32(ip+1) == MEM_read32(repMatch)) { /* repcode detected we should take it */ @@ -2027,7 +2027,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + if ( (ZSTD_index_overlap_check(dictLimit, repIndex)) & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ @@ -2059,7 +2059,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + if ( (ZSTD_index_overlap_check(dictLimit, repIndex)) & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ @@ -2113,7 +2113,7 @@ _storeSequence: const U32 repIndex = repCurrent - offset_2; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + if ( (ZSTD_index_overlap_check(dictLimit, repIndex)) & (offset_2 <= repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected we should take it */ diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index e63073e5a..8a4345b31 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -664,13 +664,13 @@ ZSTD_insertBtAndGetAllMatches ( assert(curr >= windowLow); if ( dictMode == ZSTD_extDict && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow) /* equivalent to `curr > repIndex >= windowLow` */ - & (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */) + & (ZSTD_index_overlap_check(dictLimit, repIndex)) ) && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch; } if (dictMode == ZSTD_dictMatchState && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `curr > repIndex >= dmsLowLimit` */ - & ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (ZSTD_index_overlap_check(dictLimit, repIndex)) ) && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch; } } From 949689facf96c4bce6953d07f0658412077bcbf1 Mon Sep 17 00:00:00 2001 From: Elliot Gorokhovsky Date: Mon, 3 Jun 2024 08:36:07 -0700 Subject: [PATCH 035/405] Drop FreeBSD 13.2 CI --- .cirrus.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index bf3f0c415..f68e39ae1 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,7 +3,6 @@ task: freebsd_instance: matrix: image_family: freebsd-14-0 - image_family: freebsd-13-2 install_script: pkg install -y gmake coreutils script: | MOREFLAGS="-Werror" gmake -j all From be6a18200621dd21ce073b77fce7f57636a6f4f4 Mon Sep 17 00:00:00 2001 From: Elliot Gorokhovsky Date: Mon, 3 Jun 2024 12:42:27 -0400 Subject: [PATCH 036/405] Unit test for external sequence producer + static CCtx + streaming (#4063) --- tests/zstreamtest.c | 63 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index e0ee4c3e9..e4110eb21 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -2356,7 +2356,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : Testing external sequence producer with static CCtx: ", testNb++); + DISPLAYLEVEL(3, "test%3i : Testing external sequence producer with static CCtx (one-shot): ", testNb++); { size_t const dstBufSize = ZSTD_compressBound(CNBufferSize); BYTE* const dstBuf = (BYTE*)malloc(dstBufSize); @@ -2375,7 +2375,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) size_t const cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); cctxBuf = malloc(cctxSize); staticCCtx = ZSTD_initStaticCCtx(cctxBuf, cctxSize); - ZSTD_CCtx_setParametersUsingCCtxParams(staticCCtx, params); + CHECK_Z(ZSTD_CCtx_setParametersUsingCCtxParams(staticCCtx, params)); } // Check that compression with external sequence producer succeeds when expected @@ -2408,6 +2408,65 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : Testing external sequence producer with static CCtx (streaming): ", testNb++); + { + size_t const dstBufSize = ZSTD_compressBound(CNBufferSize); + BYTE* const dstBuf = (BYTE*)malloc(dstBufSize); + size_t const checkBufSize = CNBufferSize; + BYTE* const checkBuf = (BYTE*)malloc(checkBufSize); + ZSTD_CCtx_params* params = ZSTD_createCCtxParams(); + ZSTD_CCtx* staticCCtx; + void* cctxBuf; + EMF_testCase seqProdState; + + CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_validateSequences, 1)); + CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_enableSeqProducerFallback, 0)); + ZSTD_CCtxParams_registerSequenceProducer(params, &seqProdState, zstreamSequenceProducer); + + { + size_t const cctxSize = ZSTD_estimateCStreamSize_usingCCtxParams(params); + cctxBuf = malloc(cctxSize); + staticCCtx = ZSTD_initStaticCCtx(cctxBuf, cctxSize); + CHECK_Z(ZSTD_CCtx_setParametersUsingCCtxParams(staticCCtx, params)); + } + + // Check that compression with external sequence producer succeeds when expected + seqProdState = EMF_LOTS_OF_SEQS; + { + ZSTD_inBuffer inBuf = { CNBuffer, CNBufferSize, 0 }; + ZSTD_outBuffer outBuf = { dstBuf, dstBufSize, 0 }; + size_t dResult; + CHECK_Z(ZSTD_compressStream(staticCCtx, &outBuf, &inBuf)); + CHECK_Z(ZSTD_endStream(staticCCtx, &outBuf)); + CHECK(inBuf.pos != inBuf.size, "EMF: inBuf.pos != inBuf.size"); + dResult = ZSTD_decompress(checkBuf, checkBufSize, outBuf.dst, outBuf.pos); + CHECK(ZSTD_isError(dResult), "EMF: Decompression error: %s", ZSTD_getErrorName(dResult)); + CHECK(dResult != CNBufferSize, "EMF: Corruption!"); + CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, "EMF: Corruption!"); + } + + CHECK_Z(ZSTD_CCtx_reset(staticCCtx, ZSTD_reset_session_only)); + + // Check that compression with external sequence producer fails when expected + seqProdState = EMF_BIG_ERROR; + { + ZSTD_inBuffer inBuf = { CNBuffer, CNBufferSize, 0 }; + ZSTD_outBuffer outBuf = { dstBuf, dstBufSize, 0 }; + size_t const cResult = ZSTD_compressStream(staticCCtx, &outBuf, &inBuf); + CHECK(!ZSTD_isError(cResult), "EMF: Should have raised an error!"); + CHECK( + ZSTD_getErrorCode(cResult) != ZSTD_error_sequenceProducer_failed, + "EMF: Wrong error code: %s", ZSTD_getErrorName(cResult) + ); + } + + free(dstBuf); + free(checkBuf); + free(cctxBuf); + ZSTD_freeCCtxParams(params); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : Decoder should reject invalid frame header on legacy frames: ", testNb++); { const unsigned char compressed[] = { 0x26,0xb5,0x2f,0xfd,0x50,0x91,0xfd,0xd8,0xb5 }; From 2acf90431ab2ffdc7d85d1017cf344bac897e704 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 3 Jun 2024 18:30:23 -0700 Subject: [PATCH 037/405] minor:doc: specify decompression behavior in presence of multiple concatenated frames directly at ZSTD_decompress() level. --- lib/zstd.h | 59 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/lib/zstd.h b/lib/zstd.h index 338bdb7ed..ce2b1c7de 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -157,37 +157,40 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, int compressionLevel); /*! ZSTD_decompress() : - * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. - * `dstCapacity` is an upper bound of originalSize to regenerate. - * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. - * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), - * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ + * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + * Multiple compressed frames can be decompressed at once with this method. + * The result will be the concatenation of all decompressed frames, back to back. + * `dstCapacity` is an upper bound of originalSize to regenerate. + * First frame's decompressed size can be extracted using ZSTD_getFrameContentSize(). + * If maximum upper bound isn't known, prefer using streaming mode to decompress data. + * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, const void* src, size_t compressedSize); /*! ZSTD_getFrameContentSize() : requires v1.3.0+ - * `src` should point to the start of a ZSTD encoded frame. - * `srcSize` must be at least as large as the frame header. - * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. - * @return : - decompressed size of `src` frame content, if known - * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) - * note 1 : a 0 return value means the frame is valid but "empty". - * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. - * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * Optionally, application can rely on some implicit limit, - * as ZSTD_decompress() only needs an upper bound of decompressed size. - * (For example, data could be necessarily cut into blocks <= 16 KB). - * note 3 : decompressed size is always present when compression is completed using single-pass functions, - * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). - * note 4 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure return value fits within application's authorized limits. - * Each application can set its own limits. - * note 6 : This function replaces ZSTD_getDecompressedSize() */ + * `src` should point to the start of a ZSTD encoded frame. + * `srcSize` must be at least as large as the frame header. + * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. + * @return : - decompressed size of `src` frame content, if known + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) + * note 1 : a 0 return value means the frame is valid but "empty". + * note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode). + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * Optionally, application can rely on some implicit limit, + * as ZSTD_decompress() only needs an upper bound of decompressed size. + * (For example, data could be necessarily cut into blocks <= 16 KB). + * note 3 : decompressed size is always present when compression is completed using single-pass functions, + * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). + * note 4 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure return value fits within application's authorized limits. + * Each application can set its own limits. + * note 6 : This function replaces ZSTD_getDecompressedSize() */ #define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) #define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); @@ -1802,7 +1805,7 @@ static #ifdef __GNUC__ __attribute__((__unused__)) #endif - + #if defined(__clang__) && __clang_major__ >= 5 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" From f19c98228f773413850736b3aab574a63f03f2bc Mon Sep 17 00:00:00 2001 From: Quentin Boswank Date: Wed, 5 Jun 2024 18:21:34 +0200 Subject: [PATCH 038/405] Fix $filter and Msys/Cygwin - switched the patter and input of $filter into the right places - added pattern wildcard to MSYS_NT & CYGWIN_NT as they change with windows versions - correctly identify MSYS2, even in an env like MINGW64 --- Makefile | 8 ++++---- doc/educational_decoder/Makefile | 2 +- lib/Makefile | 14 +++++++++++--- lib/libzstd.mk | 2 +- programs/Makefile | 6 +++--- tests/Makefile | 8 ++++---- tests/fuzz/Makefile | 2 +- tests/gzip/Makefile | 2 +- 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index b2d985feb..5598cdd03 100644 --- a/Makefile +++ b/Makefile @@ -151,7 +151,7 @@ clean: #------------------------------------------------------------------------------ # make install is validated only for Linux, macOS, Hurd and some BSD targets #------------------------------------------------------------------------------ -ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD MSYS_NT CYGWIN_NT Haiku AIX)) +ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD DragonFly NetBSD MSYS_NT% CYGWIN_NT% Haiku AIX,$(shell sh -c 'MSYSTEM="MSYS" uname') )) HOST_OS = POSIX @@ -390,19 +390,19 @@ lz4install: endif -ifneq (,$(filter MSYS%,$(shell uname))) +ifneq (,$(filter MSYS%,$(shell sh -c 'MSYSTEM="MSYS" uname') )) HOST_OS = MSYS endif #------------------------------------------------------------------------ # target specific tests #------------------------------------------------------------------------ -ifneq (,$(filter $(HOST_OS),MSYS POSIX)) +ifneq (,$(filter MSYS POSIX,$(HOST_OS))) CMAKE ?= cmake CMAKE_PARAMS = -DZSTD_BUILD_CONTRIB:BOOL=ON -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZLIB_SUPPORT:BOOL=ON -DZSTD_LZMA_SUPPORT:BOOL=ON -ifneq (,$(filter MSYS%,$(shell uname))) +ifneq (,$(filter MSYS%,$(shell sh -c 'MSYSTEM="MSYS" uname'))) CMAKE_PARAMS = -G"MSYS Makefiles" -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON endif diff --git a/doc/educational_decoder/Makefile b/doc/educational_decoder/Makefile index f6deeb13d..b3154d9af 100644 --- a/doc/educational_decoder/Makefile +++ b/doc/educational_decoder/Makefile @@ -10,7 +10,7 @@ ZSTD ?= zstd # note: requires zstd installation on local system -UNAME?= $(shell uname) +UNAME?= $(shell sh -c 'MSYSTEM="MSYS" uname') ifeq ($(UNAME), SunOS) DIFF ?= gdiff else diff --git a/lib/Makefile b/lib/Makefile index 57097ce3f..ccfdfedd6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -266,7 +266,7 @@ clean: #----------------------------------------------------------------------------- # make install is validated only for below listed environments #----------------------------------------------------------------------------- -ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT CYGWIN_NT)) +ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT% CYGWIN_NT%,$(UNAME))) lib: libzstd.pc @@ -305,13 +305,21 @@ else PCLIB := $(LDFLAGS_DYNLIB) endif -ifneq (,$(filter $(UNAME),FreeBSD NetBSD DragonFly)) + +ifneq ($(MT),) + PCLIB := + PCMTLIB := $(LDFLAGS_DYNLIB) +else + PCLIB := $(LDFLAGS_DYNLIB) +endif + +ifneq (,$(filter FreeBSD NetBSD DragonFly,$(UNAME))) PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig else PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig endif -ifneq (,$(filter $(UNAME),SunOS)) +ifneq (,$(filter SunOS,$(UNAME))) INSTALL ?= ginstall else INSTALL ?= install diff --git a/lib/libzstd.mk b/lib/libzstd.mk index 14b3b11d6..a2a965037 100644 --- a/lib/libzstd.mk +++ b/lib/libzstd.mk @@ -206,7 +206,7 @@ endif endif CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) -UNAME := $(shell uname) +UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname') ifndef BUILD_DIR ifeq ($(UNAME), Darwin) diff --git a/programs/Makefile b/programs/Makefile index 4dcd84105..e1a30fc2b 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -345,7 +345,7 @@ include $(wildcard $(DEPFILES)) #----------------------------------------------------------------------------- # make install is validated only for Linux, macOS, BSD, Hurd and Solaris targets #----------------------------------------------------------------------------- -ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT CYGWIN_NT)) +ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT% CYGWIN_NT%,$(UNAME))) HAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0) EGREP_OPTIONS ?= @@ -388,14 +388,14 @@ datarootdir ?= $(PREFIX)/share mandir ?= $(datarootdir)/man man1dir ?= $(mandir)/man1 -ifneq (,$(filter $(UNAME),OpenBSD FreeBSD NetBSD DragonFly SunOS)) +ifneq (,$(filter OpenBSD FreeBSD NetBSD DragonFly SunOS,$(UNAME))) MANDIR ?= $(PREFIX)/man MAN1DIR ?= $(MANDIR)/man1 else MAN1DIR ?= $(man1dir) endif -ifneq (,$(filter $(UNAME),SunOS)) +ifneq (,$(filter SunOS,$(UNAME))) INSTALL ?= ginstall else INSTALL ?= install diff --git a/tests/Makefile b/tests/Makefile index c458b682a..5c0607d10 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -271,8 +271,8 @@ clean: #---------------------------------------------------------------------------------- # valgrind tests validated only for some posix platforms #---------------------------------------------------------------------------------- -UNAME := $(shell uname) -ifneq (,$(filter $(UNAME),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS AIX CYGWIN_NT)) +UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname') +ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS AIX CYGWIN_NT%,$(UNAME))) HOST_OS = POSIX .PHONY: test-valgrind @@ -300,10 +300,10 @@ endif #----------------------------------------------------------------------------- # make tests validated only for below targets #----------------------------------------------------------------------------- -ifneq (,$(filter $(HOST_OS),MSYS POSIX)) +ifneq (,$(filter MSYS POSIX,$(HOST_OS))) DIFF:=diff -ifneq (,$(filter $(UNAME),SunOS)) +ifneq (,$(filter SunOS,$(UNAME))) DIFF:=gdiff endif diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index 430f6df15..1333675d0 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -17,7 +17,7 @@ LDFLAGS ?= ARFLAGS ?= LIB_FUZZING_ENGINE ?= libregression.a PYTHON ?= python -ifeq ($(shell uname), Darwin) +ifeq ($(shell sh -c 'MSYSTEM="MSYS" uname') , Darwin) DOWNLOAD?=curl -L -o else DOWNLOAD?=wget -O diff --git a/tests/gzip/Makefile b/tests/gzip/Makefile index cca310967..23f5cfdc3 100644 --- a/tests/gzip/Makefile +++ b/tests/gzip/Makefile @@ -36,7 +36,7 @@ clean: #------------------------------------------------------------------------------ # validated only for Linux, macOS, Hurd and some BSD targets #------------------------------------------------------------------------------ -ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD)) +ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD,$(shell sh -c 'MSYSTEM="MSYS" uname') )) test-%: zstd @./test-driver.sh --test-name $* --log-file $*.log --trs-file $*.trs --expect-failure "no" --color-tests "yes" --enable-hard-errors "yes" ./$*.sh From d7a84a683fe345342139660b9d3a36328ed5f4b3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 12 Jun 2024 09:51:01 -0700 Subject: [PATCH 039/405] added cygwin install test --- .github/workflows/dev-short-tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index e8c25d283..0269e8369 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -576,6 +576,11 @@ jobs: make -j allzstd && make -C tests fuzzer && ./tests/fuzzer.exe -v -T1m + - name: cygwin install test + shell: C:\cygwin\bin\bash.exe --noprofile --norc -eo pipefail '{0}' + run: >- + make -j && + make install pkg-config: runs-on: ubuntu-latest From 3242ac598e6f17d8008f6110337a3b4c1205842b Mon Sep 17 00:00:00 2001 From: Elliot Gorokhovsky Date: Fri, 14 Jun 2024 14:38:48 -0400 Subject: [PATCH 040/405] Expose size estimation helpers for Linux (#4064) --- contrib/linux-kernel/linux_zstd.h | 36 +++++++++++++ contrib/linux-kernel/zstd_compress_module.c | 56 +++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/contrib/linux-kernel/linux_zstd.h b/contrib/linux-kernel/linux_zstd.h index f109d49f4..a7ce080dc 100644 --- a/contrib/linux-kernel/linux_zstd.h +++ b/contrib/linux-kernel/linux_zstd.h @@ -153,6 +153,20 @@ typedef ZSTD_CCtx zstd_cctx; */ size_t zstd_cctx_workspace_bound(const zstd_compression_parameters *parameters); +/** + * zstd_cctx_workspace_bound_with_ext_seq_prod() - max memory needed to + * initialize a zstd_cctx when using the block-level external sequence + * producer API. + * @parameters: The compression parameters to be used. + * + * If multiple compression parameters might be used, the caller must call + * this function for each set of parameters and use the maximum size. + * + * Return: A lower bound on the size of the workspace that is passed to + * zstd_init_cctx(). + */ +size_t zstd_cctx_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *parameters); + /** * zstd_init_cctx() - initialize a zstd compression context * @workspace: The workspace to emplace the context into. It must outlive @@ -257,6 +271,16 @@ typedef ZSTD_CStream zstd_cstream; */ size_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams); +/** + * zstd_cstream_workspace_bound_with_ext_seq_prod() - memory needed to initialize + * a zstd_cstream when using the block-level external sequence producer API. + * @cparams: The compression parameters to be used for compression. + * + * Return: A lower bound on the size of the workspace that is passed to + * zstd_init_cstream(). + */ +size_t zstd_cstream_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *cparams); + /** * zstd_init_cstream() - initialize a zstd streaming compression context * @parameters The zstd parameters to use for compression. @@ -416,6 +440,18 @@ size_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output, */ size_t zstd_find_frame_compressed_size(const void *src, size_t src_size); +/** + * zstd_register_sequence_producer() - exposes the zstd library function + * ZSTD_registerSequenceProducer(). This is used for the block-level external + * sequence producer API. See upstream zstd.h for detailed documentation. + */ +typedef ZSTD_sequenceProducer_F zstd_sequence_producer_f; +void zstd_register_sequence_producer( + zstd_cctx *cctx, + void* sequence_producer_state, + zstd_sequence_producer_f sequence_producer +); + /** * struct zstd_frame_params - zstd frame parameters stored in the frame header * @frameContentSize: The frame content size, or ZSTD_CONTENTSIZE_UNKNOWN if not diff --git a/contrib/linux-kernel/zstd_compress_module.c b/contrib/linux-kernel/zstd_compress_module.c index 8ecf43226..039db55f9 100644 --- a/contrib/linux-kernel/zstd_compress_module.c +++ b/contrib/linux-kernel/zstd_compress_module.c @@ -16,6 +16,7 @@ #include "common/zstd_deps.h" #include "common/zstd_internal.h" +#include "compress/zstd_compress_internal.h" #define ZSTD_FORWARD_IF_ERR(ret) \ do { \ @@ -85,6 +86,52 @@ size_t zstd_cctx_workspace_bound(const zstd_compression_parameters *cparams) } EXPORT_SYMBOL(zstd_cctx_workspace_bound); +// Used by zstd_cctx_workspace_bound_with_ext_seq_prod() +static size_t dummy_external_sequence_producer( + void *sequenceProducerState, + ZSTD_Sequence *outSeqs, size_t outSeqsCapacity, + const void *src, size_t srcSize, + const void *dict, size_t dictSize, + int compressionLevel, + size_t windowSize) +{ + (void)sequenceProducerState; + (void)outSeqs; (void)outSeqsCapacity; + (void)src; (void)srcSize; + (void)dict; (void)dictSize; + (void)compressionLevel; + (void)windowSize; + return ZSTD_SEQUENCE_PRODUCER_ERROR; +} + +static void init_cctx_params_from_compress_params( + ZSTD_CCtx_params *cctx_params, + const zstd_compression_parameters *compress_params) +{ + ZSTD_parameters zstd_params; + memset(&zstd_params, 0, sizeof(zstd_params)); + zstd_params.cParams = *compress_params; + ZSTD_CCtxParams_init_advanced(cctx_params, zstd_params); +} + +size_t zstd_cctx_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *compress_params) +{ + ZSTD_CCtx_params cctx_params; + init_cctx_params_from_compress_params(&cctx_params, compress_params); + ZSTD_CCtxParams_registerSequenceProducer(&cctx_params, NULL, dummy_external_sequence_producer); + return ZSTD_estimateCCtxSize_usingCCtxParams(&cctx_params); +} +EXPORT_SYMBOL(zstd_cctx_workspace_bound_with_ext_seq_prod); + +size_t zstd_cstream_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *compress_params) +{ + ZSTD_CCtx_params cctx_params; + init_cctx_params_from_compress_params(&cctx_params, compress_params); + ZSTD_CCtxParams_registerSequenceProducer(&cctx_params, NULL, dummy_external_sequence_producer); + return ZSTD_estimateCStreamSize_usingCCtxParams(&cctx_params); +} +EXPORT_SYMBOL(zstd_cstream_workspace_bound_with_ext_seq_prod); + zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size) { if (workspace == NULL) @@ -160,5 +207,14 @@ size_t zstd_end_stream(zstd_cstream *cstream, zstd_out_buffer *output) } EXPORT_SYMBOL(zstd_end_stream); +void zstd_register_sequence_producer( + zstd_cctx *cctx, + void* sequence_producer_state, + zstd_sequence_producer_f sequence_producer +) { + ZSTD_registerSequenceProducer(cctx, sequence_producer_state, sequence_producer); +} +EXPORT_SYMBOL(zstd_register_sequence_producer); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Zstd Compressor"); From 80170f6aad9f48574b108584e7504b0f9254958f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 18 Jun 2024 20:21:25 -0700 Subject: [PATCH 041/405] fix macos build weird: after replacing the UNAME line with an identical one, it does work properly now(??). Possibly a case of hidden special character? --- .github/workflows/dev-long-tests.yml | 6 +++--- lib/Makefile | 8 -------- lib/libzstd.mk | 2 +- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index cf73acac1..82e893cb9 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -31,12 +31,12 @@ jobs: run: make test # lasts ~26mn - make-test-osx: + make-test-macos: runs-on: macos-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: OS-X test - run: make test # make -c lib all doesn't work because of the fact that it's not a tty + - name: make test on macos + run: make test # lasts ~24mn make-test-32bit: diff --git a/lib/Makefile b/lib/Makefile index ccfdfedd6..020d2ff5d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -298,14 +298,6 @@ PCLIBPREFIX := $(if $(findstring $(LIBDIR),$(PCLIBDIR)),,$${exec_prefix}) PCEXEC_PREFIX := $(if $(HAS_EXPLICIT_EXEC_PREFIX),$(EXEC_PREFIX),$${prefix}) -ifneq ($(MT),) - PCLIB := - PCMTLIB := $(LDFLAGS_DYNLIB) -else - PCLIB := $(LDFLAGS_DYNLIB) -endif - - ifneq ($(MT),) PCLIB := PCMTLIB := $(LDFLAGS_DYNLIB) diff --git a/lib/libzstd.mk b/lib/libzstd.mk index a2a965037..d89817f14 100644 --- a/lib/libzstd.mk +++ b/lib/libzstd.mk @@ -206,7 +206,7 @@ endif endif CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) -UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname') +UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname') ifndef BUILD_DIR ifeq ($(UNAME), Darwin) From 2d736d9c50057e6d1f33c175e126590816c54251 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Wed, 5 Jun 2024 19:41:43 +0200 Subject: [PATCH 042/405] Fix new typos found by codespell --- doc/zstd_manual.html | 2 +- lib/compress/zstd_lazy.c | 6 +++--- lib/zstd.h | 2 +- tests/zstreamtest.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index bc4a24036..56bfbcd81 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -298,7 +298,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */ * Special: value 0 means "use default strategy". */ ZSTD_c_targetCBlockSize=130, /* v1.5.6+ - * Attempts to fit compressed block size into approximatively targetCBlockSize. + * Attempts to fit compressed block size into approximately targetCBlockSize. * Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX. * Note that it's not a guarantee, just a convergence target (default:0). * No target when targetCBlockSize == 0. diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 9efaf4b25..cfbadf458 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -1123,9 +1123,9 @@ ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 headGr /* The high-level approach of the SIMD row based match finder is as follows: * - Figure out where to insert the new entry: - * - Generate a hash for current input posistion and split it into a one byte of tag and `rowHashLog` bits of index. - * - The hash is salted by a value that changes on every contex reset, so when the same table is used - * we will avoid collisions that would otherwise slow us down by intorducing phantom matches. + * - Generate a hash for current input position and split it into a one byte of tag and `rowHashLog` bits of index. + * - The hash is salted by a value that changes on every context reset, so when the same table is used + * we will avoid collisions that would otherwise slow us down by introducing phantom matches. * - The hashTable is effectively split into groups or "rows" of 15 or 31 entries of U32, and the index determines * which row to insert into. * - Determine the correct position within the row to insert the entry into. Each row of 15 or 31 can diff --git a/lib/zstd.h b/lib/zstd.h index ce2b1c7de..3a88c74d1 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -395,7 +395,7 @@ typedef enum { * Special: value 0 means "use default strategy". */ ZSTD_c_targetCBlockSize=130, /* v1.5.6+ - * Attempts to fit compressed block size into approximatively targetCBlockSize. + * Attempts to fit compressed block size into approximately targetCBlockSize. * Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX. * Note that it's not a guarantee, just a convergence target (default:0). * No target when targetCBlockSize == 0. diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index e4110eb21..8625b4a23 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -2478,7 +2478,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : Test single-shot fallback for magicless mode: ", testNb++); { - // Aquire resources + // Acquire resources size_t const srcSize = COMPRESSIBLE_NOISE_LENGTH; void* src = malloc(srcSize); size_t const dstSize = ZSTD_compressBound(srcSize); From 44e83e9180ee326353f98e680a7769d4b76f4c25 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Wed, 19 Jun 2024 21:04:50 +0200 Subject: [PATCH 043/405] Fix typos not found by codespell --- CHANGELOG | 4 ++-- build/cmake/CMakeModules/AddZstdCompilationFlags.cmake | 2 +- lib/common/compiler.h | 2 +- lib/common/portability_macros.h | 2 +- lib/compress/zstd_compress.c | 4 ++-- lib/decompress/zstd_decompress.c | 2 +- lib/decompress/zstd_decompress_block.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 33f43410f..ac44affce 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ api: Promote `ZSTD_c_targetCBlockSize` to Stable API by @felixhandte api: new `ZSTD_d_maxBlockSize` experimental parameter, to reduce streaming decompression memory, by @terrelln perf: improve performance of param `ZSTD_c_targetCBlockSize`, by @Cyan4973 perf: improved compression of arrays of integers at high compression, by @Cyan4973 -lib: reduce binary size with selective built-time exclusion, by @felixhandte +lib: reduce binary size with selective build-time exclusion, by @felixhandte lib: improved huffman speed on small data and linux kernel, by @terrelln lib: accept dictionaries with partial literal tables, by @terrelln lib: fix CCtx size estimation with external sequence producer, by @embg @@ -489,7 +489,7 @@ misc: added /contrib/docker script by @gyscos v1.3.3 (Dec 21, 2017) perf: faster zstd_opt strategy (levels 16-19) -fix : bug #944 : multithreading with shared ditionary and large data, reported by @gsliepen +fix : bug #944 : multithreading with shared dictionary and large data, reported by @gsliepen cli : fix : content size written in header by default cli : fix : improved LZ4 format support, by @felixhandte cli : new : hidden command `-S`, to benchmark multiple files while generating one result per file diff --git a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake index 5f179989b..6f55450c3 100644 --- a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake +++ b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake @@ -57,7 +57,7 @@ macro(ADD_ZSTD_COMPILATION_FLAGS) # Note that zstd source code is compatible with both C++98 and above # and C-gnu90 (c90 + long long + variadic macros ) and above # EnableCompilerFlag("-std=c++11" false true) # Set C++ compilation to c++11 standard - # EnableCompilerFlag("-std=c99" true false) # Set C compiation to c99 standard + # EnableCompilerFlag("-std=c99" true false) # Set C compilation to c99 standard if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND MSVC) # clang-cl normally maps -Wall to -Weverything. EnableCompilerFlag("/clang:-Wall" true true false) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 1371212ef..fdf0dd18a 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -326,7 +326,7 @@ #endif /** - * Helper function to perform a wrapped pointer difference without trigging + * Helper function to perform a wrapped pointer difference without triggering * UBSAN. * * @returns lhs - rhs with wrapping diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index e50314a78..b1d9765fb 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -90,7 +90,7 @@ #endif /** - * Only enable assembly for GNUC compatible compilers, + * Only enable assembly for GNU C compatible compilers, * because other platforms may not support GAS assembly syntax. * * Only enable assembly for Linux / MacOS, other platforms may diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9284e2a48..18f929bbe 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2606,7 +2606,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa /* Protect special index values < ZSTD_WINDOW_START_INDEX. */ U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX; assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */ - assert(size < (1U<<31)); /* can be casted to int */ + assert(size < (1U<<31)); /* can be cast to int */ #if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the table reuse logic is sound, and that we don't @@ -5622,7 +5622,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict) * workspaceSize: Use ZSTD_estimateCDictSize() * to determine how large workspace must be. * cParams : use ZSTD_getCParams() to transform a compression level - * into its relevants cParams. + * into its relevant cParams. * @return : pointer to ZSTD_CDict*, or NULL if error (size too small) * Note : there is no corresponding "free" function. * Since workspace was allocated externally, it must be freed externally. diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 2f03cf7b0..26c9457fb 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -811,7 +811,7 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) /** ZSTD_decompressBound() : * compatible with legacy mode - * `src` must point to the start of a ZSTD frame or a skippeable frame + * `src` must point to the start of a ZSTD frame or a skippable frame * `srcSize` must be at least as large as the frame contained * @return : the maximum decompressed size of the compressed source */ diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 76d7332e8..f865692f5 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -358,7 +358,7 @@ size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx, * - start from default distributions, present in /lib/common/zstd_internal.h * - generate tables normally, using ZSTD_buildFSETable() * - printout the content of tables - * - pretify output, report below, test with fuzzer to ensure it's correct */ + * - prettify output, report below, test with fuzzer to ensure it's correct */ /* Default FSE distribution table for Literal Lengths */ static const ZSTD_seqSymbol LL_defaultDTable[(1< Date: Thu, 20 Jun 2024 15:19:58 -0400 Subject: [PATCH 044/405] Throw error if Huffman weight initial states are truncated --- doc/decompressor_permissive.md | 20 ++++++++++++++++++ doc/zstd_compression_format.md | 4 ++++ lib/common/fse_decompress.c | 2 ++ .../truncated_huff_state.zst | Bin 0 -> 19 bytes 4 files changed, 26 insertions(+) create mode 100644 tests/golden-decompression-errors/truncated_huff_state.zst diff --git a/doc/decompressor_permissive.md b/doc/decompressor_permissive.md index bd77165f0..164d6c86d 100644 --- a/doc/decompressor_permissive.md +++ b/doc/decompressor_permissive.md @@ -18,6 +18,26 @@ This document lists a few known cases where invalid data was formerly accepted by the decoder, and what has changed since. +Truncated Huffman states +------------------------ + +**Last affected version**: v1.5.6 + +**Produced by the reference compressor**: No + +**Example Frame**: `28b5 2ffd 0000 5500 0072 8001 0420 7e1f 02aa 00` + +When using FSE-compressed Huffman weights, the compressed weight bitstream +could contain fewer bits than necessary to decode the initial states. + +The reference decompressor up to v1.5.6 will decode truncated or missing +initial states as zero, which can result in a valid Huffman tree if only +the second state is truncated. + +In newer versions, truncated initial states are reported as a corruption +error by the decoder. + + Offset == 0 ----------- diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index 5cae85524..fb0090f9a 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -1362,6 +1362,10 @@ symbols for each of the final states are decoded and the process is complete. If this process would produce more weights than the maximum number of decoded weights (255), then the data is considered corrupted. +If either of the 2 initial states are absent or truncated, then the data is +considered corrupted. Consequently, it is not possible to encode fewer than +2 weights using this mode. + #### Conversion from weights to Huffman prefix codes All present symbols shall now have a `Weight` value. diff --git a/lib/common/fse_decompress.c b/lib/common/fse_decompress.c index 0dcc4640d..c8f1bb0cf 100644 --- a/lib/common/fse_decompress.c +++ b/lib/common/fse_decompress.c @@ -190,6 +190,8 @@ FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic( FSE_initDState(&state1, &bitD, dt); FSE_initDState(&state2, &bitD, dt); + RETURN_ERROR_IF(BIT_reloadDStream(&bitD)==BIT_DStream_overflow, corruption_detected, ""); + #define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) /* 4 symbols per loop */ diff --git a/tests/golden-decompression-errors/truncated_huff_state.zst b/tests/golden-decompression-errors/truncated_huff_state.zst new file mode 100644 index 0000000000000000000000000000000000000000..2ce18c0b7a9d14af8d167d7118b8560a5e90efaa GIT binary patch literal 19 acmdPcs{faPA(VlksDY71p-!G@6$1b@DFnX& literal 0 HcmV?d00001 From 345bcb5ff7001fbe2dfd59974808170c9e0f4d5d Mon Sep 17 00:00:00 2001 From: Adenilson Cavalcanti Date: Tue, 18 Jun 2024 17:20:35 -0700 Subject: [PATCH 045/405] [zstd][dict] Ensure that dictionary training functions are fully reentrant The two main functions used for dictionary training using the COVER algorithm require initialization of a COVER_ctx_t where a call to qsort() is performed. The issue is that the standard C99 qsort() function doesn't offer a way to pass an extra parameter for the comparison function callback (e.g. a pointer to a context) and currently zstd relies on a *global* static variable to hold a pointer to a context needed to perform the sort operation. If a zstd library user invokes either ZDICT_trainFromBuffer_cover or ZDICT_optimizeTrainFromBuffer_cover from multiple threads, the global context may be overwritten before/during the call/execution to qsort() in the initialization of the COVER_ctx_t, thus yielding to crashes and other bad things (Tm) as reported on issue #4045. Enters qsort_r(): it was designed to address precisely this situation, to quote from the documention [1]: "the comparison function does not need to use global variables to pass through arbitrary arguments, and is therefore reentrant and safe to use in threads." It is available with small variations for multiple OSes (GNU, BSD[2], Windows[3]), and the ISO C11 [4] standard features on annex B-21 qsort_s() as part of the . Let's hope that compilers eventually catch up with it. For now, we have to handle the small variations in function parameters for each platform. The current fix solves the problem by allowing each executing thread pass its own COVER_ctx_t instance to qsort_r(), removing the use of a global pointer and allowing the code to be reentrant. Unfortunately for *BSD, we cannot leverage qsort_r() given that its API has changed on newer versions of FreeBSD (14.0) and the other BSD variants (e.g. NetBSD, OpenBSD) don't implement it. For such cases we provide a fallback that will work only requiring support for compilers implementing support for C90. [1] https://man7.org/linux/man-pages/man3/qsort_r.3.html [2] https://man.freebsd.org/cgi/man.cgi?query=qsort_r [3] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 [4] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf --- lib/common/zstd_deps.h | 12 +++++++ lib/dictBuilder/cover.c | 79 +++++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/lib/common/zstd_deps.h b/lib/common/zstd_deps.h index 4d767ae9b..f41a973c3 100644 --- a/lib/common/zstd_deps.h +++ b/lib/common/zstd_deps.h @@ -24,6 +24,18 @@ #ifndef ZSTD_DEPS_COMMON #define ZSTD_DEPS_COMMON +/* Even though we use qsort_r only for the dictionary builder, the macro + * _GNU_SOURCE has to be declared *before* the inclusion of any standard + * header and the script 'combine.sh' combines the whole zstd source code + * in a single file. + */ +#if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \ + defined(__CYGWIN__) || defined(__MSYS__) +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif +#endif + #include #include #include diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index 44f9029ac..386a4d572 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -21,8 +21,17 @@ /*-************************************* * Dependencies ***************************************/ +/* qsort_r is an extension. */ +#if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \ + defined(__CYGWIN__) || defined(__MSYS__) +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif +#endif + #include /* fprintf */ -#include /* malloc, free, qsort */ +#include /* malloc, free, qsort_r */ + #include /* memset */ #include /* clock */ @@ -232,8 +241,10 @@ typedef struct { unsigned d; } COVER_ctx_t; -/* We need a global context for qsort... */ +#if !defined(_GNU_SOURCE) && !defined(__APPLE__) && !defined(_MSC_VER) +/* C90 only offers qsort() that needs a global context. */ static COVER_ctx_t *g_coverCtx = NULL; +#endif /*-************************************* * Helper functions @@ -276,11 +287,15 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) { /** * Same as COVER_cmp() except ties are broken by pointer value - * NOTE: g_coverCtx must be set to call this function. A global is required because - * qsort doesn't take an opaque pointer. */ -static int WIN_CDECL COVER_strict_cmp(const void *lp, const void *rp) { - int result = COVER_cmp(g_coverCtx, lp, rp); +#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__) +static int WIN_CDECL COVER_strict_cmp(void* g_coverCtx, const void* lp, const void* rp) { +#elif defined(_GNU_SOURCE) +static int COVER_strict_cmp(const void *lp, const void *rp, void *g_coverCtx) { +#else /* C90 fallback.*/ +static int COVER_strict_cmp(const void *lp, const void *rp) { +#endif + int result = COVER_cmp((COVER_ctx_t*)g_coverCtx, lp, rp); if (result == 0) { result = lp < rp ? -1 : 1; } @@ -289,14 +304,50 @@ static int WIN_CDECL COVER_strict_cmp(const void *lp, const void *rp) { /** * Faster version for d <= 8. */ -static int WIN_CDECL COVER_strict_cmp8(const void *lp, const void *rp) { - int result = COVER_cmp8(g_coverCtx, lp, rp); +#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__) +static int WIN_CDECL COVER_strict_cmp8(void* g_coverCtx, const void* lp, const void* rp) { +#elif defined(_GNU_SOURCE) +static int COVER_strict_cmp8(const void *lp, const void *rp, void *g_coverCtx) { +#else /* C90 fallback.*/ +static int COVER_strict_cmp8(const void *lp, const void *rp) { +#endif + int result = COVER_cmp8((COVER_ctx_t*)g_coverCtx, lp, rp); if (result == 0) { result = lp < rp ? -1 : 1; } return result; } +/** + * Abstract away divergence of qsort_r() parameters. + * Hopefully when C11 become the norm, we will be able + * to clean it up. + */ +static void stableSort(COVER_ctx_t *ctx) { +#if defined(__APPLE__) + qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32), + ctx, + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); +#elif defined(_GNU_SOURCE) + qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp), + ctx); +#elif defined(_WIN32) && defined(_MSC_VER) + qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp), + ctx); +#elif defined(__OpenBSD__) + g_coverCtx = ctx; + mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); +#else /* C90 fallback.*/ + g_coverCtx = ctx; + /* TODO(cavalcanti): implement a reentrant qsort() when is not available. */ + qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); +#endif +} + /** * Returns the first pointer in [first, last) whose element does not compare * less than value. If no such element exists it returns last. @@ -620,17 +671,7 @@ static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer, for (i = 0; i < ctx->suffixSize; ++i) { ctx->suffix[i] = i; } - /* qsort doesn't take an opaque pointer, so pass as a global. - * On OpenBSD qsort() is not guaranteed to be stable, their mergesort() is. - */ - g_coverCtx = ctx; -#if defined(__OpenBSD__) - mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32), - (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); -#else - qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), - (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); -#endif + stableSort(ctx); } DISPLAYLEVEL(2, "Computing frequencies\n"); /* For each dmer group (group of positions with the same first d bytes): From 1f72f52bc1efd943f390a3dec3b569cf49f7a83a Mon Sep 17 00:00:00 2001 From: Joseph Lee Date: Wed, 3 Jul 2024 12:26:15 +0900 Subject: [PATCH 046/405] gen_html: Fix build error in windows --- contrib/gen_html/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gen_html/Makefile b/contrib/gen_html/Makefile index 26e870399..f93669e02 100644 --- a/contrib/gen_html/Makefile +++ b/contrib/gen_html/Makefile @@ -40,7 +40,7 @@ gen_html: gen_html.cpp $(ZSTDMANUAL): gen_html $(ZSTDAPI) echo "Update zstd manual in /doc" - ./gen_html $(LIBVER) $(ZSTDAPI) $(ZSTDMANUAL) + ./gen_html$(EXT) $(LIBVER) $(ZSTDAPI) $(ZSTDMANUAL) .PHONY: manual manual: gen_html $(ZSTDMANUAL) From b320d096a44b592d5f5bcda37e323b799c0cef57 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Sun, 7 Jul 2024 19:43:49 +0200 Subject: [PATCH 047/405] clarify when to use '--single-thread' with '--patch-from' Using '--single-thread' with '--patch-from' on compression levels above 15 will lead to significantly worse compression ratios. Corrected the man page not suggest anymore to do this. --- programs/zstd.1.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index fcbfb4573..5188be6a5 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -174,8 +174,10 @@ the last one takes effect. (_fileLog_ being the _windowLog_ required to cover the whole file). You can also manually force it. - Note: for all levels, you can use `--patch-from` in `--single-thread` mode - to improve compression ratio at the cost of speed. + Note: up to level 15, you can use `--patch-from` in `--single-thread` mode + to improve compression ratio marginally at the cost of speed. Using + '--single-thread' above level 15 will lead to lower compression + ratios. Note: for level 19, you can get increased compression ratio at the cost of speed by specifying `--zstd=targetLength=` to be something large From 5d63f186cce4bb21fde156492fe945f2ae69104c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sat, 13 Jul 2024 13:53:53 +0200 Subject: [PATCH 048/405] lib/libzstd.mk: fix typo in the definition of LIB_BINDIR Commit f4dbfce79cb2b82fb496fcd2518ecd3315051b7d ("define LIB_SRCDIR and LIB_BINDIR") significantly reworked the build logic, but in its introduction of LIB_BINDIR a typo was made. It was introduced as such: +LIB_SRCDIR ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +LIB_BINDIR ?= $(LIBSRC_DIR) But the definition of LIB_BINDIR has a typo: it should use $(LIB_SRCDIR) not $(LIBSRC_DIR). Due to this, $(LIB_BINDIR) is empty, therefore in programs/Makefile, -L$(LIB_BINDIR) is expanded to just -L, and consequently when trying to link the "zstd" binary with the libzstd library, it cannot find it: host/lib/gcc/powerpc64-buildroot-linux-gnu/13.3.0/../../../../powerpc64-buildroot-linux-gnu/bin/ld: cannot find -lzstd: No such file or directory This commit fixes the build by fixing this typo. Signed-off-by: Thomas Petazzoni --- lib/libzstd.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libzstd.mk b/lib/libzstd.mk index d89817f14..91bd4caf3 100644 --- a/lib/libzstd.mk +++ b/lib/libzstd.mk @@ -22,7 +22,7 @@ LIBZSTD_MK_INCLUDED := 1 # By default, library's directory is same as this included makefile LIB_SRCDIR ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -LIB_BINDIR ?= $(LIBSRC_DIR) +LIB_BINDIR ?= $(LIB_SRCDIR) # ZSTD_LIB_MINIFY is a helper variable that # configures a bunch of other variables to space-optimized defaults. From 0986e1e630c0a4286ea07516bde3e6571c22274d Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 26 Jul 2024 09:45:06 +0200 Subject: [PATCH 049/405] Add Conan to readme Signed-off-by: Uilian Ries --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 54dfd4065..d91ef5df1 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,17 @@ You can build and install zstd [vcpkg](https://github.com/Microsoft/vcpkg/) depe The zstd port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. +### Conan + +You can install pre-built binaries for zstd or build it from source using [Conan](https://conan.io/). Use the following command: + +```bash +conan install --requires="zstd/[*]" --build=missing +``` + +The zstd Conan recipe is kept up to date by Conan maintainers and community contributors. +If the version is out of date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the ConanCenterIndex repository. + ### Visual Studio (Windows) Going into `build` directory, you will find additional possibilities: From 1f5df587fa3edbbf2faf24ef2f0941652663305f Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Fri, 26 Jul 2024 09:47:16 +0200 Subject: [PATCH 050/405] tests/decodecorpus: add more advanced options - add option to force a specific block type - add option to force a specific literal tyle - add option to generate only frame headers - add option to skip generating magic numbers Co-authored-by: Maciej Dudek Co-authored-by: Pawel Czarnecki Co-authored-by: Robert Winkler Co-authored-by: Roman Dobrodii --- tests/decodecorpus.c | 78 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index 1abc7df8b..f25e5dc7c 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -247,6 +247,12 @@ typedef enum { #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif +typedef enum { + lt_raw, + lt_rle, + lt_compressed, +} literalType_e; + /*-******************************************************* * Global variables (set from command line) *********************************************************/ @@ -259,7 +265,11 @@ U32 g_maxBlockSize = ZSTD_BLOCKSIZE_MAX; /* <= 128 KB */ struct { int contentSize; /* force the content size to be present */ -} opts; /* advanced options on generation */ + blockType_e *blockType; /* force specific block type */ + literalType_e *literalType; /* force specific literals type */ + int frame_header_only; /* generate only frame header */ + int no_magic; /* do not generate magic number */ +} opts; /* Generate and write a random frame header */ static void writeFrameHeader(U32* seed, frame_t* frame, dictInfo info) @@ -288,10 +298,19 @@ static void writeFrameHeader(U32* seed, frame_t* frame, dictInfo info) { /* Generate random content size */ + int force_block_type = opts.blockType != NULL; size_t highBit; if (RAND(seed) & 7 && g_maxDecompressedSizeLog > 7) { /* do content of at least 128 bytes */ highBit = 1ULL << RAND_range(seed, 7, g_maxDecompressedSizeLog); + } else if (force_block_type) { + if ((RAND(seed) & 3) || (*(opts.blockType) == bt_rle)) { + /* do small content */ + highBit = 1ULL << RAND_range(seed, 0, MIN(7, 1U << g_maxDecompressedSizeLog)); + } else { + /* 0 size frame */ + highBit = 0; + } } else if (RAND(seed) & 3) { /* do small content */ highBit = 1ULL << RAND_range(seed, 0, MIN(7, 1U << g_maxDecompressedSizeLog)); @@ -324,8 +343,10 @@ static void writeFrameHeader(U32* seed, frame_t* frame, dictInfo info) } /* write out the header */ - MEM_writeLE32(op + pos, ZSTD_MAGICNUMBER); - pos += 4; + if (!opts.no_magic) { + MEM_writeLE32(op + pos, ZSTD_MAGICNUMBER); + pos += 4; + } { /* @@ -370,8 +391,10 @@ static void writeFrameHeader(U32* seed, frame_t* frame, dictInfo info) /* Write a literal block in either raw or RLE form, return the literals size */ static size_t writeLiteralsBlockSimple(U32* seed, frame_t* frame, size_t contentSize) { + int force_literal_type = opts.literalType != NULL; + int const type = (force_literal_type) ? *(opts.literalType) : RAND(seed) % 2; + BYTE* op = (BYTE*)frame->data; - int const type = RAND(seed) % 2; int const sizeFormatDesc = RAND(seed) % 8; size_t litSize; size_t maxLitSize = MIN(contentSize, g_maxBlockSize); @@ -619,8 +642,15 @@ static size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t con static size_t writeLiteralsBlock(U32* seed, frame_t* frame, size_t contentSize) { - /* only do compressed for larger segments to avoid compressibility issues */ - if (RAND(seed) & 7 && contentSize >= 64) { + int select_compressed = 0; + if (opts.literalType) { + select_compressed = *(opts.literalType) == lt_compressed; + } else { + /* only do compressed for larger segments to avoid compressibility issues */ + select_compressed = RAND(seed) & 7 && contentSize >= 64; + } + + if (select_compressed) { return writeLiteralsBlockCompressed(seed, frame, contentSize); } else { return writeLiteralsBlockSimple(seed, frame, contentSize); @@ -1034,7 +1064,8 @@ static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize static void writeBlock(U32* seed, frame_t* frame, size_t contentSize, int lastBlock, dictInfo info) { - int const blockTypeDesc = RAND(seed) % 8; + int force_block_type = opts.blockType != NULL; + int const blockTypeDesc = (force_block_type) ? *(opts.blockType) : RAND(seed) % 8; size_t blockSize; int blockType; @@ -1073,7 +1104,7 @@ static void writeBlock(U32* seed, frame_t* frame, size_t contentSize, frame->data = op; compressedSize = writeCompressedBlock(seed, frame, contentSize, info); - if (compressedSize >= contentSize) { /* compressed block must be strictly smaller than uncompressed one */ + if (compressedSize >= contentSize && !force_block_type) { /* compressed block must be strictly smaller than uncompressed one */ blockType = 0; memcpy(op, frame->src, contentSize); @@ -1244,7 +1275,11 @@ static U32 generateFrame(U32 seed, frame_t* fr, dictInfo info) DISPLAYLEVEL(3, "frame seed: %u\n", (unsigned)seed); initFrame(fr); + writeFrameHeader(&seed, fr, info); + if (opts.frame_header_only) + return seed; + writeBlocks(&seed, fr, info); writeChecksum(fr); @@ -1772,6 +1807,9 @@ static void advancedUsage(const char* programName) DISPLAY( " --max-block-size-log=# : max block size log, must be in range [2, 17]\n"); DISPLAY( " --max-content-size-log=# : max content size log, must be <= 20\n"); DISPLAY( " (this is ignored with gen-blocks)\n"); + DISPLAY( " --block-type=# : force certain block type (raw=0, rle=1, compressed=2)\n"); + DISPLAY( " --frame-header-only : dump only frame header\n"); + DISPLAY( " --no-magic : do not add magic number\n"); } /*! readU32FromChar() : @@ -1893,6 +1931,18 @@ int main(int argc, char** argv) U32 value = readU32FromChar(&argument); g_maxDecompressedSizeLog = MIN(MAX_DECOMPRESSED_SIZE_LOG, value); + } else if (longCommandWArg(&argument, "block-type=")) { + U32 value = readU32FromChar(&argument); + opts.blockType = malloc(sizeof(blockType_e)); + *(opts.blockType) = value; + } else if (longCommandWArg(&argument, "literal-type=")) { + U32 value = readU32FromChar(&argument); + opts.literalType = malloc(sizeof(literalType_e)); + *(opts.literalType) = value; + } else if (strcmp(argument, "frame-header-only") == 0) { + opts.frame_header_only = 1; + } else if (strcmp(argument, "no-magic") == 0) { + opts.no_magic = 1; } else { advancedUsage(argv[0]); return 1; @@ -1904,6 +1954,18 @@ int main(int argc, char** argv) return 1; } } } } /* for (argNb=1; argNb Date: Mon, 29 Jul 2024 05:34:32 +0000 Subject: [PATCH 051/405] Bump ossf/scorecard-action from 2.3.1 to 2.4.0 Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.1 to 2.4.0. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/0864cf19026789058feabb7e87baa5f140aac736...62b2cac7ed8198b15735ed49ab1e5cf35480ba46) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index e117798ea..9ded4f1cd 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -32,7 +32,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # tag=v2.3.1 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # tag=v2.4.0 with: results_file: results.sarif results_format: sarif From 46a3135524b1ea9cd46ea5cd61529f1231606465 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 05:34:42 +0000 Subject: [PATCH 052/405] Bump msys2/setup-msys2 from 2.23.0 to 2.24.0 Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.23.0 to 2.24.0. - [Release notes](https://github.com/msys2/setup-msys2/releases) - [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md) - [Commits](https://github.com/msys2/setup-msys2/compare/d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8...5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2) --- updated-dependencies: - dependency-name: msys2/setup-msys2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dev-long-tests.yml | 2 +- .github/workflows/dev-short-tests.yml | 2 +- .github/workflows/windows-artifacts.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index 82e893cb9..ba43be3cb 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -247,7 +247,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # tag=v2.23.0 + - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # tag=v2.24.0 with: msystem: MINGW64 install: make diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 0269e8369..524e5929c 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -499,7 +499,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # tag=v2.23.0 + - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # tag=v2.24.0 with: msystem: ${{ matrix.msystem }} install: make diffutils diff --git a/.github/workflows/windows-artifacts.yml b/.github/workflows/windows-artifacts.yml index 761b6c854..92df8589b 100644 --- a/.github/workflows/windows-artifacts.yml +++ b/.github/workflows/windows-artifacts.yml @@ -24,7 +24,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3 - - uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # tag=v2.23.0 + - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # tag=v2.24.0 with: msystem: ${{ matrix.msystem }} install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc From c3c28c4d5a28bca93c97c4ce447f3c8ece42791d Mon Sep 17 00:00:00 2001 From: Adenilson Cavalcanti Date: Mon, 29 Jul 2024 16:37:41 -0700 Subject: [PATCH 053/405] [zstd][android] Fix build with NDK r27 The NDK cross compiler declares the target as __linux (which is not technically incorrect), which triggers the enablement of _GNU_SOURCE in the newly added code that requires the presence of qsort_r() used in the COVER dictionary code. Even though the NDK uses llvm/libc, it doesn't declare qsort_r() in the stdlib.h header. The build fix is to only activate the _GNU_SOURCE macro if the OS is *not* Android, as then we will fallback to the C90 compliant code. This patch should solve the reported issue number #4103. --- lib/common/zstd_deps.h | 2 +- lib/dictBuilder/cover.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common/zstd_deps.h b/lib/common/zstd_deps.h index f41a973c3..8a9c7cc53 100644 --- a/lib/common/zstd_deps.h +++ b/lib/common/zstd_deps.h @@ -31,7 +31,7 @@ */ #if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \ defined(__CYGWIN__) || defined(__MSYS__) -#if !defined(_GNU_SOURCE) +#if !defined(_GNU_SOURCE) && !defined(__ANDROID__) /* NDK doesn't ship qsort_r(). */ #define _GNU_SOURCE #endif #endif diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index 386a4d572..2ef33c73e 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -24,7 +24,7 @@ /* qsort_r is an extension. */ #if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \ defined(__CYGWIN__) || defined(__MSYS__) -#if !defined(_GNU_SOURCE) +#if !defined(_GNU_SOURCE) && !defined(__ANDROID__) /* NDK doesn't ship qsort_r(). */ #define _GNU_SOURCE #endif #endif From cb784edf5de07940c0f48bae6cf8c4b2f4993705 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 30 Jul 2024 11:02:16 -0700 Subject: [PATCH 054/405] added android-ndk-build --- .github/workflows/android-ndk-build.yml | 37 +++++++++++++++++++++++++ lib/compress/zstd_compress_internal.h | 4 +-- lib/compress/zstd_cwksp.h | 5 ++-- 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/android-ndk-build.yml diff --git a/.github/workflows/android-ndk-build.yml b/.github/workflows/android-ndk-build.yml new file mode 100644 index 000000000..53b0fc978 --- /dev/null +++ b/.github/workflows/android-ndk-build.yml @@ -0,0 +1,37 @@ +name: Android NDK Build + +on: + pull_request: + branches: [ dev, release, actionsTest ] + push: + branches: [ actionsTest, '*ndk*' ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Install Android NDK + run: | + sdkmanager --install "ndk;27.0.12077973" + echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/27.0.12077973" >> $GITHUB_ENV + + - name: Build with NDK + run: | + export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + make CC=aarch64-linux-android21-clang \ + AR=llvm-ar \ + RANLIB=llvm-ranlib \ + STRIP=llvm-strip + diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index f8ec1c82e..ba1450852 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1246,8 +1246,8 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { MEM_STATIC ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_window_update(ZSTD_window_t* window, - void const* src, size_t srcSize, - int forceNonContiguous) + const void* src, size_t srcSize, + int forceNonContiguous) { BYTE const* const ip = (BYTE const*)src; U32 contiguous = 1; diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 3eddbd334..dcd485cb5 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -287,7 +287,7 @@ ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) { void* const alloc = (BYTE*)ws->allocStart - bytes; void* const bottom = ws->tableEnd; - DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining", + DEBUGLOG(5, "cwksp: reserving [0x%p]:%zd bytes; %zd bytes remaining", alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); ZSTD_cwksp_assert_internal_consistency(ws); assert(alloc >= bottom); @@ -577,7 +577,8 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { * Invalidates table allocations. * All other allocations remain valid. */ -MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { +MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) +{ DEBUGLOG(4, "cwksp: clearing tables!"); #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) From 688a815c8643c8ea2475ac90bdd261bbcc43631b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 05:17:43 +0000 Subject: [PATCH 055/405] Bump msys2/setup-msys2 from 2.24.0 to 2.24.1 Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.24.0 to 2.24.1. - [Release notes](https://github.com/msys2/setup-msys2/releases) - [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md) - [Commits](https://github.com/msys2/setup-msys2/compare/5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2...ddf331adaebd714795f1042345e6ca57bd66cea8) --- updated-dependencies: - dependency-name: msys2/setup-msys2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dev-long-tests.yml | 2 +- .github/workflows/dev-short-tests.yml | 2 +- .github/workflows/windows-artifacts.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index ba43be3cb..d9f074369 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -247,7 +247,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # tag=v2.24.0 + - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # tag=v2.24.1 with: msystem: MINGW64 install: make diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 524e5929c..7713a897c 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -499,7 +499,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # tag=v2.24.0 + - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # tag=v2.24.1 with: msystem: ${{ matrix.msystem }} install: make diffutils diff --git a/.github/workflows/windows-artifacts.yml b/.github/workflows/windows-artifacts.yml index 92df8589b..ff81b504a 100644 --- a/.github/workflows/windows-artifacts.yml +++ b/.github/workflows/windows-artifacts.yml @@ -24,7 +24,7 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3 - - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # tag=v2.24.0 + - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # tag=v2.24.1 with: msystem: ${{ matrix.msystem }} install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc From 89451cafbd92a350b4a924d0020efbc775054378 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 6 Aug 2024 11:44:37 -0700 Subject: [PATCH 056/405] formatString_u() can display numbers > 100 fixes #4110 --- programs/benchzstd.c | 63 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 29ee595c1..075640e82 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -139,52 +139,61 @@ static const size_t maxMemory = (sizeof(size_t) == 4) return r; \ } -/* replacement for snprintf(), which is not supported by C89 - * sprintf() would be the supported one, but it's labelled unsafe, - * so some modern static analyzer will flag it as such, making it unusable. - * formatString_u() replaces snprintf() for the specific case where there are only %u arguments */ +static size_t uintSize(unsigned value) +{ + size_t size = 1; + while (value >= 10) { + size++; + value /= 10; + } + return size; +} + +// Note: presume @buffer is large enough +static void writeUint_varLen(char* buffer, size_t capacity, unsigned value) +{ + int endPos = (int)uintSize(value) - 1; + assert(uintSize(value) >= 1); + assert(uintSize(value) < capacity); (void)capacity; + while (endPos >= 0) { + char c = '0' + (char)(value % 10); + buffer[endPos--] = c; + value /= 10; + } +} + +/* replacement for snprintf(), which is not supported by C89. + * sprintf() would be the supported one, but it's labelled unsafe: + * modern static analyzer will flag sprintf() as dangerous, making it unusable. + * formatString_u() replaces snprintf() for the specific case where there is only one %u argument */ static int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value) { + size_t const valueSize = uintSize(value); size_t written = 0; int i; - assert(value <= 100); - for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; ++i) { + for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; i++) { if (formatString[i] != '%') { buffer[written++] = formatString[i]; continue; } - if (formatString[++i] == 'u') { - /* Handle single digit */ - if (value < 10) { - buffer[written++] = '0' + (char)value; - } else if (value < 100) { - /* Handle two digits */ - if (written >= buffer_size - 2) { - return -1; /* buffer overflow */ - } - buffer[written++] = '0' + (char)(value / 10); - buffer[written++] = '0' + (char)(value % 10); - } else { /* 100 */ - if (written >= buffer_size - 3) { - return -1; /* buffer overflow */ - } - buffer[written++] = '1'; - buffer[written++] = '0'; - buffer[written++] = '0'; - } + i++; + if (formatString[i] == 'u') { + if (written + valueSize >= buffer_size) abort(); /* buffer not large enough */ + writeUint_varLen(buffer + written, buffer_size - written, value); + written += valueSize; } else if (formatString[i] == '%') { /* Check for escaped percent sign */ buffer[written++] = '%'; } else { - return -1; /* unsupported format */ + abort(); /* unsupported format */ } } if (written < buffer_size) { buffer[written] = '\0'; } else { - buffer[0] = '\0'; /* Handle truncation */ + abort(); /* buffer not large enough */ } return (int)written; From 14b8d398fd0f9155203031239748537e7df2ad75 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 6 Aug 2024 12:47:30 -0700 Subject: [PATCH 057/405] fix c90 comment style --- programs/benchzstd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 075640e82..272af5924 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -149,7 +149,7 @@ static size_t uintSize(unsigned value) return size; } -// Note: presume @buffer is large enough +/* Note: presume @buffer is large enough */ static void writeUint_varLen(char* buffer, size_t capacity, unsigned value) { int endPos = (int)uintSize(value) - 1; From 6dbd49bcd04c42b0b4893d824b856563ae901b33 Mon Sep 17 00:00:00 2001 From: Adenilson Cavalcanti Date: Tue, 6 Aug 2024 16:55:32 -0700 Subject: [PATCH 058/405] [riscv] Enable support for weak symbols Both gcc and clang support weak symbols on RISC-V, therefore let's enable it. This should fix issue #4069. --- lib/common/zstd_trace.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h index da20534eb..173d63fb1 100644 --- a/lib/common/zstd_trace.h +++ b/lib/common/zstd_trace.h @@ -21,13 +21,14 @@ extern "C" { * For now, enable conservatively: * - Only GNUC * - Only ELF - * - Only x86-64, i386 and aarch64 + * - Only x86-64, i386, aarch64 and risc-v. * Also, explicitly disable on platforms known not to work so they aren't * forgotten in the future. */ #if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && \ defined(__GNUC__) && defined(__ELF__) && \ - (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) || defined(__aarch64__)) && \ + (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \ + defined(_M_IX86) || defined(__aarch64__) || defined(__riscv)) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \ !defined(__CYGWIN__) && !defined(_AIX) # define ZSTD_HAVE_WEAK_SYMBOLS 1 From a40bad8ec06aeb992e8d8e58648a4024261b2a54 Mon Sep 17 00:00:00 2001 From: Adenilson Cavalcanti Date: Tue, 6 Aug 2024 17:16:28 -0700 Subject: [PATCH 059/405] [zstd][leak] Avoid memory leak on early return of ZSTD_generateSequence Sanity checks on a few of the context parameters (i.e. workers and block size) may prompt an early return on ZSTD_generateSequences. Allocating the destination buffer past those return points avoids a potential memory leak. This patch should fix issue #4112. --- lib/compress/zstd_compress.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 18f929bbe..aad25049d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3458,7 +3458,7 @@ size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, size_t outSeqsSize, const void* src, size_t srcSize) { const size_t dstCapacity = ZSTD_compressBound(srcSize); - void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem); + void* dst; /* Make C90 happy. */ SeqCollector seqCollector; { int targetCBlockSize; @@ -3471,6 +3471,7 @@ size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, "nbWorkers != 0"); } + dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem); RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!"); seqCollector.collectSequences = 1; From bf4a43fcd45aea991d273160262a31925ea31ba3 Mon Sep 17 00:00:00 2001 From: Xionghu Luo Date: Thu, 8 Aug 2024 15:13:27 +0800 Subject: [PATCH 060/405] Fix zstd-pgo run error The -Werror=missing-profile caused thread/zlib/lzma/lz4 detection failure when build with profile-use, thus caused ZSTD_MULTITHREAD etc. is not defined for profile-use, then there will be many profile mismatch information in output and the final binary reports run error sometimes as below: Error : ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers) failed : Unsupported parameter Signed-off-by: Xionghu Luo --- programs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/Makefile b/programs/Makefile index e1a30fc2b..4d32e0fa8 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -232,7 +232,7 @@ zstd-dll : zstd .PHONY: zstd-pgo zstd-pgo : LLVM_PROFDATA?=llvm-profdata zstd-pgo : PROF_GENERATE_FLAGS=-fprofile-generate $(if $(findstring gcc,$(CC)),-fprofile-dir=.) -zstd-pgo : PROF_USE_FLAGS=-fprofile-use $(if $(findstring gcc,$(CC)),-fprofile-dir=. -Werror=missing-profile -Wno-error=coverage-mismatch) +zstd-pgo : PROF_USE_FLAGS=-fprofile-use $(if $(findstring gcc,$(CC)),-fprofile-dir=. -Wno-error=missing-profile -Wno-error=coverage-mismatch) zstd-pgo : $(MAKE) clean HASH_DIR=$(HASH_DIR) $(MAKE) zstd HASH_DIR=$(HASH_DIR) MOREFLAGS="$(PROF_GENERATE_FLAGS)" From aed3c7540a904b2dbb12fd88038bd09d743ca05d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 05:16:05 +0000 Subject: [PATCH 061/405] Bump actions/setup-java from 3 to 4 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/android-ndk-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android-ndk-build.yml b/.github/workflows/android-ndk-build.yml index 53b0fc978..c77d5f0d1 100644 --- a/.github/workflows/android-ndk-build.yml +++ b/.github/workflows/android-ndk-build.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' From ec0c41414d5d41e6e49b5bd7402a7252ad91e7e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 05:37:33 +0000 Subject: [PATCH 062/405] Bump github/codeql-action from 3.25.1 to 3.26.2 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.1 to 3.26.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/c7f9125735019aa87cfc361530512d50ea439c71...429e1977040da7a23b6822b13c129cd1ba93dbb2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 9ded4f1cd..ccd7956a5 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # tag=v3.25.1 + uses: github/codeql-action/upload-sarif@429e1977040da7a23b6822b13c129cd1ba93dbb2 # tag=v3.26.2 with: sarif_file: results.sarif From 09cb37cbb1be014756fbc00d3c5db8eaec20f32d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 21 Aug 2024 10:53:25 -0700 Subject: [PATCH 063/405] Limit range of operations on Indexes in 32-bit mode and use unsigned type. This reduce risks that an operation produces a negative number when crossing the 2 GB limit. --- lib/compress/zstd_compress_internal.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ba1450852..6c76b5848 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -918,11 +918,12 @@ MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 /*-************************************* * Round buffer management ***************************************/ -#if (ZSTD_WINDOWLOG_MAX_64 > 31) -# error "ZSTD_WINDOWLOG_MAX is too large : would overflow ZSTD_CURRENT_MAX" -#endif -/* Max current allowed */ -#define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)) +/* Max @current value allowed: + * In 32-bit mode: we want to avoid crossing the 2 GB limit, + * reducing risks of side effects in case of signed operations on indexes. + * In 64-bit mode: we want to ensure that adding the maximum job size (512 MB) + * doesn't overflow U32 index capacity (4 GB) */ +#define ZSTD_CURRENT_MAX (MEM_64bits() ? 3500U MB : 2000U MB) /* Maximum chunk size before overflow correction needs to be called again */ #define ZSTD_CHUNKSIZE_MAX \ ( ((U32)-1) /* Maximum ending current index */ \ @@ -1274,8 +1275,9 @@ U32 ZSTD_window_update(ZSTD_window_t* window, /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */ if ( (ip+srcSize > window->dictBase + window->lowLimit) & (ip < window->dictBase + window->dictLimit)) { - ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase; - U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx; + size_t const highInputIdx = (size_t)((ip + srcSize) - window->dictBase); + U32 const lowLimitMax = (highInputIdx > (size_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx; + assert(highInputIdx < UINT_MAX); window->lowLimit = lowLimitMax; DEBUGLOG(5, "Overlapping extDict and input : new lowLimit = %u", window->lowLimit); } From 7a48dc230c42ba4d779fab4e68da14f44c92a7b3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Sep 2024 09:50:30 -0700 Subject: [PATCH 064/405] fix doc nit: ZDICT_DICTSIZE_MIN fix #4142 --- lib/zdict.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zdict.h b/lib/zdict.h index 2268f948a..bcccf750e 100644 --- a/lib/zdict.h +++ b/lib/zdict.h @@ -248,7 +248,7 @@ typedef struct { * is presumed that the most profitable content is at the end of the dictionary, * since that is the cheapest to reference. * - * `maxDictSize` must be >= max(dictContentSize, ZSTD_DICTSIZE_MIN). + * `maxDictSize` must be >= max(dictContentSize, ZDICT_DICTSIZE_MIN). * * @return: size of dictionary stored into `dstDictBuffer` (<= `maxDictSize`), * or an error code, which can be tested by ZDICT_isError(). From e8fce38954efd6bc58a5b0ec72dd26f41c8365e6 Mon Sep 17 00:00:00 2001 From: Ilya Tokar Date: Wed, 18 Sep 2024 17:36:37 -0400 Subject: [PATCH 065/405] Optimize compression by avoiding unpredictable branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid unpredictable branch. Use conditional move to generate the address that is guaranteed to be safe and compare unconditionally. Instead of if (idx < limit && x[idx] == val ) // mispredicted idx < limit branch Do addr = cmov(safe,x+idx) if (*addr == val && idx < limit) // almost always false so well predicted Using microbenchmarks from https://github.com/google/fleetbench, I get about ~10% speed-up: name old cpu/op new cpu/op delta BM_ZSTD_COMPRESS_Fleet/compression_level:-7/window_log:15 1.46ns ± 3% 1.31ns ± 7% -9.88% (p=0.000 n=35+38) BM_ZSTD_COMPRESS_Fleet/compression_level:-7/window_log:16 1.41ns ± 3% 1.28ns ± 3% -9.56% (p=0.000 n=36+39) BM_ZSTD_COMPRESS_Fleet/compression_level:-5/window_log:15 1.61ns ± 1% 1.43ns ± 3% -10.70% (p=0.000 n=30+39) BM_ZSTD_COMPRESS_Fleet/compression_level:-5/window_log:16 1.54ns ± 2% 1.39ns ± 3% -9.21% (p=0.000 n=37+39) BM_ZSTD_COMPRESS_Fleet/compression_level:-3/window_log:15 1.82ns ± 2% 1.61ns ± 3% -11.31% (p=0.000 n=37+40) BM_ZSTD_COMPRESS_Fleet/compression_level:-3/window_log:16 1.73ns ± 3% 1.56ns ± 3% -9.50% (p=0.000 n=38+39) BM_ZSTD_COMPRESS_Fleet/compression_level:-1/window_log:15 2.12ns ± 2% 1.79ns ± 3% -15.55% (p=0.000 n=34+39) BM_ZSTD_COMPRESS_Fleet/compression_level:-1/window_log:16 1.99ns ± 3% 1.72ns ± 3% -13.70% (p=0.000 n=38+38) BM_ZSTD_COMPRESS_Fleet/compression_level:0/window_log:15 3.22ns ± 3% 2.94ns ± 3% -8.67% (p=0.000 n=38+40) BM_ZSTD_COMPRESS_Fleet/compression_level:0/window_log:16 3.19ns ± 4% 2.86ns ± 4% -10.55% (p=0.000 n=40+38) BM_ZSTD_COMPRESS_Fleet/compression_level:1/window_log:15 2.60ns ± 3% 2.22ns ± 3% -14.53% (p=0.000 n=40+39) BM_ZSTD_COMPRESS_Fleet/compression_level:1/window_log:16 2.46ns ± 3% 2.13ns ± 2% -13.67% (p=0.000 n=39+36) BM_ZSTD_COMPRESS_Fleet/compression_level:2/window_log:15 2.69ns ± 3% 2.46ns ± 3% -8.63% (p=0.000 n=37+39) BM_ZSTD_COMPRESS_Fleet/compression_level:2/window_log:16 2.63ns ± 3% 2.36ns ± 3% -10.47% (p=0.000 n=40+40) BM_ZSTD_COMPRESS_Fleet/compression_level:3/window_log:15 3.20ns ± 2% 2.95ns ± 3% -7.94% (p=0.000 n=35+40) BM_ZSTD_COMPRESS_Fleet/compression_level:3/window_log:16 3.20ns ± 4% 2.87ns ± 4% -10.33% (p=0.000 n=40+40) I've also measured the impact on internal workloads and saw similar ~10% improvement in performance, measured by cpu usage/byte of data. --- lib/compress/zstd_compress_internal.h | 17 ++++++++++++ lib/compress/zstd_double_fast.c | 37 +++++++++++++++++---------- lib/compress/zstd_fast.c | 32 ++++++++++++++--------- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ba1450852..cbcded28d 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -557,6 +557,23 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value) return 1; } +/* ZSTD_selectAddr: + * @return a >= b ? trueAddr : falseAddr, + * tries to force branchless codegen. */ +MEM_STATIC const BYTE* ZSTD_selectAddr(U32 a, U32 b, const BYTE* trueAddr, const BYTE* falseAddr) { +#if defined(__GNUC__) && defined(__x86_64__) + __asm__ ( + "cmp %1, %2\n" + "cmova %3, %0\n" + : "+r"(trueAddr) + : "r"(a), "r"(b), "r"(falseAddr) + ); + return trueAddr; +#else + return a >= b ? trueAddr : falseAddr; +#endif +} + /* ZSTD_noCompressBlock() : * Writes uncompressed block to dst buffer from given src. * Returns the size of the block */ diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 1b5f64f20..819658caf 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -140,11 +140,17 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( U32 idxl1; /* the long match index for ip1 */ const BYTE* matchl0; /* the long match for ip */ + const BYTE* matchl0_safe; /* matchl0 or safe address */ const BYTE* matchs0; /* the short match for ip */ const BYTE* matchl1; /* the long match for ip1 */ + const BYTE* matchs0_safe; /* matchs0 or safe address */ const BYTE* ip = istart; /* the current position */ const BYTE* ip1; /* the next position */ + /* Array of ~random data, should have low probability of matching data + * we load from here instead of from tables, if matchl0/matchl1 are + * invalid indices. Used to avoid unpredictable branches. */ + const BYTE dummy[] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0xe2,0xb4}; DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_noDict_generic"); @@ -191,24 +197,29 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( hl1 = ZSTD_hashPtr(ip1, hBitsL, 8); - if (idxl0 > prefixLowestIndex) { - /* check prefix long match */ - if (MEM_read64(matchl0) == MEM_read64(ip)) { - mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8; - offset = (U32)(ip-matchl0); - while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */ - goto _match_found; - } + /* idxl0 > prefixLowestIndex is a (somewhat) unpredictable branch. + * However expression below complies into conditional move. Since + * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex + * if there is a match, all branches become predictable. */ + matchl0_safe = ZSTD_selectAddr(prefixLowestIndex, idxl0, &dummy[0], matchl0); + + /* check prefix long match */ + if (MEM_read64(matchl0_safe) == MEM_read64(ip) && matchl0_safe == matchl0) { + mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8; + offset = (U32)(ip-matchl0); + while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */ + goto _match_found; } idxl1 = hashLong[hl1]; matchl1 = base + idxl1; - if (idxs0 > prefixLowestIndex) { - /* check prefix short match */ - if (MEM_read32(matchs0) == MEM_read32(ip)) { - goto _search_next_long; - } + /* Same optimization as matchl0 above */ + matchs0_safe = ZSTD_selectAddr(prefixLowestIndex, idxs0, &dummy[0], matchs0); + + /* check prefix short match */ + if(MEM_read32(matchs0_safe) == MEM_read32(ip) && matchs0_safe == matchs0) { + goto _search_next_long; } if (ip1 >= nextStep) { diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index c6baa49d4..838a18ee5 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -162,6 +162,11 @@ size_t ZSTD_compressBlock_fast_noDict_generic( const BYTE* const prefixStart = base + prefixStartIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; + /* Array of ~random data, should have low probability of matching data + * we load from here instead of from tables, if the index is invalid. + * Used to avoid unpredictable branches. */ + const BYTE dummy[] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0xe2,0xb4}; + const BYTE *mvalAddr; const BYTE* anchor = istart; const BYTE* ip0 = istart; @@ -246,15 +251,18 @@ _start: /* Requires: ip0 */ goto _match; } + /* idx >= prefixStartIndex is a (somewhat) unpredictable branch. + * However expression below complies into conditional move. Since + * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex + * if there is a match, all branches become predictable. */ + mvalAddr = base + idx; + mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, mvalAddr, &dummy[0]); + /* load match for ip[0] */ - if (idx >= prefixStartIndex) { - mval = MEM_read32(base + idx); - } else { - mval = MEM_read32(ip0) ^ 1; /* guaranteed to not match. */ - } + mval = MEM_read32(mvalAddr); /* check match at ip[0] */ - if (MEM_read32(ip0) == mval) { + if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { /* found a match! */ /* First write next hash table entry; we've already calculated it. @@ -281,15 +289,15 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; + mvalAddr = base + idx; + mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, mvalAddr, &dummy[0]); + /* load match for ip[0] */ - if (idx >= prefixStartIndex) { - mval = MEM_read32(base + idx); - } else { - mval = MEM_read32(ip0) ^ 1; /* guaranteed to not match. */ - } + mval = MEM_read32(mvalAddr); + /* check match at ip[0] */ - if (MEM_read32(ip0) == mval) { + if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { /* found a match! */ /* first write next hash table entry; we've already calculated it */ From a8b544d460f3db9a79d630d95f1fa3564c29be12 Mon Sep 17 00:00:00 2001 From: inventor500 Date: Sat, 31 Aug 2024 07:23:51 -0500 Subject: [PATCH 066/405] Fixed warning when compiling pzstd with CPPFLAGS=-Wunused-result and CXXFLAGS=-std=c++17 --- contrib/pzstd/Options.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/pzstd/Options.cpp b/contrib/pzstd/Options.cpp index a77824edb..43ea2721d 100644 --- a/contrib/pzstd/Options.cpp +++ b/contrib/pzstd/Options.cpp @@ -322,7 +322,7 @@ Options::Status Options::parse(int argc, const char **argv) { g_utilDisplayLevel = verbosity; // Remove local input files that are symbolic links if (!followLinks) { - std::remove_if(localInputFiles.begin(), localInputFiles.end(), + std::ignore = std::remove_if(localInputFiles.begin(), localInputFiles.end(), [&](const char *path) { bool isLink = UTIL_isLink(path); if (isLink && verbosity >= 2) { From 9215de52c7029bdad06d5fa59a4777edf0c92df9 Mon Sep 17 00:00:00 2001 From: inventor500 Date: Wed, 25 Sep 2024 10:21:20 -0500 Subject: [PATCH 067/405] Included suggestion from @neheb --- contrib/pzstd/Options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/pzstd/Options.cpp b/contrib/pzstd/Options.cpp index 43ea2721d..90841b9bb 100644 --- a/contrib/pzstd/Options.cpp +++ b/contrib/pzstd/Options.cpp @@ -322,7 +322,7 @@ Options::Status Options::parse(int argc, const char **argv) { g_utilDisplayLevel = verbosity; // Remove local input files that are symbolic links if (!followLinks) { - std::ignore = std::remove_if(localInputFiles.begin(), localInputFiles.end(), + localInputFiles.erase(std::remove_if(localInputFiles.begin(), localInputFiles.end(), [&](const char *path) { bool isLink = UTIL_isLink(path); if (isLink && verbosity >= 2) { @@ -332,7 +332,7 @@ Options::Status Options::parse(int argc, const char **argv) { path); } return isLink; - }); + }), localInputFiles.end()); } // Translate input files/directories into files to (de)compress From 039f404faa9230e389b360c80d6c842fae3f75a0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 25 Sep 2024 16:56:01 -0700 Subject: [PATCH 068/405] update documentation to specify that Dictionary can be used for benchmark fix #4139 --- programs/zstd.1.md | 4 ++++ programs/zstdcli.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 5188be6a5..d0473fa47 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -674,6 +674,10 @@ Note that the results are highly dependent on the content being compressed. minimum evaluation time, in seconds (default: 3s), benchmark mode only * `-B#`, `--block-size=#`: cut file(s) into independent chunks of size # (default: no chunking) +* `-S`: + output one benchmark result per input file (default: consolidated result) +* `-D dictionary` + benchmark using dictionary * `--priority=rt`: set process priority to real-time (Windows) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 9dd6b051a..d8e908d85 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -32,7 +32,6 @@ #include /* getenv */ #include /* strcmp, strlen */ #include /* fprintf(), stdin, stdout, stderr */ -#include /* errno */ #include /* assert */ #include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ @@ -311,6 +310,7 @@ static void usageAdvanced(const char* programName) DISPLAYOUT(" -i# Set the minimum evaluation to time # seconds. [Default: 3]\n"); DISPLAYOUT(" -B# Cut file into independent chunks of size #. [Default: No chunking]\n"); DISPLAYOUT(" -S Output one benchmark result per input file. [Default: Consolidated result]\n"); + DISPLAYOUT(" -D dictionary Benchmark using dictionary \n"); DISPLAYOUT(" --priority=rt Set process priority to real-time.\n"); #endif From a3b5c4521c954af9b2a2bf2b1df9a4bb70f0c46d Mon Sep 17 00:00:00 2001 From: dearblue Date: Mon, 30 Sep 2024 22:45:17 +0900 Subject: [PATCH 069/405] Update FreeBSD VM image to 14.1 FreeBSD 14.0 will reach the end of life on 2024-09-30. The updated 14.1 is scheduled to end-of-life on 2025-03-31. ref. https://www.freebsd.org/releases/14.2R/schedule/ --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index f68e39ae1..e3617a960 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,7 +2,7 @@ task: name: FreeBSD (shortest) freebsd_instance: matrix: - image_family: freebsd-14-0 + image_family: freebsd-14-1 install_script: pkg install -y gmake coreutils script: | MOREFLAGS="-Werror" gmake -j all From d2d49a11618bd3958b0501942b3525d9431008c1 Mon Sep 17 00:00:00 2001 From: Artem Labazov <123321artyom@gmail.com> Date: Mon, 30 Sep 2024 17:00:42 +0300 Subject: [PATCH 070/405] meson: Do not export private headers in libzstd_dep to avoid name clash This way libzstd_dep does not override, for instance, --- build/meson/lib/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/meson/lib/meson.build b/build/meson/lib/meson.build index 68db2ca6c..6c5d53d1a 100644 --- a/build/meson/lib/meson.build +++ b/build/meson/lib/meson.build @@ -124,7 +124,7 @@ libzstd = library('zstd', version: zstd_libversion) libzstd_dep = declare_dependency(link_with: libzstd, - include_directories: libzstd_includes) + include_directories: join_paths(zstd_rootdir,'lib')) # Do not expose private headers # we link to both: # - the shared library (for public symbols) From ccc02a9a7786c7556d31cfd3d7b08ba8d6895eea Mon Sep 17 00:00:00 2001 From: Artem Labazov Date: Mon, 30 Sep 2024 18:05:57 +0300 Subject: [PATCH 071/405] meson: Fix contrib and tests build --- build/meson/contrib/pzstd/meson.build | 2 +- build/meson/lib/meson.build | 9 ++++++--- build/meson/tests/meson.build | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/build/meson/contrib/pzstd/meson.build b/build/meson/contrib/pzstd/meson.build index b95dc7964..c3ee3d60a 100644 --- a/build/meson/contrib/pzstd/meson.build +++ b/build/meson/contrib/pzstd/meson.build @@ -20,6 +20,6 @@ pzstd = executable('pzstd', pzstd_sources, cpp_args: pzstd_warning_flags, include_directories: pzstd_includes, - dependencies: [ libzstd_dep, thread_dep ], + dependencies: [ libzstd_internal_dep, thread_dep ], override_options: ['b_ndebug=true'], install: true) diff --git a/build/meson/lib/meson.build b/build/meson/lib/meson.build index 6c5d53d1a..4ff926f9c 100644 --- a/build/meson/lib/meson.build +++ b/build/meson/lib/meson.build @@ -134,7 +134,8 @@ libzstd_dep = declare_dependency(link_with: libzstd, # -fvisibility=hidden means those cannot be found if get_option('default_library') == 'static' libzstd_static = libzstd - libzstd_internal_dep = libzstd_dep + libzstd_internal_dep = declare_dependency(link_with: libzstd, + include_directories: libzstd_includes) else if get_option('default_library') == 'shared' libzstd_static = static_library('zstd_objlib', @@ -147,11 +148,13 @@ else if cc_id == compiler_msvc # msvc does not actually support linking to both, but errors out with: # error LNK2005: ZSTD_ already defined in zstd.lib(zstd-1.dll) - libzstd_internal_dep = declare_dependency(link_with: libzstd_static) + libzstd_internal_dep = declare_dependency(link_with: libzstd_static, + include_directories: libzstd_includes) else libzstd_internal_dep = declare_dependency(link_with: libzstd, # the static library must be linked after the shared one - dependencies: declare_dependency(link_with: libzstd_static)) + dependencies: declare_dependency(link_with: libzstd_static), + include_directories: libzstd_includes) endif endif diff --git a/build/meson/tests/meson.build b/build/meson/tests/meson.build index 9847ab037..71ffc5069 100644 --- a/build/meson/tests/meson.build +++ b/build/meson/tests/meson.build @@ -93,7 +93,7 @@ roundTripCrash = executable('roundTripCrash', longmatch_sources = [join_paths(zstd_rootdir, 'tests/longmatch.c')] longmatch = executable('longmatch', longmatch_sources, - dependencies: [ libzstd_dep ], + dependencies: [ libzstd_internal_dep ], install: false) invalidDictionaries_sources = [join_paths(zstd_rootdir, 'tests/invalidDictionaries.c')] From 3d5d3f5630acdb14ddd94721b2011dca8eaf496a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 30 Sep 2024 21:38:29 -0700 Subject: [PATCH 072/405] removing nightly tests built on circleci --- .circleci/config.yml | 123 ---------------------------- .circleci/images/primary/Dockerfile | 9 -- .github/workflows/nightly.yml | 29 ------- 3 files changed, 161 deletions(-) delete mode 100644 .circleci/config.yml delete mode 100644 .circleci/images/primary/Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 621ac49ff..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,123 +0,0 @@ -version: 2 - -jobs: - # the first half of the jobs are in this test - short-tests-0: - # TODO: Create a small custom docker image with all the dependencies we need - # preinstalled to reduce installation time. - docker: - - image: fbopensource/zstd-circleci-primary:0.0.1 - steps: - - checkout - - run: - name: Test - command: | - ./tests/test-license.py - cc -v - CFLAGS="-O0 -Werror -pedantic" make allmost; make clean - make c99build; make clean - make c11build; make clean - make -j regressiontest; make clean - make shortest; make clean - make cxxtest; make clean - # the second half of the jobs are in this test - short-tests-1: - docker: - - image: fbopensource/zstd-circleci-primary:0.0.1 - steps: - - checkout - - run: - name: Test - command: | - make gnu90build; make clean - make gnu99build; make clean - make ppc64build V=1; make clean - make ppcbuild V=1; make clean - make armbuild V=1; make clean - make aarch64build V=1; make clean - make -C tests test-legacy test-longmatch; make clean - make -C lib libzstd-nomt; make clean - # This step should only be run in a cron job - regression-test: - docker: - - image: fbopensource/zstd-circleci-primary:0.0.1 - environment: - CIRCLE_ARTIFACTS: /tmp/circleci-artifacts - steps: - - checkout - # Restore the cached resources. - - restore_cache: - # We try our best to bust the cache when the data changes by hashing - # data.c. If that doesn't work, simply update the version number here - # and below. If we fail to bust the cache, the regression testing will - # still work, since it has its own stamp, but will need to redownload - # everything. - keys: - - regression-cache-{{ checksum "tests/regression/data.c" }}-v0 - - run: - name: Regression Test - command: | - make -C programs zstd - make -C tests/regression test - mkdir -p $CIRCLE_ARTIFACTS - ./tests/regression/test \ - --cache tests/regression/cache \ - --output $CIRCLE_ARTIFACTS/results.csv \ - --zstd programs/zstd - echo "NOTE: The new results.csv is uploaded as an artifact to this job" - echo " If this fails, go to the Artifacts pane in CircleCI, " - echo " download /tmp/circleci-artifacts/results.csv, and if they " - echo " are still good, copy it into the repo and commit it." - echo "> diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv" - diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv - # Only save the cache on success (default), since if the failure happened - # before we stamp the data cache, we will have a bad cache for this key. - - save_cache: - key: regression-cache-{{ checksum "tests/regression/data.c" }}-v0 - paths: - - tests/regression/cache - - store_artifacts: - path: /tmp/circleci-artifacts - - -workflows: - version: 2 - commit: - jobs: - # Run the tests in parallel - - short-tests-0 - - short-tests-1 - - regression-test - - nightly: - triggers: - - schedule: - cron: "0 0 * * *" - filters: - branches: - only: - - release - - dev - - master - jobs: - # Run daily regression tests - - regression-test - - - - # Longer tests - #- make -C tests test-zstd-nolegacy && make clean - #- pyenv global 3.4.4; make -C tests versionsTest && make clean - #- make zlibwrapper && make clean - #- gcc -v; make -C tests test32 MOREFLAGS="-I/usr/include/x86_64-linux-gnu" && make clean - #- make uasan && make clean - #- make asan32 && make clean - #- make -C tests test32 CC=clang MOREFLAGS="-g -fsanitize=address -I/usr/include/x86_64-linux-gnu" - # Valgrind tests - #- CFLAGS="-O1 -g" make -C zlibWrapper valgrindTest && make clean - #- make -C tests valgrindTest && make clean - # ARM, AArch64, PowerPC, PowerPC64 tests - #- make ppctest && make clean - #- make ppc64test && make clean - #- make armtest && make clean - #- make aarch64test && make clean diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile deleted file mode 100644 index 4b77032b6..000000000 --- a/.circleci/images/primary/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM circleci/buildpack-deps@sha256:f6f10c11b7b8ccfd4f4a5b830c3256803604ce61292b60cb22e26b12f62b0e8c - -RUN sudo dpkg --add-architecture i386 -RUN sudo apt-get -y -qq update -RUN sudo apt-get -y install \ - gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \ - libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ - libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \ - libcurl4-openssl-dev diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 704e78922..98cbb352d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -11,41 +11,12 @@ permissions: read-all jobs: regression-test: runs-on: ubuntu-latest - services: - docker: - image: fbopensource/zstd-circleci-primary:0.0.1 - options: --entrypoint /bin/bash - env: - CIRCLE_ARTIFACTS: "/tmp/circleci-artifacts" steps: - uses: actions/checkout@v4 - - uses: actions/cache@v4 - with: - key: regression-cache-{{ checksum "tests/regression/data.c" }}-v0 - path: tests/regression/cache - restore-keys: regression-cache-{{ checksum "tests/regression/data.c" }}-v0 - - uses: actions/upload-artifact@v4 - with: - path: "/tmp/circleci-artifacts" - - name: Install Dependencies - run: | - sudo apt-get update - sudo apt-get install libcurl4-gnutls-dev - name: Regression Test run: | make -C programs zstd make -C tests/regression test - mkdir -p $CIRCLE_ARTIFACTS - ./tests/regression/test \ - --cache tests/regression/cache \ - --output $CIRCLE_ARTIFACTS/results.csv \ - --zstd programs/zstd - echo "NOTE: The new results.csv is uploaded as an artifact to this job" - echo " If this fails, go to the Artifacts pane in CircleCI, " - echo " download /tmp/circleci-artifacts/results.csv, and if they " - echo " are still good, copy it into the repo and commit it." - echo "> diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv" - diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv # Longer tests #- make -C tests test-zstd-nolegacy && make clean From de6cc98e07e1770b9f4571ea25dd6bf61612c08f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 1 Oct 2024 09:25:26 -0700 Subject: [PATCH 073/405] fix incorrect pointer manipulation fix #4155 --- tests/regression/result.c | 4 ++-- tests/regression/result.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression/result.c b/tests/regression/result.c index 84a8a044d..a13ef9c17 100644 --- a/tests/regression/result.c +++ b/tests/regression/result.c @@ -10,7 +10,7 @@ #include "result.h" -char const* result_get_error_string(result_t result) { +const char* result_get_error_string(result_t result) { switch (result_get_error(result)) { case result_error_ok: return "okay"; @@ -25,6 +25,6 @@ char const* result_get_error_string(result_t result) { case result_error_round_trip_error: return "round trip error"; default: - return "unknown error - " + result_get_error(result); + return "unknown error"; } } diff --git a/tests/regression/result.h b/tests/regression/result.h index 8a761ea4d..818ec356c 100644 --- a/tests/regression/result.h +++ b/tests/regression/result.h @@ -94,7 +94,7 @@ static result_error_t result_get_error(result_t result) { return result.internal_error; } -char const* result_get_error_string(result_t result); +const char* result_get_error_string(result_t result); static result_data_t result_get_data(result_t result) { return result.internal_data; From 8edd1476862222c4f0e88511241b83ab0e1948c4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 1 Oct 2024 09:52:45 -0700 Subject: [PATCH 074/405] fix missing fclose() fix #4151 --- programs/benchzstd.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 272af5924..0a1cba9e6 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -1067,11 +1067,12 @@ static int BMK_loadFiles( size_t pos = 0, totalSize = 0; unsigned n; for (n = 0; n < nbFiles; n++) { + const char* const filename = fileNamesTable[n]; U64 fileSize = UTIL_getFileSize( - fileNamesTable[n]); /* last file may be shortened */ - if (UTIL_isDirectory(fileNamesTable[n])) { + filename); /* last file may be shortened */ + if (UTIL_isDirectory(filename)) { DISPLAYLEVEL( - 2, "Ignoring %s directory... \n", fileNamesTable[n]); + 2, "Ignoring %s directory... \n", filename); fileSizes[n] = 0; continue; } @@ -1079,25 +1080,29 @@ static int BMK_loadFiles( DISPLAYLEVEL( 2, "Cannot evaluate size of %s, ignoring ... \n", - fileNamesTable[n]); + filename); fileSizes[n] = 0; continue; } - { - FILE* const f = fopen(fileNamesTable[n], "rb"); - if (f == NULL) + if (fileSize > bufferSize - pos) { + /* buffer too small - limit quantity loaded */ + fileSize = bufferSize - pos; + nbFiles = n; /* stop after this file */ + } + + { FILE* const f = fopen(filename, "rb"); + if (f == NULL) { RETURN_ERROR_INT( - 10, "impossible to open file %s", fileNamesTable[n]); - OUTPUTLEVEL(2, "Loading %s... \r", fileNamesTable[n]); - if (fileSize > bufferSize - pos) - fileSize = bufferSize - pos, - nbFiles = n; /* buffer too small - stop after this file */ - { - size_t const readSize = + 10, "cannot open file %s", filename); + } + OUTPUTLEVEL(2, "Loading %s... \r", filename); + { size_t const readSize = fread(((char*)buffer) + pos, 1, (size_t)fileSize, f); - if (readSize != (size_t)fileSize) + if (readSize != (size_t)fileSize) { + fclose(f); RETURN_ERROR_INT( - 11, "could not read %s", fileNamesTable[n]); + 11, "invalid read %s", filename); + } pos += readSize; } fileSizes[n] = (size_t)fileSize; From a8b86d024a2e5ca7029ab19f7638cd6ca42bde1a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 2 Oct 2024 22:57:36 -0700 Subject: [PATCH 075/405] refactor documentation of the FSE decoding table build process --- doc/zstd_compression_format.md | 179 ++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 79 deletions(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index e1e66c830..3c1ec3ad9 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -16,7 +16,7 @@ Distribution of this document is unlimited. ### Version -0.4.0 (2023-06-05) +0.4.2 (2024-10-02) Introduction @@ -1038,53 +1038,54 @@ and to compress Huffman headers. FSE --- FSE, short for Finite State Entropy, is an entropy codec based on [ANS]. -FSE encoding/decoding involves a state that is carried over between symbols, -so decoding must be done in the opposite direction as encoding. +FSE encoding/decoding involves a state that is carried over between symbols. +Decoding must be done in the opposite direction as encoding. Therefore, all FSE bitstreams are read from end to beginning. Note that the order of the bits in the stream is not reversed, -we just read the elements in the reverse order they are written. +we just read each multi-bits element in the reverse order they are encoded. For additional details on FSE, see [Finite State Entropy]. [Finite State Entropy]:https://github.com/Cyan4973/FiniteStateEntropy/ -FSE decoding involves a decoding table which has a power of 2 size, and contain three elements: +FSE decoding is directed by a decoding table with a power of 2 size, each row containing three elements: `Symbol`, `Num_Bits`, and `Baseline`. The `log2` of the table size is its `Accuracy_Log`. An FSE state value represents an index in this table. To obtain the initial state value, consume `Accuracy_Log` bits from the stream as a __little-endian__ value. -The next symbol in the stream is the `Symbol` indicated in the table for that state. +The first symbol in the stream is the `Symbol` indicated in the table for that state. To obtain the next state value, the decoder should consume `Num_Bits` bits from the stream as a __little-endian__ value and add it to `Baseline`. [ANS]: https://en.wikipedia.org/wiki/Asymmetric_Numeral_Systems ### FSE Table Description -To decode FSE streams, it is necessary to construct the decoding table. -The Zstandard format encodes FSE table descriptions as follows: +To decode an FSE bitstream, it is necessary to build its FSE decoding table. +The decoding table is derived from a distribution of Probabilities. +The Zstandard format encodes distributions of Probabilities as follows: -An FSE distribution table describes the probabilities of all symbols -from `0` to the last present one (included) -on a normalized scale of `1 << Accuracy_Log` . -Note that there must be two or more symbols with nonzero probability. +The distribution of probabilities is described in a bitstream which is read forward, +in __little-endian__ fashion. +The amount of bytes consumed from the bitstream to describe the distribution +is discovered at the end of the decoding process. -It's a bitstream which is read forward, in __little-endian__ fashion. -It's not necessary to know bitstream exact size, -it will be discovered and reported by the decoding process. - -The bitstream starts by reporting on which scale it operates. +The bitstream starts by reporting on which scale the distribution operates. Let's `low4Bits` designate the lowest 4 bits of the first byte : `Accuracy_Log = low4bits + 5`. -Then follows each symbol value, from `0` to last present one. -The number of bits used by each field is variable. +An FSE distribution table describes the probabilities of all symbols +from `0` to the last present one (included) in natural order. +The sum of probabilities is normalized to reach a power of 2 total of `1 << Accuracy_Log` . +There must be two or more symbols with non-zero probabilities. + +The number of bits used to decode each probability is variable. It depends on : - Remaining probabilities + 1 : __example__ : Presuming an `Accuracy_Log` of 8, - and presuming 100 probabilities points have already been distributed, + and presuming 100 probability points have already been distributed, the decoder may read any value from `0` to `256 - 100 + 1 == 157` (inclusive). Therefore, it may read up to `log2sup(157) == 8` bits, where `log2sup(N)` is the smallest integer `T` that satisfies `(1 << T) > N`. @@ -1098,115 +1099,133 @@ It depends on : values from 98 to 157 use 8 bits. This is achieved through this scheme : - | Value read | Value decoded | Number of bits used | - | ---------- | ------------- | ------------------- | - | 0 - 97 | 0 - 97 | 7 | - | 98 - 127 | 98 - 127 | 8 | - | 128 - 225 | 0 - 97 | 7 | - | 226 - 255 | 128 - 157 | 8 | + | 8-bit field read | Value decoded | Nb of bits consumed | + | ---------------- | ------------- | ------------------- | + | 0 - 97 | 0 - 97 | 7 | + | 98 - 127 | 98 - 127 | 8 | + | 128 - 225 | 0 - 97 | 7 | + | 226 - 255 | 128 - 157 | 8 | -Symbols probabilities are read one by one, in order. +Probability is derived from Value decoded using the following formula: +`Probality = Value - 1` -Probability is obtained from Value decoded by following formula : -`Proba = value - 1` +Consequently, a Probability of `0` is described by a Value `1`. -It means value `0` becomes negative probability `-1`. -`-1` is a special probability, which means "less than 1". -Its effect on distribution table is described in the [next section]. -For the purpose of calculating total allocated probability points, it counts as one. +A Value `0` is used to signal a special case, named "Probability `-1`". +It describes a probability which should have been "less than 1". +Its effect on the decoding table building process is described in the [next section]. +For the purpose of counting total allocated probability points, it counts as one. [next section]:#from-normalized-distribution-to-decoding-tables -When a symbol has a __probability__ of `zero`, +Symbols probabilities are read one by one, in order. +After each probability is decoded, the total nb of probability points is updated. +This is used to dermine how many bits must be read to decode the probability of next symbol. + +When a symbol has a __probability__ of `zero` (decoded from reading a Value `1`), it is followed by a 2-bits repeat flag. This repeat flag tells how many probabilities of zeroes follow the current one. It provides a number ranging from 0 to 3. If it is a 3, another 2-bits repeat flag follows, and so on. -When last symbol reaches cumulated total of `1 << Accuracy_Log`, -decoding is complete. -If this process results in a non-zero probability for a value outside of the -valid range of values that the FSE table is defined for, even if that value is -not used, then the data is considered corrupted. In the case of offset codes, -a decoder implementation may reject a frame containing a non-zero probability -for an offset code larger than the largest offset code supported by the decoder -implementation. +When the Probability for a symbol makes cumulated total reach `1 << Accuracy_Log`, +then it's the last symbol, and decoding is complete. Then the decoder can tell how many bytes were used in this process, and how many symbols are present. The bitstream consumes a round number of bytes. Any remaining bit within the last byte is just unused. +If this process results in a non-zero probability for a symbol outside of the +valid range of symbols that the FSE table is defined for, even if that symbol is +not used, then the data is considered corrupted. +For the specific case of offset codes, +a decoder implementation may reject a frame containing a non-zero probability +for an offset code larger than the largest offset code supported by the decoder +implementation. + #### From normalized distribution to decoding tables -The distribution of normalized probabilities is enough +The normalized distribution of probabilities is enough to create a unique decoding table. - -It follows the following build rule : +It is generated using the following build rule : The table has a size of `Table_Size = 1 << Accuracy_Log`. -Each cell describes the symbol decoded, -and instructions to get the next state (`Number_of_Bits` and `Baseline`). +Each row specifies the decoded symbol, +and instructions to reach the next state (`Number_of_Bits` and `Baseline`). -Symbols are scanned in their natural order for "less than 1" probabilities. -Symbols with this probability are being attributed a single cell, +Symbols are first scanned in their natural order for "less than 1" probabilities +(previously decoded from a Value of `0`). +Symbols with this special probability are being attributed a single row, starting from the end of the table and retreating. These symbols define a full state reset, reading `Accuracy_Log` bits. -Then, all remaining symbols, sorted in natural order, are allocated cells. -Starting from symbol `0` (if it exists), and table position `0`, -each symbol gets allocated as many cells as its probability. -Cell allocation is spread, not linear : -each successor position follows this rule : +Then, all remaining symbols, sorted in natural order, are allocated rows. +Starting from smallest present symbol, and table position `0`, +each symbol gets allocated as many rows as its probability. +Row allocation is not linear, it follows this order, in modular arithmetic: ``` position += (tableSize>>1) + (tableSize>>3) + 3; position &= tableSize-1; ``` -A position is skipped if already occupied by a "less than 1" probability symbol. -`position` does not reset between symbols, it simply iterates through -each position in the table, switching to the next symbol when enough -states have been allocated to the current one. +Using above ordering rule, each symbol gets allocated as many rows as its probability. +If a position is already occupied by a "less than 1" probability symbol, +it is simply skipped, and the next position is allocated instead. +Once enough rows have been allocated for the current symbol, +the allocation process continues, using the next symbol, in natural order. +This process guarantees that the table is entirely and exactly filled. -The process guarantees that the table is entirely filled. -Each cell corresponds to a state value, which contains the symbol being decoded. +Each row specifies a decoded symbol, and is accessed by current state value. +It also specifies `Number_of_Bits` and `Baseline`, which are required to determine next state value. -To add the `Number_of_Bits` and `Baseline` required to retrieve next state, -it's first necessary to sort all occurrences of each symbol in state order. -Lower states will need 1 more bit than higher ones. -The process is repeated for each symbol. +To correctly set these fields, it's necessary to sort all occurrences of each symbol in state value order, +and then attribute N+1 bits to lower rows, and N bits to higher rows, +following the process described below (using an example): __Example__ : -Presuming a symbol has a probability of 5, -it receives 5 cells, corresponding to 5 state values. -These state values are then sorted in natural order. +Presuming an `Accuracy_Log` of 7, +let's imagine a symbol with a Probability of 5: +it receives 5 rows, corresponding to 5 state values between `0` and `127`. -Next power of 2 after 5 is 8. -Space of probabilities must be divided into 8 equal parts. -Presuming the `Accuracy_Log` is 7, it defines a space of 128 states. -Divided by 8, each share is 16 large. +In this example, the first state value happens to be `1` (after unspecified previous symbols). +The next 4 states are then determined using above modular arithmetic rule, +which specifies to add `64+16+3 = 83` modulo `128` to jump to next position, +producing the following series: `1`, `84`, `39`, `122`, `77` (modular arithmetic). +(note: the next symbol will then start at `32`). -In order to reach 8 shares, 8-5=3 lowest states will count "double", +These state values are then sorted in natural order, +resulting in the following series: `1`, `39`, `77`, `84`, `122`. + +The next power of 2 after 5 is 8. +Therefore, the probability space will be divided into 8 equal parts. +Since the probability space is `1<<7 = 128` large, each share is `128/8 = 16` large. + +In order to reach 8 shares, the `8-5 = 3` lowest states will count "double", doubling their shares (32 in width), hence requiring one more bit. -Baseline is assigned starting from the higher states using fewer bits, -increasing at each state, then resuming at the first state, -each state takes its allocated width from Baseline. +Baseline is assigned starting from the lowest state using fewer bits, +continuing in natural state order, looping back at the beginning. +Each state takes its allocated range from Baseline, sized by its `Number_of_Bits`. | state order | 0 | 1 | 2 | 3 | 4 | | ---------------- | ----- | ----- | ------ | ---- | ------ | | state value | 1 | 39 | 77 | 84 | 122 | | width | 32 | 32 | 32 | 16 | 16 | | `Number_of_Bits` | 5 | 5 | 5 | 4 | 4 | -| range number | 2 | 4 | 6 | 0 | 1 | +| allocation order | 3 | 4 | 5 | 1 | 2 | | `Baseline` | 32 | 64 | 96 | 0 | 16 | | range | 32-63 | 64-95 | 96-127 | 0-15 | 16-31 | -During decoding, the next state value is determined from current state value, -by reading the required `Number_of_Bits`, and adding the specified `Baseline`. +During decoding, the next state value is determined by using current state value as row number, +then reading the required `Number_of_Bits` from the bitstream, and adding the specified `Baseline`. -See [Appendix A] for the results of this process applied to the default distributions. +Note: +as a trivial example, it follows that, for a symbol with a Probability of `1`, +`Baseline` is necessarily `0`, and `Number_of_Bits` is necessarily `Accuracy_Log`. + +See [Appendix A] to see the outcome of this process applied to the default distributions. [Appendix A]: #appendix-a---decoding-tables-for-predefined-codes @@ -1716,6 +1735,8 @@ or at least provide a meaningful error code explaining for which reason it canno Version changes --------------- +- 0.4.2 : refactor FSE table construction process, inspired by Donald Pian +- 0.4.1 : clarifications on a few error scenarios, by Eric Lasota - 0.4.0 : fixed imprecise behavior for nbSeq==0, detected by Igor Pavlov - 0.3.9 : clarifications for Huffman-compressed literal sizes. - 0.3.8 : clarifications for Huffman Blocks and Huffman Tree descriptions. From b84653fc839367281481bc3fee9f9d7e8496701f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 3 Oct 2024 15:10:16 -0700 Subject: [PATCH 076/405] fix dependency for nightly github actions tests --- .github/workflows/nightly.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 98cbb352d..5e531d3b6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,18 +1,20 @@ name: facebook/zstd/nightly on: schedule: - - cron: 0 0 * * * + - cron: '0 0 * * *' push: branches: - - release - - dev - - master + - release + - dev + - '*nightly*' permissions: read-all jobs: regression-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - name: Regression Test run: | make -C programs zstd From 1e7fa242f4aa71c3aec5e1e39ec69ad54e117051 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 7 Oct 2024 11:22:40 -0700 Subject: [PATCH 077/405] minor refactor zstd_fast make hot variables more local --- lib/compress/zstd_compress_internal.h | 4 +- lib/compress/zstd_fast.c | 71 +++++++++++++-------------- 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index cbcded28d..53c3bdee8 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -560,7 +560,9 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value) /* ZSTD_selectAddr: * @return a >= b ? trueAddr : falseAddr, * tries to force branchless codegen. */ -MEM_STATIC const BYTE* ZSTD_selectAddr(U32 a, U32 b, const BYTE* trueAddr, const BYTE* falseAddr) { +MEM_STATIC const BYTE* +ZSTD_selectAddr(U32 a, U32 b, const BYTE* trueAddr, const BYTE* falseAddr) +{ #if defined(__GNUC__) && defined(__x86_64__) __asm__ ( "cmp %1, %2\n" diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 838a18ee5..0b6230150 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -166,7 +166,6 @@ size_t ZSTD_compressBlock_fast_noDict_generic( * we load from here instead of from tables, if the index is invalid. * Used to avoid unpredictable branches. */ const BYTE dummy[] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0xe2,0xb4}; - const BYTE *mvalAddr; const BYTE* anchor = istart; const BYTE* ip0 = istart; @@ -182,7 +181,6 @@ size_t ZSTD_compressBlock_fast_noDict_generic( size_t hash0; /* hash for ip0 */ size_t hash1; /* hash for ip1 */ U32 idx; /* match idx for ip0 */ - U32 mval; /* src value at match idx */ U32 offcode; const BYTE* match0; @@ -255,22 +253,21 @@ _start: /* Requires: ip0 */ * However expression below complies into conditional move. Since * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex * if there is a match, all branches become predictable. */ - mvalAddr = base + idx; - mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, mvalAddr, &dummy[0]); + { const BYTE* mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, base + idx, &dummy[0]); + /* load match for ip[0] */ + U32 const mval = MEM_read32(mvalAddr); - /* load match for ip[0] */ - mval = MEM_read32(mvalAddr); + /* check match at ip[0] */ + if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { + /* found a match! */ - /* check match at ip[0] */ - if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { - /* found a match! */ + /* Write next hash table entry (it's already calculated). + * This write is known to be safe because the ip1 == ip0 + 1, + * so searching will resume after ip1 */ + hashTable[hash1] = (U32)(ip1 - base); - /* First write next hash table entry; we've already calculated it. - * This write is known to be safe because the ip1 == ip0 + 1, so - * we know we will resume searching after ip1 */ - hashTable[hash1] = (U32)(ip1 - base); - - goto _offset; + goto _offset; + } } /* lookup ip[1] */ @@ -289,32 +286,30 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; - mvalAddr = base + idx; - mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, mvalAddr, &dummy[0]); + { const BYTE* mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, base + idx, &dummy[0]); + /* load match for ip[0] */ + U32 const mval = MEM_read32(mvalAddr); - /* load match for ip[0] */ - mval = MEM_read32(mvalAddr); + /* check match at ip[0] */ + if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { + /* found a match! */ + /* first write next hash table entry; we've already calculated it */ + if (step <= 4) { + /* We need to avoid writing an index into the hash table >= the + * position at which we will pick up our searching after we've + * taken this match. + * + * The minimum possible match has length 4, so the earliest ip0 + * can be after we take this match will be the current ip0 + 4. + * ip1 is ip0 + step - 1. If ip1 is >= ip0 + 4, we can't safely + * write this position. + */ + hashTable[hash1] = (U32)(ip1 - base); + } - /* check match at ip[0] */ - if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { - /* found a match! */ - - /* first write next hash table entry; we've already calculated it */ - if (step <= 4) { - /* We need to avoid writing an index into the hash table >= the - * position at which we will pick up our searching after we've - * taken this match. - * - * The minimum possible match has length 4, so the earliest ip0 - * can be after we take this match will be the current ip0 + 4. - * ip1 is ip0 + step - 1. If ip1 is >= ip0 + 4, we can't safely - * write this position. - */ - hashTable[hash1] = (U32)(ip1 - base); + goto _offset; } - - goto _offset; } /* lookup ip[1] */ @@ -554,7 +549,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( size_t const dictHashAndTag1 = ZSTD_hashPtr(ip1, dictHBits, mls); hashTable[hash0] = curr; /* update hash table */ - if ((ZSTD_index_overlap_check(prefixStartIndex, repIndex)) + if ((ZSTD_index_overlap_check(prefixStartIndex, repIndex)) && (MEM_read32(repMatch) == MEM_read32(ip0 + 1))) { const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip0 + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4; From 3b343dcfb140ccb278a781faa8116d273f36e4a1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 7 Oct 2024 17:15:07 -0700 Subject: [PATCH 078/405] refactor huffman prefix code paragraph --- doc/zstd_compression_format.md | 67 +++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index 3c1ec3ad9..b4a6edf9e 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -16,7 +16,7 @@ Distribution of this document is unlimited. ### Version -0.4.2 (2024-10-02) +0.4.3 (2024-10-07) Introduction @@ -1270,13 +1270,13 @@ This specification limits maximum code length to 11 bits. #### Representation -All literal values from zero (included) to last present one (excluded) +All literal symbols from zero (included) to last present one (excluded) are represented by `Weight` with values from `0` to `Max_Number_of_Bits`. Transformation from `Weight` to `Number_of_Bits` follows this formula : ``` Number_of_Bits = Weight ? (Max_Number_of_Bits + 1 - Weight) : 0 ``` -When a literal value is not present, it receives a `Weight` of 0. +When a literal symbol is not present, it receives a `Weight` of 0. The least frequent symbol receives a `Weight` of 1. If no literal has a `Weight` of 1, then the data is considered corrupted. If there are not at least two literals with non-zero `Weight`, then the data @@ -1293,33 +1293,38 @@ otherwise the representation is considered corrupted. __Example__ : Let's presume the following Huffman tree must be described : -| literal value | 0 | 1 | 2 | 3 | 4 | 5 | +| literal symbol | A | B | C | D | E | F | | ---------------- | --- | --- | --- | --- | --- | --- | | `Number_of_Bits` | 1 | 2 | 3 | 0 | 4 | 4 | The tree depth is 4, since its longest elements uses 4 bits -(longest elements are the one with smallest frequency). -Literal value `5` will not be listed, as it can be determined from previous values 0-4, -nor will values above `5` as they are all 0. -Values from `0` to `4` will be listed using `Weight` instead of `Number_of_Bits`. +(longest elements are the ones with smallest frequency). + +All symbols will now receive a `Weight` instead of `Number_of_Bits`. Weight formula is : ``` Weight = Number_of_Bits ? (Max_Number_of_Bits + 1 - Number_of_Bits) : 0 ``` -It gives the following series of weights : +It gives the following series of Weights : -| literal value | 0 | 1 | 2 | 3 | 4 | -| ------------- | --- | --- | --- | --- | --- | -| `Weight` | 4 | 3 | 2 | 0 | 1 | +| literal symbol | A | B | C | D | E | F | +| -------------- | --- | --- | --- | --- | --- | --- | +| `Weight` | 4 | 3 | 2 | 0 | 1 | 1 | + +This list will be sent to the decoder, with the following modifications: + +- `F` will not be listed, because it can be determined from previous symbols +- nor will symbols above `F` as they are all 0 +- on the other hand, all symbols before `A`, starting with `\0`, will be listed, with a Weight of 0. The decoder will do the inverse operation : -having collected weights of literal symbols from `0` to `4`, -it knows the last literal, `5`, is present with a non-zero `Weight`. -The `Weight` of `5` can be determined by advancing to the next power of 2. +having collected weights of literal symbols from `A` to `E`, +it knows the last literal, `F`, is present with a non-zero `Weight`. +The `Weight` of `F` can be determined by advancing to the next power of 2. The sum of `2^(Weight-1)` (excluding 0's) is : `8 + 4 + 2 + 0 + 1 = 15`. Nearest larger power of 2 value is 16. -Therefore, `Max_Number_of_Bits = 4` and `Weight[5] = log_2(16 - 15) + 1 = 1`. +Therefore, `Max_Number_of_Bits = log2(16) = 4` and `Weight[F] = log_2(16 - 15) + 1 = 1`. #### Huffman Tree header @@ -1359,7 +1364,7 @@ sharing a single distribution table. To decode an FSE bitstream, it is necessary to know its compressed size. Compressed size is provided by `headerByte`. It's also necessary to know its _maximum possible_ decompressed size, -which is `255`, since literal values span from `0` to `255`, +which is `255`, since literal symbols span from `0` to `255`, and last symbol's `Weight` is not represented. An FSE bitstream starts by a header, describing probabilities distribution. @@ -1395,26 +1400,27 @@ It is possible to transform weights into `Number_of_Bits`, using this formula: ``` Number_of_Bits = (Weight>0) ? Max_Number_of_Bits + 1 - Weight : 0 ``` -Symbols are sorted by `Weight`. -Within same `Weight`, symbols keep natural sequential order. +In order to determine which prefix is assigned to each Symbol, +Symbols are first sorted by `Weight`, then by natural sequential order. Symbols with a `Weight` of zero are removed. -Then, starting from lowest `Weight`, prefix codes are distributed in sequential order. +Then, starting from lowest `Weight` (hence highest `Number_of_Bits`), +prefix codes are assigned in ascending order. __Example__ : -Let's presume the following list of weights has been decoded : +Let's assume the following list of weights has been decoded: -| Literal | 0 | 1 | 2 | 3 | 4 | 5 | +| Literal | A | B | C | D | E | F | | -------- | --- | --- | --- | --- | --- | --- | | `Weight` | 4 | 3 | 2 | 0 | 1 | 1 | Sorted by weight and then natural sequential order, -it gives the following distribution : +it gives the following prefix codes distribution: -| Literal | 3 | 4 | 5 | 2 | 1 | 0 | -| ---------------- | --- | --- | --- | --- | --- | ---- | -| `Weight` | 0 | 1 | 1 | 2 | 3 | 4 | -| `Number_of_Bits` | 0 | 4 | 4 | 3 | 2 | 1 | -| prefix codes | N/A | 0000| 0001| 001 | 01 | 1 | +| Literal | D | E | F | C | B | A | +| ---------------- | --- | ---- | ---- | --- | --- | --- | +| `Weight` | 0 | 1 | 1 | 2 | 3 | 4 | +| `Number_of_Bits` | 0 | 4 | 4 | 3 | 2 | 1 | +| prefix code | N/A | 0000 | 0001 | 001 | 01 | 1 | ### Huffman-coded Streams @@ -1437,10 +1443,10 @@ it's possible to read the bitstream in a __little-endian__ fashion, keeping track of already used bits. Since the bitstream is encoded in reverse order, starting from the end read symbols in forward order. -For example, if the literal sequence "0145" was encoded using above prefix code, +For example, if the literal sequence `ABEF` was encoded using above prefix code, it would be encoded (in reverse order) as: -|Symbol | 5 | 4 | 1 | 0 | Padding | +|Symbol | F | E | B | A | Padding | |--------|------|------|----|---|---------| |Encoding|`0000`|`0001`|`01`|`1`| `00001` | @@ -1735,6 +1741,7 @@ or at least provide a meaningful error code explaining for which reason it canno Version changes --------------- +- 0.4.3 : clarifications for Huffman prefix code assignment example - 0.4.2 : refactor FSE table construction process, inspired by Donald Pian - 0.4.1 : clarifications on a few error scenarios, by Eric Lasota - 0.4.0 : fixed imprecise behavior for nbSeq==0, detected by Igor Pavlov From 2cc600bab21657ccf966ceadfeb316e2eacff25c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 8 Oct 2024 11:10:48 -0700 Subject: [PATCH 079/405] refactor search into an inline function for easier swapping with a parameter --- lib/compress/zstd_compress_internal.h | 4 +- lib/compress/zstd_fast.c | 91 +++++++++++++-------------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 53c3bdee8..64618848d 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -561,14 +561,14 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value) * @return a >= b ? trueAddr : falseAddr, * tries to force branchless codegen. */ MEM_STATIC const BYTE* -ZSTD_selectAddr(U32 a, U32 b, const BYTE* trueAddr, const BYTE* falseAddr) +ZSTD_selectAddr(U32 index, U32 lowLimit, const BYTE* trueAddr, const BYTE* falseAddr) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ( "cmp %1, %2\n" "cmova %3, %0\n" : "+r"(trueAddr) - : "r"(a), "r"(b), "r"(falseAddr) + : "r"(index), "r"(lowLimit), "r"(falseAddr) ); return trueAddr; #else diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 0b6230150..94e6300eb 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -97,6 +97,18 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, } +static int +ZSTD_findMatch_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress) +{ + /* idx >= prefixStartIndex is a (somewhat) unpredictable branch. + * However expression below complies into conditional move. Since + * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex + * if there is a match, all branches become predictable. */ + const BYTE* mvalAddr = ZSTD_selectAddr(currentIdx, lowLimit, matchAddress, fakeAddress); + return ((MEM_read32(currentPtr) == MEM_read32(mvalAddr)) & (currentIdx >= lowLimit)); +} + + /** * If you squint hard enough (and ignore repcodes), the search operation at any * given position is broken into 4 stages: @@ -148,13 +160,12 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_noDict_generic( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, - U32 const mls, U32 const hasStep) + U32 const mls, U32 const unpredictable) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; U32 const hlog = cParams->hashLog; - /* support stepSize of 0 */ - size_t const stepSize = hasStep ? (cParams->targetLength + !(cParams->targetLength) + 1) : 2; + size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; /* min 2 */ const BYTE* const base = ms->window.base; const BYTE* const istart = (const BYTE*)src; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); @@ -193,6 +204,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( size_t step; const BYTE* nextStep; const size_t kStepIncr = (1 << (kSearchStrength - 1)); + (void)unpredictable; DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); @@ -249,25 +261,15 @@ _start: /* Requires: ip0 */ goto _match; } - /* idx >= prefixStartIndex is a (somewhat) unpredictable branch. - * However expression below complies into conditional move. Since - * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex - * if there is a match, all branches become predictable. */ - { const BYTE* mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, base + idx, &dummy[0]); - /* load match for ip[0] */ - U32 const mval = MEM_read32(mvalAddr); + if (ZSTD_findMatch_cmov(ip0, base + idx, idx, prefixStartIndex, dummy)) { + /* found a match! */ - /* check match at ip[0] */ - if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { - /* found a match! */ + /* Write next hash table entry (it's already calculated). + * This write is known to be safe because the ip1 == ip0 + 1, + * so searching will resume after ip1 */ + hashTable[hash1] = (U32)(ip1 - base); - /* Write next hash table entry (it's already calculated). - * This write is known to be safe because the ip1 == ip0 + 1, - * so searching will resume after ip1 */ - hashTable[hash1] = (U32)(ip1 - base); - - goto _offset; - } + goto _offset; } /* lookup ip[1] */ @@ -286,30 +288,24 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; - { const BYTE* mvalAddr = ZSTD_selectAddr(idx, prefixStartIndex, base + idx, &dummy[0]); - /* load match for ip[0] */ - U32 const mval = MEM_read32(mvalAddr); + if (ZSTD_findMatch_cmov(ip0, base + idx, idx, prefixStartIndex, dummy)) { + /* found a match! */ - /* check match at ip[0] */ - if (MEM_read32(ip0) == mval && idx >= prefixStartIndex) { - /* found a match! */ - - /* first write next hash table entry; we've already calculated it */ - if (step <= 4) { - /* We need to avoid writing an index into the hash table >= the - * position at which we will pick up our searching after we've - * taken this match. - * - * The minimum possible match has length 4, so the earliest ip0 - * can be after we take this match will be the current ip0 + 4. - * ip1 is ip0 + step - 1. If ip1 is >= ip0 + 4, we can't safely - * write this position. - */ - hashTable[hash1] = (U32)(ip1 - base); - } - - goto _offset; + /* first write next hash table entry; it's already calculated */ + if (step <= 4) { + /* We need to avoid writing an index into the hash table >= the + * position at which we will pick up our searching after we've + * taken this match. + * + * The minimum possible match has length 4, so the earliest ip0 + * can be after we take this match will be the current ip0 + 4. + * ip1 is ip0 + step - 1. If ip1 is >= ip0 + 4, we can't safely + * write this position. + */ + hashTable[hash1] = (U32)(ip1 - base); } + + goto _offset; } /* lookup ip[1] */ @@ -409,12 +405,12 @@ _match: /* Requires: ip0, match0, offcode */ goto _start; } -#define ZSTD_GEN_FAST_FN(dictMode, mls, step) \ - static size_t ZSTD_compressBlock_fast_##dictMode##_##mls##_##step( \ +#define ZSTD_GEN_FAST_FN(dictMode, mls, cmov) \ + static size_t ZSTD_compressBlock_fast_##dictMode##_##mls##_##cmov( \ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ void const* src, size_t srcSize) \ { \ - return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls, step); \ + return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls, cmov); \ } ZSTD_GEN_FAST_FN(noDict, 4, 1) @@ -432,8 +428,10 @@ size_t ZSTD_compressBlock_fast( void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; + /* use cmov instead of branch when the branch is likely unpredictable */ + int const useCmov = 1; assert(ms->dictMatchState == NULL); - if (ms->cParams.targetLength > 1) { + if (useCmov) { switch(mls) { default: /* includes case 3 */ @@ -447,6 +445,7 @@ size_t ZSTD_compressBlock_fast( return ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize); } } else { + /* use a branch instead */ switch(mls) { default: /* includes case 3 */ From 186b1324951f2505469a3415aaf8ddc3398b9fca Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 8 Oct 2024 11:43:07 -0700 Subject: [PATCH 080/405] made search strategy switchable between cmov and branch and use a simple heuristic based on wlog to select between them. note: performance is not good on clang (yet) --- lib/compress/zstd_compress_internal.h | 12 ++--- lib/compress/zstd_fast.c | 72 +++++++++++++++------------ 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 64618848d..0be7ae14e 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -558,21 +558,21 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value) } /* ZSTD_selectAddr: - * @return a >= b ? trueAddr : falseAddr, + * @return index >= lowLimit ? candidate : backup, * tries to force branchless codegen. */ MEM_STATIC const BYTE* -ZSTD_selectAddr(U32 index, U32 lowLimit, const BYTE* trueAddr, const BYTE* falseAddr) +ZSTD_selectAddr(U32 index, U32 lowLimit, const BYTE* candidate, const BYTE* backup) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ( "cmp %1, %2\n" "cmova %3, %0\n" - : "+r"(trueAddr) - : "r"(index), "r"(lowLimit), "r"(falseAddr) + : "+r"(candidate) + : "r"(index), "r"(lowLimit), "r"(backup) ); - return trueAddr; + return candidate; #else - return a >= b ? trueAddr : falseAddr; + return index >= lowLimit ? candidate : backup; #endif } diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 94e6300eb..3c6e75131 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -45,7 +45,7 @@ void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms, size_t const hashAndTag = ZSTD_hashPtr(ip + p, hBits, mls); if (hashTable[hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) { /* not yet filled */ ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr + p); - } } } } + } } } } } static @@ -97,17 +97,34 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, } +typedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress); + static int -ZSTD_findMatch_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress) +ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress) { - /* idx >= prefixStartIndex is a (somewhat) unpredictable branch. - * However expression below complies into conditional move. Since - * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex - * if there is a match, all branches become predictable. */ + /* currentIdx >= lowLimit is a (somewhat) unpredictable branch. + * However expression below compiles into conditional move. + */ const BYTE* mvalAddr = ZSTD_selectAddr(currentIdx, lowLimit, matchAddress, fakeAddress); return ((MEM_read32(currentPtr) == MEM_read32(mvalAddr)) & (currentIdx >= lowLimit)); } +static int +ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress) +{ + /* using a branch instead of a cmov, + * because it's faster in scenarios where currentIdx >= lowLimit is generally true, + * aka almost all candidates are within range */ + U32 mval; (void)fakeAddress; + if (currentIdx >= lowLimit) { + mval = MEM_read32(matchAddress); + } else { + mval = MEM_read32(currentPtr) ^ 1; /* guaranteed to not match. */ + } + + return (MEM_read32(currentPtr) == mval); +} + /** * If you squint hard enough (and ignore repcodes), the search operation at any @@ -160,7 +177,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_noDict_generic( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, - U32 const mls, U32 const unpredictable) + U32 const mls, int useCmov) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; @@ -204,7 +221,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( size_t step; const BYTE* nextStep; const size_t kStepIncr = (1 << (kSearchStrength - 1)); - (void)unpredictable; + const ZSTD_match4Found findMatch = useCmov ? ZSTD_match4Found_cmov : ZSTD_match4Found_branch; DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); @@ -253,15 +270,15 @@ _start: /* Requires: ip0 */ offcode = REPCODE1_TO_OFFBASE; mLength += 4; - /* First write next hash table entry; we've already calculated it. - * This write is known to be safe because the ip1 is before the + /* Write next hash table entry: it's already calculated. + * This write is known to be safe because ip1 is before the * repcode (ip2). */ hashTable[hash1] = (U32)(ip1 - base); goto _match; } - if (ZSTD_findMatch_cmov(ip0, base + idx, idx, prefixStartIndex, dummy)) { + if (findMatch(ip0, base + idx, idx, prefixStartIndex, dummy)) { /* found a match! */ /* Write next hash table entry (it's already calculated). @@ -288,19 +305,13 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; - if (ZSTD_findMatch_cmov(ip0, base + idx, idx, prefixStartIndex, dummy)) { + if (findMatch(ip0, base + idx, idx, prefixStartIndex, dummy)) { /* found a match! */ - /* first write next hash table entry; it's already calculated */ + /* Write next hash table entry; it's already calculated */ if (step <= 4) { - /* We need to avoid writing an index into the hash table >= the - * position at which we will pick up our searching after we've - * taken this match. - * - * The minimum possible match has length 4, so the earliest ip0 - * can be after we take this match will be the current ip0 + 4. - * ip1 is ip0 + step - 1. If ip1 is >= ip0 + 4, we can't safely - * write this position. + /* Avoid writing an index if it's >= position where search will resume. + * The minimum possible match has length 4, so search can resume at ip0 + 4. */ hashTable[hash1] = (U32)(ip1 - base); } @@ -331,7 +342,7 @@ _start: /* Requires: ip0 */ } while (ip3 < ilimit); _cleanup: - /* Note that there are probably still a couple positions we could search. + /* Note that there are probably still a couple positions one could search. * However, it seems to be a meaningful performance hit to try to search * them. So let's not. */ @@ -405,12 +416,12 @@ _match: /* Requires: ip0, match0, offcode */ goto _start; } -#define ZSTD_GEN_FAST_FN(dictMode, mls, cmov) \ - static size_t ZSTD_compressBlock_fast_##dictMode##_##mls##_##cmov( \ +#define ZSTD_GEN_FAST_FN(dictMode, mml, cmov) \ + static size_t ZSTD_compressBlock_fast_##dictMode##_##mml##_##cmov( \ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ void const* src, size_t srcSize) \ { \ - return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls, cmov); \ + return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mml, cmov); \ } ZSTD_GEN_FAST_FN(noDict, 4, 1) @@ -427,12 +438,12 @@ size_t ZSTD_compressBlock_fast( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { - U32 const mls = ms->cParams.minMatch; - /* use cmov instead of branch when the branch is likely unpredictable */ - int const useCmov = 1; + U32 const mml = ms->cParams.minMatch; + /* use cmov when "candidate in range" branch is likely unpredictable */ + int const useCmov = ms->cParams.windowLog < 19; assert(ms->dictMatchState == NULL); if (useCmov) { - switch(mls) + switch(mml) { default: /* includes case 3 */ case 4 : @@ -446,7 +457,7 @@ size_t ZSTD_compressBlock_fast( } } else { /* use a branch instead */ - switch(mls) + switch(mml) { default: /* includes case 3 */ case 4 : @@ -458,7 +469,6 @@ size_t ZSTD_compressBlock_fast( case 7 : return ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize); } - } } From 197c258a79a94b60ec45020defc5fb6a2f570e80 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 8 Oct 2024 15:54:48 -0700 Subject: [PATCH 081/405] introduce memory barrier to force test order suggested by @terrelln --- lib/compress/zstd_fast.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 3c6e75131..9d0cefeac 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -106,7 +106,15 @@ ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 curr * However expression below compiles into conditional move. */ const BYTE* mvalAddr = ZSTD_selectAddr(currentIdx, lowLimit, matchAddress, fakeAddress); - return ((MEM_read32(currentPtr) == MEM_read32(mvalAddr)) & (currentIdx >= lowLimit)); + /* Note: this used to be written as : return test1 && test2; + * Unfortunately, once inlined, these tests become branches, + * in which case it becomes critical that they are executed in the right order (test1 then test2). + * So we have to write these tests in a specific manner to ensure their ordering. + */ + if (MEM_read32(currentPtr) != MEM_read32(mvalAddr)) return 0; + /* force ordering of these tests, which matters once the function is inlined, as they become branches */ + __asm__(""); + return currentIdx >= lowLimit; } static int From 741b860fc1e8171519a72bf3d30cdd20995b00ce Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 8 Oct 2024 16:02:54 -0700 Subject: [PATCH 082/405] store dummy bytes within ZSTD_match4Found_cmov() feels more logical, better contained --- lib/compress/zstd_fast.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 9d0cefeac..5bac5d9cf 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -97,15 +97,20 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, } -typedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress); +typedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit); static int -ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress) +ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit) { + /* Array of ~random data, should have low probability of matching data. + * Load from here if the index is invalid. + * Used to avoid unpredictable branches. */ + static const BYTE dummy[] = {0x12,0x34,0x56,0x78 }; + /* currentIdx >= lowLimit is a (somewhat) unpredictable branch. * However expression below compiles into conditional move. */ - const BYTE* mvalAddr = ZSTD_selectAddr(currentIdx, lowLimit, matchAddress, fakeAddress); + const BYTE* mvalAddr = ZSTD_selectAddr(currentIdx, lowLimit, matchAddress, dummy); /* Note: this used to be written as : return test1 && test2; * Unfortunately, once inlined, these tests become branches, * in which case it becomes critical that they are executed in the right order (test1 then test2). @@ -118,12 +123,12 @@ ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 curr } static int -ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit, const BYTE* fakeAddress) +ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit) { /* using a branch instead of a cmov, * because it's faster in scenarios where currentIdx >= lowLimit is generally true, * aka almost all candidates are within range */ - U32 mval; (void)fakeAddress; + U32 mval; if (currentIdx >= lowLimit) { mval = MEM_read32(matchAddress); } else { @@ -198,10 +203,6 @@ size_t ZSTD_compressBlock_fast_noDict_generic( const BYTE* const prefixStart = base + prefixStartIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; - /* Array of ~random data, should have low probability of matching data - * we load from here instead of from tables, if the index is invalid. - * Used to avoid unpredictable branches. */ - const BYTE dummy[] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0xe2,0xb4}; const BYTE* anchor = istart; const BYTE* ip0 = istart; @@ -286,7 +287,7 @@ _start: /* Requires: ip0 */ goto _match; } - if (findMatch(ip0, base + idx, idx, prefixStartIndex, dummy)) { + if (findMatch(ip0, base + idx, idx, prefixStartIndex)) { /* found a match! */ /* Write next hash table entry (it's already calculated). @@ -313,7 +314,7 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; - if (findMatch(ip0, base + idx, idx, prefixStartIndex, dummy)) { + if (findMatch(ip0, base + idx, idx, prefixStartIndex)) { /* found a match! */ /* Write next hash table entry; it's already calculated */ From d45aee43f4b1ac8ee0fbb182310b9b7622f85d1c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 8 Oct 2024 16:38:35 -0700 Subject: [PATCH 083/405] make __asm__ a __GNUC__ specific --- lib/compress/zstd_fast.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 5bac5d9cf..d4b8f0672 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -118,7 +118,9 @@ ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 curr */ if (MEM_read32(currentPtr) != MEM_read32(mvalAddr)) return 0; /* force ordering of these tests, which matters once the function is inlined, as they become branches */ +#if defined(__GNUC__) __asm__(""); +#endif return currentIdx >= lowLimit; } From 3e7c66acd1b6dab2473a996adac027dacf648d0a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 9 Oct 2024 01:06:24 -0700 Subject: [PATCH 084/405] added ascending order example --- doc/zstd_compression_format.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index b4a6edf9e..78279ce71 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -1400,7 +1400,7 @@ It is possible to transform weights into `Number_of_Bits`, using this formula: ``` Number_of_Bits = (Weight>0) ? Max_Number_of_Bits + 1 - Weight : 0 ``` -In order to determine which prefix is assigned to each Symbol, +In order to determine which prefix code is assigned to each Symbol, Symbols are first sorted by `Weight`, then by natural sequential order. Symbols with a `Weight` of zero are removed. Then, starting from lowest `Weight` (hence highest `Number_of_Bits`), @@ -1416,11 +1416,12 @@ Let's assume the following list of weights has been decoded: Sorted by weight and then natural sequential order, it gives the following prefix codes distribution: -| Literal | D | E | F | C | B | A | -| ---------------- | --- | ---- | ---- | --- | --- | --- | -| `Weight` | 0 | 1 | 1 | 2 | 3 | 4 | -| `Number_of_Bits` | 0 | 4 | 4 | 3 | 2 | 1 | -| prefix code | N/A | 0000 | 0001 | 001 | 01 | 1 | +| Literal | D | E | F | C | B | A | +| ---------------- | --- | ---- | ---- | ---- | ---- | ---- | +| `Weight` | 0 | 1 | 1 | 2 | 3 | 4 | +| `Number_of_Bits` | 0 | 4 | 4 | 3 | 2 | 1 | +| prefix code | N/A | 0000 | 0001 | 001 | 01 | 1 | +| ascending order | N/A | 0000 | 0001 | 001x | 01xx | 1xxx | ### Huffman-coded Streams From fa1fcb08ab447de8cdb4492d663779cad6841379 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 10 Oct 2024 16:07:20 -0700 Subject: [PATCH 085/405] minor: better variable naming --- lib/compress/zstd_fast.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index d4b8f0672..691bedc1e 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -97,10 +97,10 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, } -typedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit); +typedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit); static int -ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit) +ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit) { /* Array of ~random data, should have low probability of matching data. * Load from here if the index is invalid. @@ -110,7 +110,7 @@ ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 curr /* currentIdx >= lowLimit is a (somewhat) unpredictable branch. * However expression below compiles into conditional move. */ - const BYTE* mvalAddr = ZSTD_selectAddr(currentIdx, lowLimit, matchAddress, dummy); + const BYTE* mvalAddr = ZSTD_selectAddr(matchIdx, idxLowLimit, matchAddress, dummy); /* Note: this used to be written as : return test1 && test2; * Unfortunately, once inlined, these tests become branches, * in which case it becomes critical that they are executed in the right order (test1 then test2). @@ -121,17 +121,17 @@ ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 curr #if defined(__GNUC__) __asm__(""); #endif - return currentIdx >= lowLimit; + return matchIdx >= idxLowLimit; } static int -ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 currentIdx, U32 lowLimit) +ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit) { /* using a branch instead of a cmov, - * because it's faster in scenarios where currentIdx >= lowLimit is generally true, + * because it's faster in scenarios where matchIdx >= idxLowLimit is generally true, * aka almost all candidates are within range */ U32 mval; - if (currentIdx >= lowLimit) { + if (matchIdx >= idxLowLimit) { mval = MEM_read32(matchAddress); } else { mval = MEM_read32(currentPtr) ^ 1; /* guaranteed to not match. */ @@ -219,7 +219,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( size_t hash0; /* hash for ip0 */ size_t hash1; /* hash for ip1 */ - U32 idx; /* match idx for ip0 */ + U32 matchIdx; /* match idx for ip0 */ U32 offcode; const BYTE* match0; @@ -261,7 +261,7 @@ _start: /* Requires: ip0 */ hash0 = ZSTD_hashPtr(ip0, hlog, mls); hash1 = ZSTD_hashPtr(ip1, hlog, mls); - idx = hashTable[hash0]; + matchIdx = hashTable[hash0]; do { /* load repcode match for ip[2]*/ @@ -289,7 +289,7 @@ _start: /* Requires: ip0 */ goto _match; } - if (findMatch(ip0, base + idx, idx, prefixStartIndex)) { + if (findMatch(ip0, base + matchIdx, matchIdx, prefixStartIndex)) { /* found a match! */ /* Write next hash table entry (it's already calculated). @@ -301,7 +301,7 @@ _start: /* Requires: ip0 */ } /* lookup ip[1] */ - idx = hashTable[hash1]; + matchIdx = hashTable[hash1]; /* hash ip[2] */ hash0 = hash1; @@ -316,7 +316,7 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; - if (findMatch(ip0, base + idx, idx, prefixStartIndex)) { + if (findMatch(ip0, base + matchIdx, matchIdx, prefixStartIndex)) { /* found a match! */ /* Write next hash table entry; it's already calculated */ @@ -331,7 +331,7 @@ _start: /* Requires: ip0 */ } /* lookup ip[1] */ - idx = hashTable[hash1]; + matchIdx = hashTable[hash1]; /* hash ip[2] */ hash0 = hash1; @@ -382,7 +382,7 @@ _cleanup: _offset: /* Requires: ip0, idx */ /* Compute the offset code. */ - match0 = base + idx; + match0 = base + matchIdx; rep_offset2 = rep_offset1; rep_offset1 = (U32)(ip0-match0); offcode = OFFSET_TO_OFFBASE(rep_offset1); From 83de00316c29a7f5245a67733f6208c699b686c2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 11 Oct 2024 15:36:15 -0700 Subject: [PATCH 086/405] fixed parameter ordering in `dfast` noticed by @terrelln --- lib/compress/zstd_double_fast.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 819658caf..c04010b11 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -201,7 +201,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( * However expression below complies into conditional move. Since * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex * if there is a match, all branches become predictable. */ - matchl0_safe = ZSTD_selectAddr(prefixLowestIndex, idxl0, &dummy[0], matchl0); + matchl0_safe = ZSTD_selectAddr(idxl0, prefixLowestIndex, matchl0, &dummy[0]); /* check prefix long match */ if (MEM_read64(matchl0_safe) == MEM_read64(ip) && matchl0_safe == matchl0) { @@ -215,7 +215,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( matchl1 = base + idxl1; /* Same optimization as matchl0 above */ - matchs0_safe = ZSTD_selectAddr(prefixLowestIndex, idxs0, &dummy[0], matchs0); + matchs0_safe = ZSTD_selectAddr(idxs0, prefixLowestIndex, matchs0, &dummy[0]); /* check prefix short match */ if(MEM_read32(matchs0_safe) == MEM_read32(ip) && matchs0_safe == matchs0) { @@ -662,7 +662,7 @@ size_t ZSTD_compressBlock_doubleFast_extDict_generic( size_t mLength; hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */ - if (((ZSTD_index_overlap_check(prefixStartIndex, repIndex)) + if (((ZSTD_index_overlap_check(prefixStartIndex, repIndex)) & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; From 8e5823b65c6d0d1eb1c07be8428f427df5892d3a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 11 Oct 2024 15:38:12 -0700 Subject: [PATCH 087/405] rename variable name findMatch -> matchFound since it's a test, as opposed to an active search operation. suggested by @terrelln --- lib/compress/zstd_fast.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 691bedc1e..e7edf9490 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -105,7 +105,7 @@ ZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 matc /* Array of ~random data, should have low probability of matching data. * Load from here if the index is invalid. * Used to avoid unpredictable branches. */ - static const BYTE dummy[] = {0x12,0x34,0x56,0x78 }; + static const BYTE dummy[] = {0x12,0x34,0x56,0x78}; /* currentIdx >= lowLimit is a (somewhat) unpredictable branch. * However expression below compiles into conditional move. @@ -232,7 +232,7 @@ size_t ZSTD_compressBlock_fast_noDict_generic( size_t step; const BYTE* nextStep; const size_t kStepIncr = (1 << (kSearchStrength - 1)); - const ZSTD_match4Found findMatch = useCmov ? ZSTD_match4Found_cmov : ZSTD_match4Found_branch; + const ZSTD_match4Found matchFound = useCmov ? ZSTD_match4Found_cmov : ZSTD_match4Found_branch; DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); @@ -289,9 +289,7 @@ _start: /* Requires: ip0 */ goto _match; } - if (findMatch(ip0, base + matchIdx, matchIdx, prefixStartIndex)) { - /* found a match! */ - + if (matchFound(ip0, base + matchIdx, matchIdx, prefixStartIndex)) { /* Write next hash table entry (it's already calculated). * This write is known to be safe because the ip1 == ip0 + 1, * so searching will resume after ip1 */ @@ -316,17 +314,14 @@ _start: /* Requires: ip0 */ current0 = (U32)(ip0 - base); hashTable[hash0] = current0; - if (findMatch(ip0, base + matchIdx, matchIdx, prefixStartIndex)) { - /* found a match! */ - - /* Write next hash table entry; it's already calculated */ + if (matchFound(ip0, base + matchIdx, matchIdx, prefixStartIndex)) { + /* Write next hash table entry, since it's already calculated */ if (step <= 4) { /* Avoid writing an index if it's >= position where search will resume. * The minimum possible match has length 4, so search can resume at ip0 + 4. */ hashTable[hash1] = (U32)(ip1 - base); } - goto _offset; } From 1024aa9252ff02ebc03511a2c0311957511d0be9 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 11 Oct 2024 16:24:25 -0700 Subject: [PATCH 088/405] attempt to make 32-bit tests faster this is the longest CI test, reaching ~40mn on last PR --- .github/workflows/dev-long-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index d9f074369..3c2d1183b 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -50,7 +50,7 @@ jobs: run: | sudo apt-get -qqq update make libc6install - CFLAGS="-m32" make test + CFLAGS="-m32 -O1" make test V=1 no-intrinsics-fuzztest: runs-on: ubuntu-latest From 6f2e29a234c9f9ca63f1dd2748933a03f03ac731 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 11 Oct 2024 17:30:55 -0700 Subject: [PATCH 089/405] measure if -O2 makes the test complete faster --- .github/workflows/dev-long-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index 3c2d1183b..e4564c1d8 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -46,11 +46,11 @@ jobs: READFROMBLOCKDEVICE: 1 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: make test + - name: make test # note: make -j test seems to break when associated with `-m32` run: | sudo apt-get -qqq update make libc6install - CFLAGS="-m32 -O1" make test V=1 + CFLAGS="-m32 -O2" make test V=1 no-intrinsics-fuzztest: runs-on: ubuntu-latest From e6740355e35fa5695cb606e7bbda41b595175b3a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 11 Oct 2024 18:01:28 -0700 Subject: [PATCH 090/405] attempt parallel test running with -j --- .github/workflows/dev-long-tests.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index e4564c1d8..deb5242b0 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -46,11 +46,12 @@ jobs: READFROMBLOCKDEVICE: 1 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: make test # note: make -j test seems to break when associated with `-m32` + - name: make test # note: `make -j test success` seems to require a clean state run: | sudo apt-get -qqq update make libc6install - CFLAGS="-m32 -O2" make test V=1 + make clean + CFLAGS="-m32 -O2" make -j test V=1 no-intrinsics-fuzztest: runs-on: ubuntu-latest From e63896eb5844cb246aad7959ab208aa0a8f152bd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 15 Oct 2024 17:46:01 -0700 Subject: [PATCH 091/405] small dictionary compression speed improvement not as good as small-blocks improvement, but generally positive. --- lib/compress/zstd_fast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index e7edf9490..5373e3640 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -597,8 +597,8 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( } } - if (matchIndex > prefixStartIndex && MEM_read32(match) == MEM_read32(ip0)) { - /* found a regular match */ + if (ZSTD_match4Found_cmov(ip0, match, matchIndex, prefixStartIndex)) { + /* found a regular match of size >= 4 */ U32 const offset = (U32) (ip0 - match); mLength = ZSTD_count(ip0 + 4, match + 4, iend) + 4; while (((ip0 > anchor) & (match > prefixStart)) From c2abfc5ba40b2c7863080c937b728fb902b9cb5b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 15 Oct 2024 17:58:33 -0700 Subject: [PATCH 092/405] minor improvement to level 3 dictionary compression ratio --- lib/compress/zstd_double_fast.c | 45 +++++++++++++++------------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index c04010b11..e2b3b4a14 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -140,7 +140,6 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( U32 idxl1; /* the long match index for ip1 */ const BYTE* matchl0; /* the long match for ip */ - const BYTE* matchl0_safe; /* matchl0 or safe address */ const BYTE* matchs0; /* the short match for ip */ const BYTE* matchl1; /* the long match for ip1 */ const BYTE* matchs0_safe; /* matchs0 or safe address */ @@ -201,15 +200,15 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic( * However expression below complies into conditional move. Since * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex * if there is a match, all branches become predictable. */ - matchl0_safe = ZSTD_selectAddr(idxl0, prefixLowestIndex, matchl0, &dummy[0]); + { const BYTE* const matchl0_safe = ZSTD_selectAddr(idxl0, prefixLowestIndex, matchl0, &dummy[0]); - /* check prefix long match */ - if (MEM_read64(matchl0_safe) == MEM_read64(ip) && matchl0_safe == matchl0) { - mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8; - offset = (U32)(ip-matchl0); - while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */ - goto _match_found; - } + /* check prefix long match */ + if (MEM_read64(matchl0_safe) == MEM_read64(ip) && matchl0_safe == matchl0) { + mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8; + offset = (U32)(ip-matchl0); + while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */ + goto _match_found; + } } idxl1 = hashLong[hl1]; matchl1 = base + idxl1; @@ -412,14 +411,12 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( goto _match_stored; } - if (matchIndexL > prefixLowestIndex) { + if ((matchIndexL >= prefixLowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) { /* check prefix long match */ - if (MEM_read64(matchLong) == MEM_read64(ip)) { - mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8; - offset = (U32)(ip-matchLong); - while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ - goto _match_found; - } + mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8; + offset = (U32)(ip-matchLong); + while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ + goto _match_found; } else if (dictTagsMatchL) { /* check dictMatchState long match */ U32 const dictMatchIndexL = dictMatchIndexAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS; @@ -434,7 +431,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( } } if (matchIndexS > prefixLowestIndex) { - /* check prefix short match */ + /* short match candidate */ if (MEM_read32(match) == MEM_read32(ip)) { goto _search_next_long; } @@ -464,14 +461,12 @@ _search_next_long: hashLong[hl3] = curr + 1; /* check prefix long +1 match */ - if (matchIndexL3 > prefixLowestIndex) { - if (MEM_read64(matchL3) == MEM_read64(ip+1)) { - mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8; - ip++; - offset = (U32)(ip-matchL3); - while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */ - goto _match_found; - } + if ((matchIndexL3 >= prefixLowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1))) { + mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8; + ip++; + offset = (U32)(ip-matchL3); + while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */ + goto _match_found; } else if (dictTagsMatchL3) { /* check dict long +1 match */ U32 const dictMatchIndexL3 = dictMatchIndexAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS; From 730d2dce41800d2850726cdb0eefbf5fcb10b3de Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 15 Oct 2024 18:44:40 -0700 Subject: [PATCH 093/405] fix test --- tests/fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index f7bdae90e..ead3cc8dd 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2450,7 +2450,7 @@ static int basicUnitTests(U32 const seed, double compressibility) 3742, 3675, 3674, 3665, 3664, 3663, 3662, 3661, 3660, 3660, 3660, 3660, 3660 }; - size_t const target_wdict_cSize[22+1] = { 2830, 2896, 2893, 2820, 2940, + size_t const target_wdict_cSize[22+1] = { 2830, 2896, 2893, 2840, 2950, 2950, 2950, 2925, 2900, 2892, 2910, 2910, 2910, 2780, 2775, 2765, 2760, 2755, 2754, 2753, From 632677516616434c312d2fff2d84dcf0c9b78012 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 16 Oct 2024 12:13:57 -0700 Subject: [PATCH 094/405] slightly improved compression ratio at levels 3 & 4 The compression ratio benefits are small but consistent, i.e. always positive. On `silesia.tar` corpus, this modification saves ~75 KB at level 3. The measured speed cost is negligible, i.e. below noise level, between 0 and -1%. --- lib/compress/zstd_double_fast.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index e2b3b4a14..72b541ea6 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -252,19 +252,23 @@ _cleanup: _search_next_long: - /* check prefix long +1 match */ + /* short match found: let's check for a longer one */ + mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4; + + /* check long match at +1 position */ if (idxl1 > prefixLowestIndex) { if (MEM_read64(matchl1) == MEM_read64(ip1)) { - ip = ip1; - mLength = ZSTD_count(ip+8, matchl1+8, iend) + 8; - offset = (U32)(ip-matchl1); - while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */ - goto _match_found; - } + size_t const llen = ZSTD_count(ip1+8, matchl1+8, iend) + 8; + if (llen > mLength) { + ip = ip1; + mLength = llen; + offset = (U32)(ip-matchl1); + while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */ + goto _match_found; + } } } - /* if no long +1 match, explore the short match we found */ - mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4; + /* validate short match previously found */ offset = (U32)(ip - matchs0); while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* catch up */ From 61d08b0e42e7397af479ca9d1b66fe7235508f34 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 16 Oct 2024 12:55:52 -0700 Subject: [PATCH 095/405] fix test a margin of 4 is insufficient to guarantee compression success. --- tests/zstreamtest.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 8625b4a23..2c25adf3c 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -758,7 +758,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) } streaming2KSize = ZSTD_sizeof_DCtx(dctx); CHECK_Z(streaming2KSize); - + CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters)); inBuff.pos = 0; outBuff.pos = 0; @@ -769,7 +769,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) } streamingSize = ZSTD_sizeof_DCtx(dctx); CHECK_Z(streamingSize); - + CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024)); inBuff.pos = 0; outBuff.pos = 0; @@ -884,7 +884,8 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : ZSTD_compress2() uses stable input and output : ", testNb++); CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize)); CHECK(!(cSize < ZSTD_compressBound(CNBufferSize)), "cSize too large for test"); - CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, cSize + 4, CNBuffer, CNBufferSize)); + /* check that compression fits with just a 8-bytes margin */ + CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, cSize+8, CNBuffer, CNBufferSize)); CHECK_Z(cctxSize1 = ZSTD_sizeof_CCtx(cctx)); /* @cctxSize2 : sizeof_CCtx when doing full streaming (no stable in/out) */ { ZSTD_CCtx* const cctx2 = ZSTD_createCCtx(); @@ -2503,7 +2504,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) // Validate CHECK(outBuf.pos != srcSize, "decompressed size must match"); CHECK(memcmp(src, val, srcSize) != 0, "decompressed data must match"); - + // Cleanup free(src); free(dst); free(val); ZSTD_freeCCtx(cctx); From 47d4f5662df83c1a84476ab6c6f7fcb1d415f4f1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 09:36:56 -0700 Subject: [PATCH 096/405] rewrite code in the manner suggested by @terrelln --- lib/compress/zstd_double_fast.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 72b541ea6..50d698b37 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -254,23 +254,21 @@ _search_next_long: /* short match found: let's check for a longer one */ mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4; + offset = (U32)(ip - matchs0); /* check long match at +1 position */ - if (idxl1 > prefixLowestIndex) { - if (MEM_read64(matchl1) == MEM_read64(ip1)) { - size_t const llen = ZSTD_count(ip1+8, matchl1+8, iend) + 8; - if (llen > mLength) { - ip = ip1; - mLength = llen; - offset = (U32)(ip-matchl1); - while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */ - goto _match_found; - } } + if ((idxl1 > prefixLowestIndex) && (MEM_read64(matchl1) == MEM_read64(ip1))) { + size_t const l1len = ZSTD_count(ip1+8, matchl1+8, iend) + 8; + if (l1len > mLength) { + /* use the long match instead */ + ip = ip1; + mLength = l1len; + offset = (U32)(ip-matchl1); + matchs0 = matchl1; + } } - /* validate short match previously found */ - offset = (U32)(ip - matchs0); - while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* catch up */ + while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* complete backward */ /* fall-through */ From ff8e98bebee144321d7c39234deff43f9211dfbc Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 09:45:16 -0700 Subject: [PATCH 097/405] enable regression tests at pull request time was transferred from circleci, but was only triggered on push into dev, i.e. after pull request is merged. --- .github/workflows/commit.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 25d8c52f9..ca5a85b8f 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -3,7 +3,12 @@ on: push: branches: - dev + pull_request: + branches: + - dev + permissions: read-all + jobs: short-tests-0: runs-on: ubuntu-latest @@ -27,6 +32,7 @@ jobs: make -j regressiontest; make clean make shortest; make clean make cxxtest; make clean + short-tests-1: runs-on: ubuntu-latest services: @@ -49,6 +55,7 @@ jobs: make aarch64build V=1; make clean make -C tests test-legacy test-longmatch; make clean make -C lib libzstd-nomt; make clean + regression-test: runs-on: ubuntu-latest services: From 41d870fbbf594c1ee1c0ac4113d1278ebf8301da Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 10:50:28 -0700 Subject: [PATCH 098/405] updated regression tests results --- tests/fuzz/.gitignore | 2 + tests/regression/results.csv | 604 +++++++++++++++++------------------ 2 files changed, 304 insertions(+), 302 deletions(-) diff --git a/tests/fuzz/.gitignore b/tests/fuzz/.gitignore index 28f2b8da4..b88ecb4ea 100644 --- a/tests/fuzz/.gitignore +++ b/tests/fuzz/.gitignore @@ -23,6 +23,8 @@ fuzz-*.log rt_lib_* d_lib_* crash-* +decompress_cross_format +generate_sequences # misc trace diff --git a/tests/regression/results.csv b/tests/regression/results.csv index fc3fbe7c7..e39abd66d 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -2,10 +2,10 @@ Data, Config, Method, silesia.tar, level -5, compress simple, 6861055 silesia.tar, level -3, compress simple, 6505483 silesia.tar, level -1, compress simple, 6179047 -silesia.tar, level 0, compress simple, 4854086 +silesia.tar, level 0, compress simple, 4851407 silesia.tar, level 1, compress simple, 5327717 -silesia.tar, level 3, compress simple, 4854086 -silesia.tar, level 4, compress simple, 4791503 +silesia.tar, level 3, compress simple, 4851407 +silesia.tar, level 4, compress simple, 4788821 silesia.tar, level 5, compress simple, 4679004 silesia.tar, level 6, compress simple, 4614561 silesia.tar, level 7, compress simple, 4579828 @@ -13,16 +13,16 @@ silesia.tar, level 9, compress silesia.tar, level 13, compress simple, 4502956 silesia.tar, level 16, compress simple, 4360385 silesia.tar, level 19, compress simple, 4260939 -silesia.tar, uncompressed literals, compress simple, 4854086 +silesia.tar, uncompressed literals, compress simple, 4851407 silesia.tar, uncompressed literals optimal, compress simple, 4260939 silesia.tar, huffman literals, compress simple, 6179047 github.tar, level -5, compress simple, 52115 github.tar, level -3, compress simple, 45678 github.tar, level -1, compress simple, 42560 -github.tar, level 0, compress simple, 38831 +github.tar, level 0, compress simple, 38884 github.tar, level 1, compress simple, 39200 -github.tar, level 3, compress simple, 38831 -github.tar, level 4, compress simple, 38893 +github.tar, level 3, compress simple, 38884 +github.tar, level 4, compress simple, 38880 github.tar, level 5, compress simple, 39651 github.tar, level 6, compress simple, 39282 github.tar, level 7, compress simple, 38005 @@ -30,16 +30,16 @@ github.tar, level 9, compress github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 github.tar, level 19, compress simple, 32262 -github.tar, uncompressed literals, compress simple, 38831 +github.tar, uncompressed literals, compress simple, 38884 github.tar, uncompressed literals optimal, compress simple, 32262 github.tar, huffman literals, compress simple, 42560 silesia, level -5, compress cctx, 6857372 silesia, level -3, compress cctx, 6503412 silesia, level -1, compress cctx, 6172202 -silesia, level 0, compress cctx, 4842075 +silesia, level 0, compress cctx, 4839431 silesia, level 1, compress cctx, 5306632 -silesia, level 3, compress cctx, 4842075 -silesia, level 4, compress cctx, 4779186 +silesia, level 3, compress cctx, 4839431 +silesia, level 4, compress cctx, 4776557 silesia, level 5, compress cctx, 4667668 silesia, level 6, compress cctx, 4604351 silesia, level 7, compress cctx, 4570271 @@ -47,28 +47,28 @@ silesia, level 9, compress silesia, level 13, compress cctx, 4493990 silesia, level 16, compress cctx, 4359652 silesia, level 19, compress cctx, 4266582 -silesia, long distance mode, compress cctx, 4842075 -silesia, multithreaded, compress cctx, 4842075 -silesia, multithreaded long distance mode, compress cctx, 4842075 -silesia, small window log, compress cctx, 7082951 +silesia, long distance mode, compress cctx, 4839431 +silesia, multithreaded, compress cctx, 4839431 +silesia, multithreaded long distance mode, compress cctx, 4839431 +silesia, small window log, compress cctx, 7082907 silesia, small hash log, compress cctx, 6526141 silesia, small chain log, compress cctx, 4912197 silesia, explicit params, compress cctx, 4794318 -silesia, uncompressed literals, compress cctx, 4842075 +silesia, uncompressed literals, compress cctx, 4839431 silesia, uncompressed literals optimal, compress cctx, 4266582 silesia, huffman literals, compress cctx, 6172202 -silesia, multithreaded with advanced params, compress cctx, 4842075 +silesia, multithreaded with advanced params, compress cctx, 4839431 github, level -5, compress cctx, 204407 github, level -5 with dict, compress cctx, 47581 github, level -3, compress cctx, 193253 github, level -3 with dict, compress cctx, 43043 github, level -1, compress cctx, 175468 github, level -1 with dict, compress cctx, 42044 -github, level 0, compress cctx, 136332 +github, level 0, compress cctx, 136331 github, level 0 with dict, compress cctx, 41534 github, level 1, compress cctx, 142365 github, level 1 with dict, compress cctx, 41715 -github, level 3, compress cctx, 136332 +github, level 3, compress cctx, 136331 github, level 3 with dict, compress cctx, 41534 github, level 4, compress cctx, 136199 github, level 4 with dict, compress cctx, 41725 @@ -93,17 +93,17 @@ github, small window log, compress github, small hash log, compress cctx, 138949 github, small chain log, compress cctx, 139242 github, explicit params, compress cctx, 140932 -github, uncompressed literals, compress cctx, 136332 +github, uncompressed literals, compress cctx, 136331 github, uncompressed literals optimal, compress cctx, 132879 github, huffman literals, compress cctx, 175468 github, multithreaded with advanced params, compress cctx, 141069 silesia, level -5, zstdcli, 6857420 silesia, level -3, zstdcli, 6503460 silesia, level -1, zstdcli, 6172250 -silesia, level 0, zstdcli, 4842123 +silesia, level 0, zstdcli, 4839479 silesia, level 1, zstdcli, 5306680 -silesia, level 3, zstdcli, 4842123 -silesia, level 4, zstdcli, 4779234 +silesia, level 3, zstdcli, 4839479 +silesia, level 4, zstdcli, 4776605 silesia, level 5, zstdcli, 4667716 silesia, level 6, zstdcli, 4604399 silesia, level 7, zstdcli, 4570319 @@ -111,24 +111,24 @@ silesia, level 9, zstdcli, silesia, level 13, zstdcli, 4494038 silesia, level 16, zstdcli, 4359700 silesia, level 19, zstdcli, 4266630 -silesia, long distance mode, zstdcli, 4833785 -silesia, multithreaded, zstdcli, 4842123 -silesia, multithreaded long distance mode, zstdcli, 4833785 -silesia, small window log, zstdcli, 7095048 +silesia, long distance mode, zstdcli, 4831224 +silesia, multithreaded, zstdcli, 4839479 +silesia, multithreaded long distance mode, zstdcli, 4831224 +silesia, small window log, zstdcli, 7094528 silesia, small hash log, zstdcli, 6526189 silesia, small chain log, zstdcli, 4912245 silesia, explicit params, zstdcli, 4795840 -silesia, uncompressed literals, zstdcli, 5120614 +silesia, uncompressed literals, zstdcli, 5117005 silesia, uncompressed literals optimal, zstdcli, 4316928 silesia, huffman literals, zstdcli, 5321417 -silesia, multithreaded with advanced params, zstdcli, 5120614 +silesia, multithreaded with advanced params, zstdcli, 5117005 silesia.tar, level -5, zstdcli, 6862049 silesia.tar, level -3, zstdcli, 6506509 silesia.tar, level -1, zstdcli, 6179789 -silesia.tar, level 0, zstdcli, 4854164 +silesia.tar, level 0, zstdcli, 4851482 silesia.tar, level 1, zstdcli, 5329010 -silesia.tar, level 3, zstdcli, 4854164 -silesia.tar, level 4, zstdcli, 4792352 +silesia.tar, level 3, zstdcli, 4851482 +silesia.tar, level 4, zstdcli, 4789729 silesia.tar, level 5, zstdcli, 4679860 silesia.tar, level 6, zstdcli, 4615355 silesia.tar, level 7, zstdcli, 4581791 @@ -136,32 +136,32 @@ silesia.tar, level 9, zstdcli, silesia.tar, level 13, zstdcli, 4502960 silesia.tar, level 16, zstdcli, 4360389 silesia.tar, level 19, zstdcli, 4260943 -silesia.tar, no source size, zstdcli, 4854160 -silesia.tar, long distance mode, zstdcli, 4845745 -silesia.tar, multithreaded, zstdcli, 4854164 -silesia.tar, multithreaded long distance mode, zstdcli, 4845745 -silesia.tar, small window log, zstdcli, 7100701 +silesia.tar, no source size, zstdcli, 4851478 +silesia.tar, long distance mode, zstdcli, 4843159 +silesia.tar, multithreaded, zstdcli, 4851482 +silesia.tar, multithreaded long distance mode, zstdcli, 4843159 +silesia.tar, small window log, zstdcli, 7100110 silesia.tar, small hash log, zstdcli, 6529264 silesia.tar, small chain log, zstdcli, 4917022 silesia.tar, explicit params, zstdcli, 4821112 -silesia.tar, uncompressed literals, zstdcli, 5122571 +silesia.tar, uncompressed literals, zstdcli, 5118944 silesia.tar, uncompressed literals optimal, zstdcli, 4308455 silesia.tar, huffman literals, zstdcli, 5342074 -silesia.tar, multithreaded with advanced params, zstdcli, 5122571 +silesia.tar, multithreaded with advanced params, zstdcli, 5118944 github, level -5, zstdcli, 206407 github, level -5 with dict, zstdcli, 47832 github, level -3, zstdcli, 195253 github, level -3 with dict, zstdcli, 46671 github, level -1, zstdcli, 177468 github, level -1 with dict, zstdcli, 43825 -github, level 0, zstdcli, 138332 -github, level 0 with dict, zstdcli, 43148 +github, level 0, zstdcli, 138331 +github, level 0 with dict, zstdcli, 43118 github, level 1, zstdcli, 144365 github, level 1 with dict, zstdcli, 43266 -github, level 3, zstdcli, 138332 -github, level 3 with dict, zstdcli, 43148 +github, level 3, zstdcli, 138331 +github, level 3 with dict, zstdcli, 43118 github, level 4, zstdcli, 138199 -github, level 4 with dict, zstdcli, 43251 +github, level 4 with dict, zstdcli, 43229 github, level 5, zstdcli, 137121 github, level 5 with dict, zstdcli, 40728 github, level 6, zstdcli, 137122 @@ -176,30 +176,30 @@ github, level 16, zstdcli, github, level 16 with dict, zstdcli, 39902 github, level 19, zstdcli, 134879 github, level 19 with dict, zstdcli, 39916 -github, long distance mode, zstdcli, 138332 -github, multithreaded, zstdcli, 138332 -github, multithreaded long distance mode, zstdcli, 138332 -github, small window log, zstdcli, 138332 +github, long distance mode, zstdcli, 138331 +github, multithreaded, zstdcli, 138331 +github, multithreaded long distance mode, zstdcli, 138331 +github, small window log, zstdcli, 138331 github, small hash log, zstdcli, 137590 github, small chain log, zstdcli, 138341 github, explicit params, zstdcli, 136197 -github, uncompressed literals, zstdcli, 167911 +github, uncompressed literals, zstdcli, 167909 github, uncompressed literals optimal, zstdcli, 154667 github, huffman literals, zstdcli, 144365 -github, multithreaded with advanced params, zstdcli, 167911 +github, multithreaded with advanced params, zstdcli, 167909 github.tar, level -5, zstdcli, 52119 github.tar, level -5 with dict, zstdcli, 51101 github.tar, level -3, zstdcli, 45682 github.tar, level -3 with dict, zstdcli, 44738 github.tar, level -1, zstdcli, 42564 github.tar, level -1 with dict, zstdcli, 41357 -github.tar, level 0, zstdcli, 38835 +github.tar, level 0, zstdcli, 38888 github.tar, level 0 with dict, zstdcli, 37999 github.tar, level 1, zstdcli, 39204 github.tar, level 1 with dict, zstdcli, 38123 -github.tar, level 3, zstdcli, 38835 +github.tar, level 3, zstdcli, 38888 github.tar, level 3 with dict, zstdcli, 37999 -github.tar, level 4, zstdcli, 38897 +github.tar, level 4, zstdcli, 38884 github.tar, level 4 with dict, zstdcli, 37952 github.tar, level 5, zstdcli, 39655 github.tar, level 5 with dict, zstdcli, 39073 @@ -215,26 +215,26 @@ github.tar, level 16, zstdcli, github.tar, level 16 with dict, zstdcli, 33379 github.tar, level 19, zstdcli, 32266 github.tar, level 19 with dict, zstdcli, 32705 -github.tar, no source size, zstdcli, 38832 -github.tar, no source size with dict, zstdcli, 38004 -github.tar, long distance mode, zstdcli, 40236 -github.tar, multithreaded, zstdcli, 38835 -github.tar, multithreaded long distance mode, zstdcli, 40236 -github.tar, small window log, zstdcli, 198544 +github.tar, no source size, zstdcli, 38885 +github.tar, no source size with dict, zstdcli, 38115 +github.tar, long distance mode, zstdcli, 40227 +github.tar, multithreaded, zstdcli, 38888 +github.tar, multithreaded long distance mode, zstdcli, 40227 +github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 github.tar, explicit params, zstdcli, 41385 -github.tar, uncompressed literals, zstdcli, 41529 +github.tar, uncompressed literals, zstdcli, 41566 github.tar, uncompressed literals optimal, zstdcli, 35360 github.tar, huffman literals, zstdcli, 38857 -github.tar, multithreaded with advanced params, zstdcli, 41529 +github.tar, multithreaded with advanced params, zstdcli, 41566 silesia, level -5, advanced one pass, 6857372 silesia, level -3, advanced one pass, 6503412 silesia, level -1, advanced one pass, 6172202 -silesia, level 0, advanced one pass, 4842075 +silesia, level 0, advanced one pass, 4839431 silesia, level 1, advanced one pass, 5306632 -silesia, level 3, advanced one pass, 4842075 -silesia, level 4, advanced one pass, 4779186 +silesia, level 3, advanced one pass, 4839431 +silesia, level 4, advanced one pass, 4776557 silesia, level 5 row 1, advanced one pass, 4667668 silesia, level 5 row 2, advanced one pass, 4670326 silesia, level 5, advanced one pass, 4667668 @@ -250,25 +250,25 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced one pass, 4493990 silesia, level 16, advanced one pass, 4359652 silesia, level 19, advanced one pass, 4266582 -silesia, no source size, advanced one pass, 4842075 -silesia, long distance mode, advanced one pass, 4833710 -silesia, multithreaded, advanced one pass, 4842075 -silesia, multithreaded long distance mode, advanced one pass, 4833737 -silesia, small window log, advanced one pass, 7095000 +silesia, no source size, advanced one pass, 4839431 +silesia, long distance mode, advanced one pass, 4831158 +silesia, multithreaded, advanced one pass, 4839431 +silesia, multithreaded long distance mode, advanced one pass, 4831176 +silesia, small window log, advanced one pass, 7094480 silesia, small hash log, advanced one pass, 6526141 silesia, small chain log, advanced one pass, 4912197 silesia, explicit params, advanced one pass, 4795840 -silesia, uncompressed literals, advanced one pass, 5120566 +silesia, uncompressed literals, advanced one pass, 5116957 silesia, uncompressed literals optimal, advanced one pass, 4316880 silesia, huffman literals, advanced one pass, 5321369 -silesia, multithreaded with advanced params, advanced one pass, 5120566 +silesia, multithreaded with advanced params, advanced one pass, 5116957 silesia.tar, level -5, advanced one pass, 6861055 silesia.tar, level -3, advanced one pass, 6505483 silesia.tar, level -1, advanced one pass, 6179047 -silesia.tar, level 0, advanced one pass, 4854086 +silesia.tar, level 0, advanced one pass, 4851407 silesia.tar, level 1, advanced one pass, 5327717 -silesia.tar, level 3, advanced one pass, 4854086 -silesia.tar, level 4, advanced one pass, 4791503 +silesia.tar, level 3, advanced one pass, 4851407 +silesia.tar, level 4, advanced one pass, 4788821 silesia.tar, level 5 row 1, advanced one pass, 4679004 silesia.tar, level 5 row 2, advanced one pass, 4682334 silesia.tar, level 5, advanced one pass, 4679004 @@ -284,28 +284,28 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced one pass, 4502956 silesia.tar, level 16, advanced one pass, 4360385 silesia.tar, level 19, advanced one pass, 4260939 -silesia.tar, no source size, advanced one pass, 4854086 -silesia.tar, long distance mode, advanced one pass, 4840452 -silesia.tar, multithreaded, advanced one pass, 4854160 -silesia.tar, multithreaded long distance mode, advanced one pass, 4845741 -silesia.tar, small window log, advanced one pass, 7100655 +silesia.tar, no source size, advanced one pass, 4851407 +silesia.tar, long distance mode, advanced one pass, 4837775 +silesia.tar, multithreaded, advanced one pass, 4851478 +silesia.tar, multithreaded long distance mode, advanced one pass, 4843155 +silesia.tar, small window log, advanced one pass, 7100064 silesia.tar, small hash log, advanced one pass, 6529206 silesia.tar, small chain log, advanced one pass, 4917041 silesia.tar, explicit params, advanced one pass, 4807274 -silesia.tar, uncompressed literals, advanced one pass, 5122473 +silesia.tar, uncompressed literals, advanced one pass, 5118848 silesia.tar, uncompressed literals optimal, advanced one pass, 4308451 silesia.tar, huffman literals, advanced one pass, 5341705 -silesia.tar, multithreaded with advanced params, advanced one pass, 5122567 +silesia.tar, multithreaded with advanced params, advanced one pass, 5118940 github, level -5, advanced one pass, 204407 github, level -5 with dict, advanced one pass, 45832 github, level -3, advanced one pass, 193253 github, level -3 with dict, advanced one pass, 44671 github, level -1, advanced one pass, 175468 github, level -1 with dict, advanced one pass, 41825 -github, level 0, advanced one pass, 136332 -github, level 0 with dict, advanced one pass, 41148 -github, level 0 with dict dms, advanced one pass, 41148 -github, level 0 with dict dds, advanced one pass, 41148 +github, level 0, advanced one pass, 136331 +github, level 0 with dict, advanced one pass, 41118 +github, level 0 with dict dms, advanced one pass, 41118 +github, level 0 with dict dds, advanced one pass, 41118 github, level 0 with dict copy, advanced one pass, 41124 github, level 0 with dict load, advanced one pass, 41847 github, level 1, advanced one pass, 142365 @@ -314,16 +314,16 @@ github, level 1 with dict dms, advanced github, level 1 with dict dds, advanced one pass, 41266 github, level 1 with dict copy, advanced one pass, 41279 github, level 1 with dict load, advanced one pass, 43331 -github, level 3, advanced one pass, 136332 -github, level 3 with dict, advanced one pass, 41148 -github, level 3 with dict dms, advanced one pass, 41148 -github, level 3 with dict dds, advanced one pass, 41148 +github, level 3, advanced one pass, 136331 +github, level 3 with dict, advanced one pass, 41118 +github, level 3 with dict dms, advanced one pass, 41118 +github, level 3 with dict dds, advanced one pass, 41118 github, level 3 with dict copy, advanced one pass, 41124 github, level 3 with dict load, advanced one pass, 41847 github, level 4, advanced one pass, 136199 -github, level 4 with dict, advanced one pass, 41251 -github, level 4 with dict dms, advanced one pass, 41251 -github, level 4 with dict dds, advanced one pass, 41251 +github, level 4 with dict, advanced one pass, 41229 +github, level 4 with dict dms, advanced one pass, 41229 +github, level 4 with dict dds, advanced one pass, 41229 github, level 4 with dict copy, advanced one pass, 41216 github, level 4 with dict load, advanced one pass, 41548 github, level 5 row 1, advanced one pass, 134584 @@ -408,29 +408,29 @@ github, level 19 with dict dms, advanced github, level 19 with dict dds, advanced one pass, 37916 github, level 19 with dict copy, advanced one pass, 37906 github, level 19 with dict load, advanced one pass, 39770 -github, no source size, advanced one pass, 136332 -github, no source size with dict, advanced one pass, 41148 -github, long distance mode, advanced one pass, 136332 -github, multithreaded, advanced one pass, 136332 -github, multithreaded long distance mode, advanced one pass, 136332 -github, small window log, advanced one pass, 136332 +github, no source size, advanced one pass, 136331 +github, no source size with dict, advanced one pass, 41118 +github, long distance mode, advanced one pass, 136331 +github, multithreaded, advanced one pass, 136331 +github, multithreaded long distance mode, advanced one pass, 136331 +github, small window log, advanced one pass, 136331 github, small hash log, advanced one pass, 135590 github, small chain log, advanced one pass, 136341 github, explicit params, advanced one pass, 137727 -github, uncompressed literals, advanced one pass, 165911 +github, uncompressed literals, advanced one pass, 165909 github, uncompressed literals optimal, advanced one pass, 152667 github, huffman literals, advanced one pass, 142365 -github, multithreaded with advanced params, advanced one pass, 165911 +github, multithreaded with advanced params, advanced one pass, 165909 github.tar, level -5, advanced one pass, 52115 github.tar, level -5 with dict, advanced one pass, 51097 github.tar, level -3, advanced one pass, 45678 github.tar, level -3 with dict, advanced one pass, 44734 github.tar, level -1, advanced one pass, 42560 github.tar, level -1 with dict, advanced one pass, 41353 -github.tar, level 0, advanced one pass, 38831 +github.tar, level 0, advanced one pass, 38884 github.tar, level 0 with dict, advanced one pass, 37995 -github.tar, level 0 with dict dms, advanced one pass, 38003 -github.tar, level 0 with dict dds, advanced one pass, 38003 +github.tar, level 0 with dict dms, advanced one pass, 38114 +github.tar, level 0 with dict dds, advanced one pass, 38114 github.tar, level 0 with dict copy, advanced one pass, 37995 github.tar, level 0 with dict load, advanced one pass, 37956 github.tar, level 1, advanced one pass, 39200 @@ -439,16 +439,16 @@ github.tar, level 1 with dict dms, advanced github.tar, level 1 with dict dds, advanced one pass, 38406 github.tar, level 1 with dict copy, advanced one pass, 38119 github.tar, level 1 with dict load, advanced one pass, 38364 -github.tar, level 3, advanced one pass, 38831 +github.tar, level 3, advanced one pass, 38884 github.tar, level 3 with dict, advanced one pass, 37995 -github.tar, level 3 with dict dms, advanced one pass, 38003 -github.tar, level 3 with dict dds, advanced one pass, 38003 +github.tar, level 3 with dict dms, advanced one pass, 38114 +github.tar, level 3 with dict dds, advanced one pass, 38114 github.tar, level 3 with dict copy, advanced one pass, 37995 github.tar, level 3 with dict load, advanced one pass, 37956 -github.tar, level 4, advanced one pass, 38893 +github.tar, level 4, advanced one pass, 38880 github.tar, level 4 with dict, advanced one pass, 37948 -github.tar, level 4 with dict dms, advanced one pass, 37954 -github.tar, level 4 with dict dds, advanced one pass, 37954 +github.tar, level 4 with dict dms, advanced one pass, 37995 +github.tar, level 4 with dict dds, advanced one pass, 37995 github.tar, level 4 with dict copy, advanced one pass, 37948 github.tar, level 4 with dict load, advanced one pass, 37927 github.tar, level 5 row 1, advanced one pass, 39651 @@ -533,26 +533,26 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass, 32565 github.tar, level 19 with dict copy, advanced one pass, 32701 github.tar, level 19 with dict load, advanced one pass, 32428 -github.tar, no source size, advanced one pass, 38831 +github.tar, no source size, advanced one pass, 38884 github.tar, no source size with dict, advanced one pass, 37995 -github.tar, long distance mode, advanced one pass, 40252 -github.tar, multithreaded, advanced one pass, 38831 -github.tar, multithreaded long distance mode, advanced one pass, 40232 -github.tar, small window log, advanced one pass, 198540 +github.tar, long distance mode, advanced one pass, 40242 +github.tar, multithreaded, advanced one pass, 38884 +github.tar, multithreaded long distance mode, advanced one pass, 40223 +github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 github.tar, explicit params, advanced one pass, 41385 -github.tar, uncompressed literals, advanced one pass, 41525 +github.tar, uncompressed literals, advanced one pass, 41562 github.tar, uncompressed literals optimal, advanced one pass, 35356 github.tar, huffman literals, advanced one pass, 38853 -github.tar, multithreaded with advanced params, advanced one pass, 41525 +github.tar, multithreaded with advanced params, advanced one pass, 41562 silesia, level -5, advanced one pass small out, 6857372 silesia, level -3, advanced one pass small out, 6503412 silesia, level -1, advanced one pass small out, 6172202 -silesia, level 0, advanced one pass small out, 4842075 +silesia, level 0, advanced one pass small out, 4839431 silesia, level 1, advanced one pass small out, 5306632 -silesia, level 3, advanced one pass small out, 4842075 -silesia, level 4, advanced one pass small out, 4779186 +silesia, level 3, advanced one pass small out, 4839431 +silesia, level 4, advanced one pass small out, 4776557 silesia, level 5 row 1, advanced one pass small out, 4667668 silesia, level 5 row 2, advanced one pass small out, 4670326 silesia, level 5, advanced one pass small out, 4667668 @@ -568,25 +568,25 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced one pass small out, 4493990 silesia, level 16, advanced one pass small out, 4359652 silesia, level 19, advanced one pass small out, 4266582 -silesia, no source size, advanced one pass small out, 4842075 -silesia, long distance mode, advanced one pass small out, 4833710 -silesia, multithreaded, advanced one pass small out, 4842075 -silesia, multithreaded long distance mode, advanced one pass small out, 4833737 -silesia, small window log, advanced one pass small out, 7095000 +silesia, no source size, advanced one pass small out, 4839431 +silesia, long distance mode, advanced one pass small out, 4831158 +silesia, multithreaded, advanced one pass small out, 4839431 +silesia, multithreaded long distance mode, advanced one pass small out, 4831176 +silesia, small window log, advanced one pass small out, 7094480 silesia, small hash log, advanced one pass small out, 6526141 silesia, small chain log, advanced one pass small out, 4912197 silesia, explicit params, advanced one pass small out, 4795840 -silesia, uncompressed literals, advanced one pass small out, 5120566 +silesia, uncompressed literals, advanced one pass small out, 5116957 silesia, uncompressed literals optimal, advanced one pass small out, 4316880 silesia, huffman literals, advanced one pass small out, 5321369 -silesia, multithreaded with advanced params, advanced one pass small out, 5120566 +silesia, multithreaded with advanced params, advanced one pass small out, 5116957 silesia.tar, level -5, advanced one pass small out, 6861055 silesia.tar, level -3, advanced one pass small out, 6505483 silesia.tar, level -1, advanced one pass small out, 6179047 -silesia.tar, level 0, advanced one pass small out, 4854086 +silesia.tar, level 0, advanced one pass small out, 4851407 silesia.tar, level 1, advanced one pass small out, 5327717 -silesia.tar, level 3, advanced one pass small out, 4854086 -silesia.tar, level 4, advanced one pass small out, 4791503 +silesia.tar, level 3, advanced one pass small out, 4851407 +silesia.tar, level 4, advanced one pass small out, 4788821 silesia.tar, level 5 row 1, advanced one pass small out, 4679004 silesia.tar, level 5 row 2, advanced one pass small out, 4682334 silesia.tar, level 5, advanced one pass small out, 4679004 @@ -602,28 +602,28 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced one pass small out, 4502956 silesia.tar, level 16, advanced one pass small out, 4360385 silesia.tar, level 19, advanced one pass small out, 4260939 -silesia.tar, no source size, advanced one pass small out, 4854086 -silesia.tar, long distance mode, advanced one pass small out, 4840452 -silesia.tar, multithreaded, advanced one pass small out, 4854160 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4845741 -silesia.tar, small window log, advanced one pass small out, 7100655 +silesia.tar, no source size, advanced one pass small out, 4851407 +silesia.tar, long distance mode, advanced one pass small out, 4837775 +silesia.tar, multithreaded, advanced one pass small out, 4851478 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4843155 +silesia.tar, small window log, advanced one pass small out, 7100064 silesia.tar, small hash log, advanced one pass small out, 6529206 silesia.tar, small chain log, advanced one pass small out, 4917041 silesia.tar, explicit params, advanced one pass small out, 4807274 -silesia.tar, uncompressed literals, advanced one pass small out, 5122473 +silesia.tar, uncompressed literals, advanced one pass small out, 5118848 silesia.tar, uncompressed literals optimal, advanced one pass small out, 4308451 silesia.tar, huffman literals, advanced one pass small out, 5341705 -silesia.tar, multithreaded with advanced params, advanced one pass small out, 5122567 +silesia.tar, multithreaded with advanced params, advanced one pass small out, 5118940 github, level -5, advanced one pass small out, 204407 github, level -5 with dict, advanced one pass small out, 45832 github, level -3, advanced one pass small out, 193253 github, level -3 with dict, advanced one pass small out, 44671 github, level -1, advanced one pass small out, 175468 github, level -1 with dict, advanced one pass small out, 41825 -github, level 0, advanced one pass small out, 136332 -github, level 0 with dict, advanced one pass small out, 41148 -github, level 0 with dict dms, advanced one pass small out, 41148 -github, level 0 with dict dds, advanced one pass small out, 41148 +github, level 0, advanced one pass small out, 136331 +github, level 0 with dict, advanced one pass small out, 41118 +github, level 0 with dict dms, advanced one pass small out, 41118 +github, level 0 with dict dds, advanced one pass small out, 41118 github, level 0 with dict copy, advanced one pass small out, 41124 github, level 0 with dict load, advanced one pass small out, 41847 github, level 1, advanced one pass small out, 142365 @@ -632,16 +632,16 @@ github, level 1 with dict dms, advanced github, level 1 with dict dds, advanced one pass small out, 41266 github, level 1 with dict copy, advanced one pass small out, 41279 github, level 1 with dict load, advanced one pass small out, 43331 -github, level 3, advanced one pass small out, 136332 -github, level 3 with dict, advanced one pass small out, 41148 -github, level 3 with dict dms, advanced one pass small out, 41148 -github, level 3 with dict dds, advanced one pass small out, 41148 +github, level 3, advanced one pass small out, 136331 +github, level 3 with dict, advanced one pass small out, 41118 +github, level 3 with dict dms, advanced one pass small out, 41118 +github, level 3 with dict dds, advanced one pass small out, 41118 github, level 3 with dict copy, advanced one pass small out, 41124 github, level 3 with dict load, advanced one pass small out, 41847 github, level 4, advanced one pass small out, 136199 -github, level 4 with dict, advanced one pass small out, 41251 -github, level 4 with dict dms, advanced one pass small out, 41251 -github, level 4 with dict dds, advanced one pass small out, 41251 +github, level 4 with dict, advanced one pass small out, 41229 +github, level 4 with dict dms, advanced one pass small out, 41229 +github, level 4 with dict dds, advanced one pass small out, 41229 github, level 4 with dict copy, advanced one pass small out, 41216 github, level 4 with dict load, advanced one pass small out, 41548 github, level 5 row 1, advanced one pass small out, 134584 @@ -726,29 +726,29 @@ github, level 19 with dict dms, advanced github, level 19 with dict dds, advanced one pass small out, 37916 github, level 19 with dict copy, advanced one pass small out, 37906 github, level 19 with dict load, advanced one pass small out, 39770 -github, no source size, advanced one pass small out, 136332 -github, no source size with dict, advanced one pass small out, 41148 -github, long distance mode, advanced one pass small out, 136332 -github, multithreaded, advanced one pass small out, 136332 -github, multithreaded long distance mode, advanced one pass small out, 136332 -github, small window log, advanced one pass small out, 136332 +github, no source size, advanced one pass small out, 136331 +github, no source size with dict, advanced one pass small out, 41118 +github, long distance mode, advanced one pass small out, 136331 +github, multithreaded, advanced one pass small out, 136331 +github, multithreaded long distance mode, advanced one pass small out, 136331 +github, small window log, advanced one pass small out, 136331 github, small hash log, advanced one pass small out, 135590 github, small chain log, advanced one pass small out, 136341 github, explicit params, advanced one pass small out, 137727 -github, uncompressed literals, advanced one pass small out, 165911 +github, uncompressed literals, advanced one pass small out, 165909 github, uncompressed literals optimal, advanced one pass small out, 152667 github, huffman literals, advanced one pass small out, 142365 -github, multithreaded with advanced params, advanced one pass small out, 165911 +github, multithreaded with advanced params, advanced one pass small out, 165909 github.tar, level -5, advanced one pass small out, 52115 github.tar, level -5 with dict, advanced one pass small out, 51097 github.tar, level -3, advanced one pass small out, 45678 github.tar, level -3 with dict, advanced one pass small out, 44734 github.tar, level -1, advanced one pass small out, 42560 github.tar, level -1 with dict, advanced one pass small out, 41353 -github.tar, level 0, advanced one pass small out, 38831 +github.tar, level 0, advanced one pass small out, 38884 github.tar, level 0 with dict, advanced one pass small out, 37995 -github.tar, level 0 with dict dms, advanced one pass small out, 38003 -github.tar, level 0 with dict dds, advanced one pass small out, 38003 +github.tar, level 0 with dict dms, advanced one pass small out, 38114 +github.tar, level 0 with dict dds, advanced one pass small out, 38114 github.tar, level 0 with dict copy, advanced one pass small out, 37995 github.tar, level 0 with dict load, advanced one pass small out, 37956 github.tar, level 1, advanced one pass small out, 39200 @@ -757,16 +757,16 @@ github.tar, level 1 with dict dms, advanced github.tar, level 1 with dict dds, advanced one pass small out, 38406 github.tar, level 1 with dict copy, advanced one pass small out, 38119 github.tar, level 1 with dict load, advanced one pass small out, 38364 -github.tar, level 3, advanced one pass small out, 38831 +github.tar, level 3, advanced one pass small out, 38884 github.tar, level 3 with dict, advanced one pass small out, 37995 -github.tar, level 3 with dict dms, advanced one pass small out, 38003 -github.tar, level 3 with dict dds, advanced one pass small out, 38003 +github.tar, level 3 with dict dms, advanced one pass small out, 38114 +github.tar, level 3 with dict dds, advanced one pass small out, 38114 github.tar, level 3 with dict copy, advanced one pass small out, 37995 github.tar, level 3 with dict load, advanced one pass small out, 37956 -github.tar, level 4, advanced one pass small out, 38893 +github.tar, level 4, advanced one pass small out, 38880 github.tar, level 4 with dict, advanced one pass small out, 37948 -github.tar, level 4 with dict dms, advanced one pass small out, 37954 -github.tar, level 4 with dict dds, advanced one pass small out, 37954 +github.tar, level 4 with dict dms, advanced one pass small out, 37995 +github.tar, level 4 with dict dds, advanced one pass small out, 37995 github.tar, level 4 with dict copy, advanced one pass small out, 37948 github.tar, level 4 with dict load, advanced one pass small out, 37927 github.tar, level 5 row 1, advanced one pass small out, 39651 @@ -851,26 +851,26 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass small out, 32565 github.tar, level 19 with dict copy, advanced one pass small out, 32701 github.tar, level 19 with dict load, advanced one pass small out, 32428 -github.tar, no source size, advanced one pass small out, 38831 +github.tar, no source size, advanced one pass small out, 38884 github.tar, no source size with dict, advanced one pass small out, 37995 -github.tar, long distance mode, advanced one pass small out, 40252 -github.tar, multithreaded, advanced one pass small out, 38831 -github.tar, multithreaded long distance mode, advanced one pass small out, 40232 -github.tar, small window log, advanced one pass small out, 198540 +github.tar, long distance mode, advanced one pass small out, 40242 +github.tar, multithreaded, advanced one pass small out, 38884 +github.tar, multithreaded long distance mode, advanced one pass small out, 40223 +github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 github.tar, explicit params, advanced one pass small out, 41385 -github.tar, uncompressed literals, advanced one pass small out, 41525 +github.tar, uncompressed literals, advanced one pass small out, 41562 github.tar, uncompressed literals optimal, advanced one pass small out, 35356 github.tar, huffman literals, advanced one pass small out, 38853 -github.tar, multithreaded with advanced params, advanced one pass small out, 41525 +github.tar, multithreaded with advanced params, advanced one pass small out, 41562 silesia, level -5, advanced streaming, 6854744 silesia, level -3, advanced streaming, 6503319 silesia, level -1, advanced streaming, 6172207 -silesia, level 0, advanced streaming, 4842075 +silesia, level 0, advanced streaming, 4839431 silesia, level 1, advanced streaming, 5306388 -silesia, level 3, advanced streaming, 4842075 -silesia, level 4, advanced streaming, 4779186 +silesia, level 3, advanced streaming, 4839431 +silesia, level 4, advanced streaming, 4776557 silesia, level 5 row 1, advanced streaming, 4667668 silesia, level 5 row 2, advanced streaming, 4670326 silesia, level 5, advanced streaming, 4667668 @@ -886,25 +886,25 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced streaming, 4493990 silesia, level 16, advanced streaming, 4359652 silesia, level 19, advanced streaming, 4266582 -silesia, no source size, advanced streaming, 4842039 -silesia, long distance mode, advanced streaming, 4833710 -silesia, multithreaded, advanced streaming, 4842075 -silesia, multithreaded long distance mode, advanced streaming, 4833737 -silesia, small window log, advanced streaming, 7111103 +silesia, no source size, advanced streaming, 4839395 +silesia, long distance mode, advanced streaming, 4831158 +silesia, multithreaded, advanced streaming, 4839431 +silesia, multithreaded long distance mode, advanced streaming, 4831176 +silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6526141 silesia, small chain log, advanced streaming, 4912197 silesia, explicit params, advanced streaming, 4795857 -silesia, uncompressed literals, advanced streaming, 5120566 +silesia, uncompressed literals, advanced streaming, 5116957 silesia, uncompressed literals optimal, advanced streaming, 4316880 silesia, huffman literals, advanced streaming, 5321370 -silesia, multithreaded with advanced params, advanced streaming, 5120566 +silesia, multithreaded with advanced params, advanced streaming, 5116957 silesia.tar, level -5, advanced streaming, 6856523 silesia.tar, level -3, advanced streaming, 6505954 silesia.tar, level -1, advanced streaming, 6179056 -silesia.tar, level 0, advanced streaming, 4859271 +silesia.tar, level 0, advanced streaming, 4858632 silesia.tar, level 1, advanced streaming, 5327708 -silesia.tar, level 3, advanced streaming, 4859271 -silesia.tar, level 4, advanced streaming, 4797470 +silesia.tar, level 3, advanced streaming, 4858632 +silesia.tar, level 4, advanced streaming, 4796895 silesia.tar, level 5 row 1, advanced streaming, 4679020 silesia.tar, level 5 row 2, advanced streaming, 4682355 silesia.tar, level 5, advanced streaming, 4679020 @@ -920,28 +920,28 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced streaming, 4502956 silesia.tar, level 16, advanced streaming, 4360385 silesia.tar, level 19, advanced streaming, 4260939 -silesia.tar, no source size, advanced streaming, 4859267 -silesia.tar, long distance mode, advanced streaming, 4840452 -silesia.tar, multithreaded, advanced streaming, 4854160 -silesia.tar, multithreaded long distance mode, advanced streaming, 4845741 -silesia.tar, small window log, advanced streaming, 7117559 +silesia.tar, no source size, advanced streaming, 4858628 +silesia.tar, long distance mode, advanced streaming, 4837775 +silesia.tar, multithreaded, advanced streaming, 4851478 +silesia.tar, multithreaded long distance mode, advanced streaming, 4843155 +silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529209 silesia.tar, small chain log, advanced streaming, 4917021 silesia.tar, explicit params, advanced streaming, 4807288 -silesia.tar, uncompressed literals, advanced streaming, 5127423 +silesia.tar, uncompressed literals, advanced streaming, 5126542 silesia.tar, uncompressed literals optimal, advanced streaming, 4308451 silesia.tar, huffman literals, advanced streaming, 5341712 -silesia.tar, multithreaded with advanced params, advanced streaming, 5122567 +silesia.tar, multithreaded with advanced params, advanced streaming, 5118940 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 github, level -3, advanced streaming, 193253 github, level -3 with dict, advanced streaming, 44671 github, level -1, advanced streaming, 175468 github, level -1 with dict, advanced streaming, 41825 -github, level 0, advanced streaming, 136332 -github, level 0 with dict, advanced streaming, 41148 -github, level 0 with dict dms, advanced streaming, 41148 -github, level 0 with dict dds, advanced streaming, 41148 +github, level 0, advanced streaming, 136331 +github, level 0 with dict, advanced streaming, 41118 +github, level 0 with dict dms, advanced streaming, 41118 +github, level 0 with dict dds, advanced streaming, 41118 github, level 0 with dict copy, advanced streaming, 41124 github, level 0 with dict load, advanced streaming, 41847 github, level 1, advanced streaming, 142365 @@ -950,16 +950,16 @@ github, level 1 with dict dms, advanced github, level 1 with dict dds, advanced streaming, 41266 github, level 1 with dict copy, advanced streaming, 41279 github, level 1 with dict load, advanced streaming, 43331 -github, level 3, advanced streaming, 136332 -github, level 3 with dict, advanced streaming, 41148 -github, level 3 with dict dms, advanced streaming, 41148 -github, level 3 with dict dds, advanced streaming, 41148 +github, level 3, advanced streaming, 136331 +github, level 3 with dict, advanced streaming, 41118 +github, level 3 with dict dms, advanced streaming, 41118 +github, level 3 with dict dds, advanced streaming, 41118 github, level 3 with dict copy, advanced streaming, 41124 github, level 3 with dict load, advanced streaming, 41847 github, level 4, advanced streaming, 136199 -github, level 4 with dict, advanced streaming, 41251 -github, level 4 with dict dms, advanced streaming, 41251 -github, level 4 with dict dds, advanced streaming, 41251 +github, level 4 with dict, advanced streaming, 41229 +github, level 4 with dict dms, advanced streaming, 41229 +github, level 4 with dict dds, advanced streaming, 41229 github, level 4 with dict copy, advanced streaming, 41216 github, level 4 with dict load, advanced streaming, 41548 github, level 5 row 1, advanced streaming, 134584 @@ -1044,29 +1044,29 @@ github, level 19 with dict dms, advanced github, level 19 with dict dds, advanced streaming, 37916 github, level 19 with dict copy, advanced streaming, 37906 github, level 19 with dict load, advanced streaming, 39770 -github, no source size, advanced streaming, 136332 -github, no source size with dict, advanced streaming, 41148 -github, long distance mode, advanced streaming, 136332 -github, multithreaded, advanced streaming, 136332 -github, multithreaded long distance mode, advanced streaming, 136332 -github, small window log, advanced streaming, 136332 +github, no source size, advanced streaming, 136331 +github, no source size with dict, advanced streaming, 41118 +github, long distance mode, advanced streaming, 136331 +github, multithreaded, advanced streaming, 136331 +github, multithreaded long distance mode, advanced streaming, 136331 +github, small window log, advanced streaming, 136331 github, small hash log, advanced streaming, 135590 github, small chain log, advanced streaming, 136341 github, explicit params, advanced streaming, 137727 -github, uncompressed literals, advanced streaming, 165911 +github, uncompressed literals, advanced streaming, 165909 github, uncompressed literals optimal, advanced streaming, 152667 github, huffman literals, advanced streaming, 142365 -github, multithreaded with advanced params, advanced streaming, 165911 +github, multithreaded with advanced params, advanced streaming, 165909 github.tar, level -5, advanced streaming, 52152 github.tar, level -5 with dict, advanced streaming, 51181 github.tar, level -3, advanced streaming, 45678 github.tar, level -3 with dict, advanced streaming, 44734 github.tar, level -1, advanced streaming, 42560 github.tar, level -1 with dict, advanced streaming, 41353 -github.tar, level 0, advanced streaming, 38831 +github.tar, level 0, advanced streaming, 38884 github.tar, level 0 with dict, advanced streaming, 37995 -github.tar, level 0 with dict dms, advanced streaming, 38003 -github.tar, level 0 with dict dds, advanced streaming, 38003 +github.tar, level 0 with dict dms, advanced streaming, 38114 +github.tar, level 0 with dict dds, advanced streaming, 38114 github.tar, level 0 with dict copy, advanced streaming, 37995 github.tar, level 0 with dict load, advanced streaming, 37956 github.tar, level 1, advanced streaming, 39200 @@ -1075,16 +1075,16 @@ github.tar, level 1 with dict dms, advanced github.tar, level 1 with dict dds, advanced streaming, 38406 github.tar, level 1 with dict copy, advanced streaming, 38119 github.tar, level 1 with dict load, advanced streaming, 38364 -github.tar, level 3, advanced streaming, 38831 +github.tar, level 3, advanced streaming, 38884 github.tar, level 3 with dict, advanced streaming, 37995 -github.tar, level 3 with dict dms, advanced streaming, 38003 -github.tar, level 3 with dict dds, advanced streaming, 38003 +github.tar, level 3 with dict dms, advanced streaming, 38114 +github.tar, level 3 with dict dds, advanced streaming, 38114 github.tar, level 3 with dict copy, advanced streaming, 37995 github.tar, level 3 with dict load, advanced streaming, 37956 -github.tar, level 4, advanced streaming, 38893 +github.tar, level 4, advanced streaming, 38880 github.tar, level 4 with dict, advanced streaming, 37948 -github.tar, level 4 with dict dms, advanced streaming, 37954 -github.tar, level 4 with dict dds, advanced streaming, 37954 +github.tar, level 4 with dict dms, advanced streaming, 37995 +github.tar, level 4 with dict dds, advanced streaming, 37995 github.tar, level 4 with dict copy, advanced streaming, 37948 github.tar, level 4 with dict load, advanced streaming, 37927 github.tar, level 5 row 1, advanced streaming, 39651 @@ -1169,26 +1169,26 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced streaming, 32565 github.tar, level 19 with dict copy, advanced streaming, 32701 github.tar, level 19 with dict load, advanced streaming, 32428 -github.tar, no source size, advanced streaming, 38828 -github.tar, no source size with dict, advanced streaming, 38000 -github.tar, long distance mode, advanced streaming, 40252 -github.tar, multithreaded, advanced streaming, 38831 -github.tar, multithreaded long distance mode, advanced streaming, 40232 -github.tar, small window log, advanced streaming, 199558 +github.tar, no source size, advanced streaming, 38881 +github.tar, no source size with dict, advanced streaming, 38111 +github.tar, long distance mode, advanced streaming, 40242 +github.tar, multithreaded, advanced streaming, 38884 +github.tar, multithreaded long distance mode, advanced streaming, 40223 +github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 github.tar, explicit params, advanced streaming, 41385 -github.tar, uncompressed literals, advanced streaming, 41525 +github.tar, uncompressed literals, advanced streaming, 41562 github.tar, uncompressed literals optimal, advanced streaming, 35356 github.tar, huffman literals, advanced streaming, 38853 -github.tar, multithreaded with advanced params, advanced streaming, 41525 +github.tar, multithreaded with advanced params, advanced streaming, 41562 silesia, level -5, old streaming, 6854744 silesia, level -3, old streaming, 6503319 silesia, level -1, old streaming, 6172207 -silesia, level 0, old streaming, 4842075 +silesia, level 0, old streaming, 4839431 silesia, level 1, old streaming, 5306388 -silesia, level 3, old streaming, 4842075 -silesia, level 4, old streaming, 4779186 +silesia, level 3, old streaming, 4839431 +silesia, level 4, old streaming, 4776557 silesia, level 5, old streaming, 4667668 silesia, level 6, old streaming, 4604351 silesia, level 7, old streaming, 4570271 @@ -1196,17 +1196,17 @@ silesia, level 9, old stre silesia, level 13, old streaming, 4493990 silesia, level 16, old streaming, 4359652 silesia, level 19, old streaming, 4266582 -silesia, no source size, old streaming, 4842039 -silesia, uncompressed literals, old streaming, 4842075 +silesia, no source size, old streaming, 4839395 +silesia, uncompressed literals, old streaming, 4839431 silesia, uncompressed literals optimal, old streaming, 4266582 silesia, huffman literals, old streaming, 6172207 silesia.tar, level -5, old streaming, 6856523 silesia.tar, level -3, old streaming, 6505954 silesia.tar, level -1, old streaming, 6179056 -silesia.tar, level 0, old streaming, 4859271 +silesia.tar, level 0, old streaming, 4858632 silesia.tar, level 1, old streaming, 5327708 -silesia.tar, level 3, old streaming, 4859271 -silesia.tar, level 4, old streaming, 4797470 +silesia.tar, level 3, old streaming, 4858632 +silesia.tar, level 4, old streaming, 4796895 silesia.tar, level 5, old streaming, 4679020 silesia.tar, level 6, old streaming, 4614558 silesia.tar, level 7, old streaming, 4579823 @@ -1214,8 +1214,8 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming, 4502956 silesia.tar, level 16, old streaming, 4360385 silesia.tar, level 19, old streaming, 4260939 -silesia.tar, no source size, old streaming, 4859267 -silesia.tar, uncompressed literals, old streaming, 4859271 +silesia.tar, no source size, old streaming, 4858628 +silesia.tar, uncompressed literals, old streaming, 4858632 silesia.tar, uncompressed literals optimal, old streaming, 4260939 silesia.tar, huffman literals, old streaming, 6179056 github, level -5, old streaming, 204407 @@ -1224,14 +1224,14 @@ github, level -3, old stre github, level -3 with dict, old streaming, 44671 github, level -1, old streaming, 175468 github, level -1 with dict, old streaming, 41825 -github, level 0, old streaming, 136332 -github, level 0 with dict, old streaming, 41148 +github, level 0, old streaming, 136331 +github, level 0 with dict, old streaming, 41118 github, level 1, old streaming, 142365 github, level 1 with dict, old streaming, 41266 -github, level 3, old streaming, 136332 -github, level 3 with dict, old streaming, 41148 +github, level 3, old streaming, 136331 +github, level 3 with dict, old streaming, 41118 github, level 4, old streaming, 136199 -github, level 4 with dict, old streaming, 41251 +github, level 4 with dict, old streaming, 41229 github, level 5, old streaming, 135121 github, level 5 with dict, old streaming, 38754 github, level 6, old streaming, 135122 @@ -1247,8 +1247,8 @@ github, level 16 with dict, old stre github, level 19, old streaming, 132879 github, level 19 with dict, old streaming, 37916 github, no source size, old streaming, 140599 -github, no source size with dict, old streaming, 40654 -github, uncompressed literals, old streaming, 136332 +github, no source size with dict, old streaming, 40652 +github, uncompressed literals, old streaming, 136331 github, uncompressed literals optimal, old streaming, 132879 github, huffman literals, old streaming, 175468 github.tar, level -5, old streaming, 52152 @@ -1257,13 +1257,13 @@ github.tar, level -3, old stre github.tar, level -3 with dict, old streaming, 44734 github.tar, level -1, old streaming, 42560 github.tar, level -1 with dict, old streaming, 41353 -github.tar, level 0, old streaming, 38831 +github.tar, level 0, old streaming, 38884 github.tar, level 0 with dict, old streaming, 37995 github.tar, level 1, old streaming, 39200 github.tar, level 1 with dict, old streaming, 38119 -github.tar, level 3, old streaming, 38831 +github.tar, level 3, old streaming, 38884 github.tar, level 3 with dict, old streaming, 37995 -github.tar, level 4, old streaming, 38893 +github.tar, level 4, old streaming, 38880 github.tar, level 4 with dict, old streaming, 37948 github.tar, level 5, old streaming, 39651 github.tar, level 5 with dict, old streaming, 39145 @@ -1279,18 +1279,18 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming, 33375 github.tar, level 19, old streaming, 32262 github.tar, level 19 with dict, old streaming, 32701 -github.tar, no source size, old streaming, 38828 -github.tar, no source size with dict, old streaming, 38000 -github.tar, uncompressed literals, old streaming, 38831 +github.tar, no source size, old streaming, 38881 +github.tar, no source size with dict, old streaming, 38111 +github.tar, uncompressed literals, old streaming, 38884 github.tar, uncompressed literals optimal, old streaming, 32262 github.tar, huffman literals, old streaming, 42560 silesia, level -5, old streaming advanced, 6854744 silesia, level -3, old streaming advanced, 6503319 silesia, level -1, old streaming advanced, 6172207 -silesia, level 0, old streaming advanced, 4842075 +silesia, level 0, old streaming advanced, 4839431 silesia, level 1, old streaming advanced, 5306388 -silesia, level 3, old streaming advanced, 4842075 -silesia, level 4, old streaming advanced, 4779186 +silesia, level 3, old streaming advanced, 4839431 +silesia, level 4, old streaming advanced, 4776557 silesia, level 5, old streaming advanced, 4667668 silesia, level 6, old streaming advanced, 4604351 silesia, level 7, old streaming advanced, 4570271 @@ -1298,25 +1298,25 @@ silesia, level 9, old stre silesia, level 13, old streaming advanced, 4493990 silesia, level 16, old streaming advanced, 4359652 silesia, level 19, old streaming advanced, 4266582 -silesia, no source size, old streaming advanced, 4842039 -silesia, long distance mode, old streaming advanced, 4842075 -silesia, multithreaded, old streaming advanced, 4842075 -silesia, multithreaded long distance mode, old streaming advanced, 4842075 -silesia, small window log, old streaming advanced, 7111103 +silesia, no source size, old streaming advanced, 4839395 +silesia, long distance mode, old streaming advanced, 4839431 +silesia, multithreaded, old streaming advanced, 4839431 +silesia, multithreaded long distance mode, old streaming advanced, 4839431 +silesia, small window log, old streaming advanced, 7110591 silesia, small hash log, old streaming advanced, 6526141 silesia, small chain log, old streaming advanced, 4912197 silesia, explicit params, old streaming advanced, 4795857 -silesia, uncompressed literals, old streaming advanced, 4842075 +silesia, uncompressed literals, old streaming advanced, 4839431 silesia, uncompressed literals optimal, old streaming advanced, 4266582 silesia, huffman literals, old streaming advanced, 6172207 -silesia, multithreaded with advanced params, old streaming advanced, 4842075 +silesia, multithreaded with advanced params, old streaming advanced, 4839431 silesia.tar, level -5, old streaming advanced, 6856523 silesia.tar, level -3, old streaming advanced, 6505954 silesia.tar, level -1, old streaming advanced, 6179056 -silesia.tar, level 0, old streaming advanced, 4859271 +silesia.tar, level 0, old streaming advanced, 4858632 silesia.tar, level 1, old streaming advanced, 5327708 -silesia.tar, level 3, old streaming advanced, 4859271 -silesia.tar, level 4, old streaming advanced, 4797470 +silesia.tar, level 3, old streaming advanced, 4858632 +silesia.tar, level 4, old streaming advanced, 4796895 silesia.tar, level 5, old streaming advanced, 4679020 silesia.tar, level 6, old streaming advanced, 4614558 silesia.tar, level 7, old streaming advanced, 4579823 @@ -1324,32 +1324,32 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming advanced, 4502956 silesia.tar, level 16, old streaming advanced, 4360385 silesia.tar, level 19, old streaming advanced, 4260939 -silesia.tar, no source size, old streaming advanced, 4859267 -silesia.tar, long distance mode, old streaming advanced, 4859271 -silesia.tar, multithreaded, old streaming advanced, 4859271 -silesia.tar, multithreaded long distance mode, old streaming advanced, 4859271 -silesia.tar, small window log, old streaming advanced, 7117562 +silesia.tar, no source size, old streaming advanced, 4858628 +silesia.tar, long distance mode, old streaming advanced, 4858632 +silesia.tar, multithreaded, old streaming advanced, 4858632 +silesia.tar, multithreaded long distance mode, old streaming advanced, 4858632 +silesia.tar, small window log, old streaming advanced, 7117027 silesia.tar, small hash log, old streaming advanced, 6529209 silesia.tar, small chain log, old streaming advanced, 4917021 silesia.tar, explicit params, old streaming advanced, 4807288 -silesia.tar, uncompressed literals, old streaming advanced, 4859271 +silesia.tar, uncompressed literals, old streaming advanced, 4858632 silesia.tar, uncompressed literals optimal, old streaming advanced, 4260939 silesia.tar, huffman literals, old streaming advanced, 6179056 -silesia.tar, multithreaded with advanced params, old streaming advanced, 4859271 +silesia.tar, multithreaded with advanced params, old streaming advanced, 4858632 github, level -5, old streaming advanced, 213265 github, level -5 with dict, old streaming advanced, 46708 github, level -3, old streaming advanced, 196126 github, level -3 with dict, old streaming advanced, 45476 github, level -1, old streaming advanced, 181107 github, level -1 with dict, old streaming advanced, 42060 -github, level 0, old streaming advanced, 141104 -github, level 0 with dict, old streaming advanced, 41113 +github, level 0, old streaming advanced, 141101 +github, level 0 with dict, old streaming advanced, 41074 github, level 1, old streaming advanced, 143693 github, level 1 with dict, old streaming advanced, 42430 -github, level 3, old streaming advanced, 141104 -github, level 3 with dict, old streaming advanced, 41113 -github, level 4, old streaming advanced, 141104 -github, level 4 with dict, old streaming advanced, 41084 +github, level 3, old streaming advanced, 141101 +github, level 3 with dict, old streaming advanced, 41074 +github, level 4, old streaming advanced, 141101 +github, level 4 with dict, old streaming advanced, 41046 github, level 5, old streaming advanced, 139402 github, level 5 with dict, old streaming advanced, 38723 github, level 6, old streaming advanced, 138676 @@ -1366,30 +1366,30 @@ github, level 19, old stre github, level 19 with dict, old streaming advanced, 37916 github, no source size, old streaming advanced, 140599 github, no source size with dict, old streaming advanced, 40608 -github, long distance mode, old streaming advanced, 141104 -github, multithreaded, old streaming advanced, 141104 -github, multithreaded long distance mode, old streaming advanced, 141104 -github, small window log, old streaming advanced, 141104 +github, long distance mode, old streaming advanced, 141101 +github, multithreaded, old streaming advanced, 141101 +github, multithreaded long distance mode, old streaming advanced, 141101 +github, small window log, old streaming advanced, 141101 github, small hash log, old streaming advanced, 141597 github, small chain log, old streaming advanced, 139275 github, explicit params, old streaming advanced, 140937 -github, uncompressed literals, old streaming advanced, 141104 +github, uncompressed literals, old streaming advanced, 141101 github, uncompressed literals optimal, old streaming advanced, 132879 github, huffman literals, old streaming advanced, 181107 -github, multithreaded with advanced params, old streaming advanced, 141104 +github, multithreaded with advanced params, old streaming advanced, 141101 github.tar, level -5, old streaming advanced, 52152 github.tar, level -5 with dict, old streaming advanced, 51129 github.tar, level -3, old streaming advanced, 45678 github.tar, level -3 with dict, old streaming advanced, 44986 github.tar, level -1, old streaming advanced, 42560 github.tar, level -1 with dict, old streaming advanced, 41650 -github.tar, level 0, old streaming advanced, 38831 +github.tar, level 0, old streaming advanced, 38884 github.tar, level 0 with dict, old streaming advanced, 38013 github.tar, level 1, old streaming advanced, 39200 github.tar, level 1 with dict, old streaming advanced, 38359 -github.tar, level 3, old streaming advanced, 38831 +github.tar, level 3, old streaming advanced, 38884 github.tar, level 3 with dict, old streaming advanced, 38013 -github.tar, level 4, old streaming advanced, 38893 +github.tar, level 4, old streaming advanced, 38880 github.tar, level 4 with dict, old streaming advanced, 38063 github.tar, level 5, old streaming advanced, 39651 github.tar, level 5 with dict, old streaming advanced, 39018 @@ -1405,26 +1405,26 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming advanced, 38578 github.tar, level 19, old streaming advanced, 32262 github.tar, level 19 with dict, old streaming advanced, 32678 -github.tar, no source size, old streaming advanced, 38828 -github.tar, no source size with dict, old streaming advanced, 38015 -github.tar, long distance mode, old streaming advanced, 38831 -github.tar, multithreaded, old streaming advanced, 38831 -github.tar, multithreaded long distance mode, old streaming advanced, 38831 -github.tar, small window log, old streaming advanced, 199561 +github.tar, no source size, old streaming advanced, 38881 +github.tar, no source size with dict, old streaming advanced, 38076 +github.tar, long distance mode, old streaming advanced, 38884 +github.tar, multithreaded, old streaming advanced, 38884 +github.tar, multithreaded long distance mode, old streaming advanced, 38884 +github.tar, small window log, old streaming advanced, 199556 github.tar, small hash log, old streaming advanced, 129870 github.tar, small chain log, old streaming advanced, 41669 github.tar, explicit params, old streaming advanced, 41385 -github.tar, uncompressed literals, old streaming advanced, 38831 +github.tar, uncompressed literals, old streaming advanced, 38884 github.tar, uncompressed literals optimal, old streaming advanced, 32262 github.tar, huffman literals, old streaming advanced, 42560 -github.tar, multithreaded with advanced params, old streaming advanced, 38831 +github.tar, multithreaded with advanced params, old streaming advanced, 38884 github, level -5 with dict, old streaming cdict, 45832 github, level -3 with dict, old streaming cdict, 44671 github, level -1 with dict, old streaming cdict, 41825 -github, level 0 with dict, old streaming cdict, 41148 +github, level 0 with dict, old streaming cdict, 41118 github, level 1 with dict, old streaming cdict, 41266 -github, level 3 with dict, old streaming cdict, 41148 -github, level 4 with dict, old streaming cdict, 41251 +github, level 3 with dict, old streaming cdict, 41118 +github, level 4 with dict, old streaming cdict, 41229 github, level 5 with dict, old streaming cdict, 38754 github, level 6 with dict, old streaming cdict, 38669 github, level 7 with dict, old streaming cdict, 38765 @@ -1432,7 +1432,7 @@ github, level 9 with dict, old stre github, level 13 with dict, old streaming cdict, 39900 github, level 16 with dict, old streaming cdict, 37902 github, level 19 with dict, old streaming cdict, 37916 -github, no source size with dict, old streaming cdict, 40654 +github, no source size with dict, old streaming cdict, 40652 github.tar, level -5 with dict, old streaming cdict, 51286 github.tar, level -3 with dict, old streaming cdict, 45147 github.tar, level -1 with dict, old streaming cdict, 41865 @@ -1447,14 +1447,14 @@ github.tar, level 9 with dict, old stre github.tar, level 13 with dict, old streaming cdict, 36010 github.tar, level 16 with dict, old streaming cdict, 39081 github.tar, level 19 with dict, old streaming cdict, 32428 -github.tar, no source size with dict, old streaming cdict, 38000 +github.tar, no source size with dict, old streaming cdict, 38111 github, level -5 with dict, old streaming advanced cdict, 46708 github, level -3 with dict, old streaming advanced cdict, 45476 github, level -1 with dict, old streaming advanced cdict, 42060 -github, level 0 with dict, old streaming advanced cdict, 41113 +github, level 0 with dict, old streaming advanced cdict, 41074 github, level 1 with dict, old streaming advanced cdict, 42430 -github, level 3 with dict, old streaming advanced cdict, 41113 -github, level 4 with dict, old streaming advanced cdict, 41084 +github, level 3 with dict, old streaming advanced cdict, 41074 +github, level 4 with dict, old streaming advanced cdict, 41046 github, level 5 with dict, old streaming advanced cdict, 38723 github, level 6 with dict, old streaming advanced cdict, 38744 github, level 7 with dict, old streaming advanced cdict, 38875 @@ -1477,4 +1477,4 @@ github.tar, level 9 with dict, old stre github.tar, level 13 with dict, old streaming advanced cdict, 35807 github.tar, level 16 with dict, old streaming advanced cdict, 38578 github.tar, level 19 with dict, old streaming advanced cdict, 32678 -github.tar, no source size with dict, old streaming advanced cdict, 38015 +github.tar, no source size with dict, old streaming advanced cdict, 38076 From 0079d515b1673a7deba3dfa46204a1af61d81dce Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 02:18:48 -0700 Subject: [PATCH 099/405] Modify benchmark to only load sources once After a regrettable update, the benchmark module ended up reloading sources for every compression level. While the delay itself is likely torelable, the main issue is that the `--quiet` mode now also displays a loading summary between each compression line. This wasn't the original intention, which is to produce a compact view of all compressions. This is fixed in this version, where sources are loaded only once, for all compression levels, and loading summary is only displayed once. --- programs/benchzstd.c | 87 +++++++++++++++++++++++--------------------- programs/benchzstd.h | 10 +++-- programs/zstdcli.c | 16 +++----- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 0a1cba9e6..5ea7bb72e 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -928,12 +928,13 @@ BMK_benchOutcome_t BMK_benchMem( &adv); } -static BMK_benchOutcome_t BMK_benchCLevel( +/* @return: 0 on success, !0 if error */ +static int BMK_benchCLevels( const void* srcBuffer, size_t benchedSize, const size_t* fileSizes, unsigned nbFiles, - int cLevel, + int startCLevel, int endCLevel, const ZSTD_compressionParameters* comprParams, const void* dictBuffer, size_t dictBufferSize, @@ -941,12 +942,22 @@ static BMK_benchOutcome_t BMK_benchCLevel( const char* displayName, BMK_advancedParams_t const* const adv) { + int level; const char* pch = strrchr(displayName, '\\'); /* Windows */ if (!pch) pch = strrchr(displayName, '/'); /* Linux */ if (pch) displayName = pch + 1; + if (endCLevel > ZSTD_maxCLevel()) { + DISPLAYLEVEL(1, "Invalid Compression Level \n"); + return 15; + } + if (endCLevel < startCLevel) { + DISPLAYLEVEL(1, "Invalid Compression Level Range \n"); + return 15; + } + if (adv->realTime) { DISPLAYLEVEL(2, "Note : switching to real-time priority \n"); SET_REALTIME_PRIORITY; @@ -960,25 +971,29 @@ static BMK_benchOutcome_t BMK_benchCLevel( adv->nbSeconds, (unsigned)(adv->blockSize >> 10)); - return BMK_benchMemAdvanced( + for (level = startCLevel; level <= endCLevel; level++) { + BMK_benchOutcome_t res = BMK_benchMemAdvanced( srcBuffer, benchedSize, NULL, 0, fileSizes, nbFiles, - cLevel, + level, comprParams, dictBuffer, dictBufferSize, displayLevel, displayName, adv); + if (!BMK_isSuccessful_benchOutcome(res)) return 1; + } + return 0; } int BMK_syntheticTest( - int cLevel, double compressibility, + int startingCLevel, int endCLevel, const ZSTD_compressionParameters* compressionParams, int displayLevel, const BMK_advancedParams_t* adv) @@ -986,18 +1001,11 @@ int BMK_syntheticTest( char nameBuff[20] = { 0 }; const char* name = nameBuff; size_t const benchedSize = adv->blockSize ? adv->blockSize : 10000000; - void* srcBuffer; - BMK_benchOutcome_t res; - - if (cLevel > ZSTD_maxCLevel()) { - DISPLAYLEVEL(1, "Invalid Compression Level"); - return 15; - } /* Memory allocation */ - srcBuffer = malloc(benchedSize); + void* const srcBuffer = malloc(benchedSize); if (!srcBuffer) { - DISPLAYLEVEL(1, "allocation error : not enough memory"); + DISPLAYLEVEL(1, "allocation error : not enough memory \n"); return 16; } @@ -1015,23 +1023,21 @@ int BMK_syntheticTest( } /* Bench */ - res = BMK_benchCLevel( - srcBuffer, - benchedSize, - &benchedSize /* ? */, - 1 /* ? */, - cLevel, - compressionParams, - NULL, - 0, /* dictionary */ - displayLevel, - name, - adv); - - /* clean up */ - free(srcBuffer); - - return !BMK_isSuccessful_benchOutcome(res); + { int res = BMK_benchCLevels( + srcBuffer, + benchedSize, + &benchedSize, + 1, + startingCLevel, endCLevel, + compressionParams, + NULL, + 0, /* dictionary */ + displayLevel, + name, + adv); + free(srcBuffer); + return res; + } } static size_t BMK_findMaxMem(U64 requiredMem) @@ -1120,7 +1126,7 @@ int BMK_benchFilesAdvanced( const char* const* fileNamesTable, unsigned nbFiles, const char* dictFileName, - int cLevel, + int startCLevel, int endCLevel, const ZSTD_compressionParameters* compressionParams, int displayLevel, const BMK_advancedParams_t* adv) @@ -1130,7 +1136,7 @@ int BMK_benchFilesAdvanced( void* dictBuffer = NULL; size_t dictBufferSize = 0; size_t* fileSizes = NULL; - BMK_benchOutcome_t res; + int res = 1; U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles); if (!nbFiles) { @@ -1138,7 +1144,7 @@ int BMK_benchFilesAdvanced( return 13; } - if (cLevel > ZSTD_maxCLevel()) { + if (endCLevel > ZSTD_maxCLevel()) { DISPLAYLEVEL(1, "Invalid Compression Level"); return 14; } @@ -1192,7 +1198,6 @@ int BMK_benchFilesAdvanced( 1 /*?*/, displayLevel); if (errorCode) { - res = BMK_benchOutcome_error(); goto _cleanUp; } } @@ -1224,7 +1229,6 @@ int BMK_benchFilesAdvanced( nbFiles, displayLevel); if (errorCode) { - res = BMK_benchOutcome_error(); goto _cleanUp; } } @@ -1233,15 +1237,14 @@ int BMK_benchFilesAdvanced( { char mfName[20] = { 0 }; formatString_u(mfName, sizeof(mfName), " %u files", nbFiles); - { - const char* const displayName = + { const char* const displayName = (nbFiles > 1) ? mfName : fileNamesTable[0]; - res = BMK_benchCLevel( + res = BMK_benchCLevels( srcBuffer, benchedSize, fileSizes, nbFiles, - cLevel, + startCLevel, endCLevel, compressionParams, dictBuffer, dictBufferSize, @@ -1255,7 +1258,7 @@ _cleanUp: free(srcBuffer); free(dictBuffer); free(fileSizes); - return !BMK_isSuccessful_benchOutcome(res); + return res; } int BMK_benchFiles( @@ -1271,7 +1274,7 @@ int BMK_benchFiles( fileNamesTable, nbFiles, dictFileName, - cLevel, + cLevel, cLevel, compressionParams, displayLevel, &adv); diff --git a/programs/benchzstd.h b/programs/benchzstd.h index ad3088cd4..6388d4d58 100644 --- a/programs/benchzstd.h +++ b/programs/benchzstd.h @@ -122,12 +122,13 @@ BMK_advancedParams_t BMK_initAdvancedParams(void); int BMK_benchFilesAdvanced( const char* const * fileNamesTable, unsigned nbFiles, const char* dictFileName, - int cLevel, const ZSTD_compressionParameters* compressionParams, + int startCLevel, int endCLevel, + const ZSTD_compressionParameters* compressionParams, int displayLevel, const BMK_advancedParams_t* adv); /*! BMK_syntheticTest() -- called from zstdcli */ -/* Generates a sample with datagen, using compressibility argument */ -/* @cLevel - compression level to benchmark, errors if invalid +/* Generates a sample with datagen, using @compressibility argument + * @cLevel - compression level to benchmark, errors if invalid * @compressibility - determines compressibility of sample, range [0.0 - 1.0] * if @compressibility < 0.0, uses the lorem ipsum generator * @compressionParams - basic compression Parameters @@ -135,7 +136,8 @@ int BMK_benchFilesAdvanced( * @adv - see advanced_Params_t * @return: 0 on success, !0 on error */ -int BMK_syntheticTest(int cLevel, double compressibility, +int BMK_syntheticTest(double compressibility, + int startingCLevel, int endCLevel, const ZSTD_compressionParameters* compressionParams, int displayLevel, const BMK_advancedParams_t* adv); diff --git a/programs/zstdcli.c b/programs/zstdcli.c index d8e908d85..438e9c970 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1400,19 +1400,15 @@ int main(int argCount, const char* argv[]) if(separateFiles) { unsigned i; for(i = 0; i < filenames->tableSize; i++) { - int c; DISPLAYLEVEL(3, "Benchmarking %s \n", filenames->fileNames[i]); - for(c = cLevel; c <= cLevelLast; c++) { - operationResult = BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams); - } } + operationResult = BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams); + } } else { - for(; cLevel <= cLevelLast; cLevel++) { - operationResult = BMK_benchFilesAdvanced(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams); - } } + operationResult = BMK_benchFilesAdvanced(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams); + } } else { - for(; cLevel <= cLevelLast; cLevel++) { - operationResult = BMK_syntheticTest(cLevel, compressibility, &compressionParams, g_displayLevel, &benchParams); - } } + operationResult = BMK_syntheticTest(compressibility, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams); + } #else (void)bench_nbSeconds; (void)blockSize; (void)setRealTimePrio; (void)separateFiles; (void)compressibility; From f34bc9cee63759a85011db66e5cb9187c88ea843 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 23:53:56 -0700 Subject: [PATCH 100/405] improve man page on benchmark mode update the man page in troff format, and the README with latest `--help` content and complementary details about benchmark mode. also: display level 0 when doing decompression benchmark --- programs/README.md | 178 +++++++++++++++++++------------ programs/zstd.1 | 260 ++++++++------------------------------------- programs/zstd.1.md | 11 +- programs/zstdcli.c | 1 + 4 files changed, 162 insertions(+), 288 deletions(-) diff --git a/programs/README.md b/programs/README.md index 1b9f47cbb..43ef07a45 100644 --- a/programs/README.md +++ b/programs/README.md @@ -129,89 +129,131 @@ CLI includes in-memory compression benchmark module for zstd. The benchmark is conducted using given filenames. The files are read into memory and joined together. It makes benchmark more precise as it eliminates I/O overhead. Multiple filenames can be supplied, as multiple parameters, with wildcards, -or names of directories can be used as parameters with `-r` option. +or directory names can be used with `-r` option. +If no file is provided, the benchmark will use a procedurally generated "lorem ipsum" content. The benchmark measures ratio, compressed size, compression and decompression speed. One can select compression levels starting from `-b` and ending with `-e`. The `-i` parameter selects minimal time used for each of tested levels. +The benchmark can also be used to test specific parameters, +such as number of threads (`-T#`), or advanced parameters (`--zstd=#`), or dictionary compression (`-D DICTIONARY`), +and many others available on command for regular compression and decompression. + ### Usage of Command Line Interface The full list of options can be obtained with `-h` or `-H` parameter: ``` -Usage : - zstd [args] [FILE(s)] [-o file] +*** Zstandard CLI (64-bit) v1.5.6, by Yann Collet *** -FILE : a filename - with no FILE, or when FILE is - , read standard input -Arguments : - -# : # compression level (1-19, default: 3) - -d : decompression - -D DICT: use DICT as Dictionary for compression or decompression - -o file: result stored into `file` (only 1 output file) - -f : overwrite output without prompting, also (de)compress links ---rm : remove source file(s) after successful de/compression - -k : preserve source file(s) (default) - -h/-H : display help/long help and exit +Compress or decompress the INPUT file(s); reads from STDIN if INPUT is `-` or not provided. -Advanced arguments : - -V : display Version number and exit - -c : write to standard output (even if it is the console) - -v : verbose mode; specify multiple times to increase verbosity - -q : suppress warnings; specify twice to suppress errors too ---no-progress : do not display the progress counter - -r : operate recursively on directories ---filelist FILE : read list of files to operate upon from FILE ---output-dir-flat DIR : processed files are stored into DIR ---output-dir-mirror DIR : processed files are stored into DIR respecting original directory structure ---[no-]asyncio : use asynchronous IO (default: enabled) ---[no-]check : during compression, add XXH64 integrity checksum to frame (default: enabled). If specified with -d, decompressor will ignore/validate checksums in compressed frame (default: validate). --- : All arguments after "--" are treated as files +Usage: zstd [OPTIONS...] [INPUT... | -] [-o OUTPUT] -Advanced compression arguments : ---ultra : enable levels beyond 19, up to 22 (requires more memory) ---long[=#]: enable long distance matching with given window log (default: 27) ---fast[=#]: switch to very fast compression levels (default: 1) ---adapt : dynamically adapt compression level to I/O conditions ---patch-from=FILE : specify the file to be used as a reference point for zstd's diff engine - -T# : spawns # compression threads (default: 1, 0==# cores) - -B# : select size of each job (default: 0==automatic) ---single-thread : use a single thread for both I/O and compression (result slightly different than -T1) ---rsyncable : compress using a rsync-friendly method (-B sets block size) ---exclude-compressed: only compress files that are not already compressed ---stream-size=# : specify size of streaming input from `stdin` ---size-hint=# optimize compression parameters for streaming input of approximately this size ---target-compressed-block-size=# : generate compressed block of approximately targeted size ---no-dictID : don't write dictID into header (dictionary compression only) ---[no-]compress-literals : force (un)compressed literals ---format=zstd : compress files to the .zst format (default) ---format=gzip : compress files to the .gz format ---format=xz : compress files to the .xz format ---format=lzma : compress files to the .lzma format ---format=lz4 : compress files to the .lz4 format +Options: + -o OUTPUT Write output to a single file, OUTPUT. + -k, --keep Preserve INPUT file(s). [Default] + --rm Remove INPUT file(s) after successful (de)compression. -Advanced decompression arguments : - -l : print information about zstd compressed files ---test : test compressed file integrity - -M# : Set a memory usage limit for decompression ---[no-]sparse : sparse mode (default: disabled) + -# Desired compression level, where `#` is a number between 1 and 19; + lower numbers provide faster compression, higher numbers yield + better compression ratios. [Default: 3] -Dictionary builder : ---train ## : create a dictionary from a training set of files ---train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args ---train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args ---train-legacy[=s=#] : use the legacy algorithm with selectivity (default: 9) - -o DICT : DICT is dictionary name (default: dictionary) ---maxdict=# : limit dictionary to specified size (default: 112640) ---dictID=# : force dictionary ID to specified value (default: random) + -d, --decompress Perform decompression. + -D DICT Use DICT as the dictionary for compression or decompression. -Benchmark arguments : - -b# : benchmark file(s), using # compression level (default: 3) - -e# : test all compression levels successively from -b# to -e# (default: 1) - -i# : minimum evaluation time in seconds (default: 3s) - -B# : cut file into independent chunks of size # (default: no chunking) - -S : output one benchmark result per input file (default: consolidated result) ---priority=rt : set process priority to real-time + -f, --force Disable input and output checks. Allows overwriting existing files, + receiving input from the console, printing output to STDOUT, and + operating on links, block devices, etc. Unrecognized formats will be + passed-through through as-is. + + -h Display short usage and exit. + -H, --help Display full help and exit. + -V, --version Display the program version and exit. + +Advanced options: + -c, --stdout Write to STDOUT (even if it is a console) and keep the INPUT file(s). + + -v, --verbose Enable verbose output; pass multiple times to increase verbosity. + -q, --quiet Suppress warnings; pass twice to suppress errors. + --trace LOG Log tracing information to LOG. + + --[no-]progress Forcibly show/hide the progress counter. NOTE: Any (de)compressed + output to terminal will mix with progress counter text. + + -r Operate recursively on directories. + --filelist LIST Read a list of files to operate on from LIST. + --output-dir-flat DIR Store processed files in DIR. + --output-dir-mirror DIR Store processed files in DIR, respecting original directory structure. + --[no-]asyncio Use asynchronous IO. [Default: Enabled] + + --[no-]check Add XXH64 integrity checksums during compression. [Default: Add, Validate] + If `-d` is present, ignore/validate checksums during decompression. + + -- Treat remaining arguments after `--` as files. + +Advanced compression options: + --ultra Enable levels beyond 19, up to 22; requires more memory. + --fast[=#] Use to very fast compression levels. [Default: 1] + --adapt Dynamically adapt compression level to I/O conditions. + --long[=#] Enable long distance matching with window log #. [Default: 27] + --patch-from=REF Use REF as the reference point for Zstandard's diff engine. + + -T# Spawn # compression threads. [Default: 1; pass 0 for core count.] + --single-thread Share a single thread for I/O and compression (slightly different than `-T1`). + --auto-threads={physical|logical} + Use physical/logical cores when using `-T0`. [Default: Physical] + + -B# Set job size to #. [Default: 0 (automatic)] + --rsyncable Compress using a rsync-friendly method (`-B` sets block size). + + --exclude-compressed Only compress files that are not already compressed. + + --stream-size=# Specify size of streaming input from STDIN. + --size-hint=# Optimize compression parameters for streaming input of approximately size #. + --target-compressed-block-size=# + Generate compressed blocks of approximately # size. + + --no-dictID Don't write `dictID` into the header (dictionary compression only). + --[no-]compress-literals Force (un)compressed literals. + --[no-]row-match-finder Explicitly enable/disable the fast, row-based matchfinder for + the 'greedy', 'lazy', and 'lazy2' strategies. + + --format=zstd Compress files to the `.zst` format. [Default] + --[no-]mmap-dict Memory-map dictionary file rather than mallocing and loading all at once + --format=gzip Compress files to the `.gz` format. + --format=xz Compress files to the `.xz` format. + --format=lzma Compress files to the `.lzma` format. + --format=lz4 Compress files to the `.lz4` format. + +Advanced decompression options: + -l Print information about Zstandard-compressed files. + --test Test compressed file integrity. + -M# Set the memory usage limit to # megabytes. + --[no-]sparse Enable sparse mode. [Default: Enabled for files, disabled for STDOUT.] + --[no-]pass-through Pass through uncompressed files as-is. [Default: Disabled] + +Dictionary builder: + --train Create a dictionary from a training set of files. + + --train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] + Use the cover algorithm (with optional arguments). + --train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] + Use the fast cover algorithm (with optional arguments). + + --train-legacy[=s=#] Use the legacy algorithm with selectivity #. [Default: 9] + -o NAME Use NAME as dictionary name. [Default: dictionary] + --maxdict=# Limit dictionary to specified size #. [Default: 112640] + --dictID=# Force dictionary ID to #. [Default: Random] + +Benchmark options: + -b# Perform benchmarking with compression level #. [Default: 3] + -e# Test all compression levels up to #; starting level is `-b#`. [Default: 1] + -i# Set the minimum evaluation to time # seconds. [Default: 3] + -B# Cut file into independent chunks of size #. [Default: No chunking] + -S Output one benchmark result per input file. [Default: Consolidated result] + -D dictionary Benchmark using dictionary + --priority=rt Set process priority to real-time. ``` ### Passing parameters through Environment Variables diff --git a/programs/zstd.1 b/programs/zstd.1 index 2b5a98511..5f1519f33 100644 --- a/programs/zstd.1 +++ b/programs/zstd.1 @@ -1,566 +1,392 @@ -. -.TH "ZSTD" "1" "March 2024" "zstd 1.5.6" "User Commands" -. +.TH "ZSTD" "1" "October 2024" "zstd 1.5.6" "User Commands" .SH "NAME" \fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files -. .SH "SYNOPSIS" -\fBzstd\fR [\fIOPTIONS\fR] [\-|\fIINPUT\-FILE\fR] [\-o \fIOUTPUT\-FILE\fR] -. +.TS +allbox; +\fBzstd\fR [\fIOPTIONS\fR] [\- \fIINPUT\-FILE\fR] [\-o \fIOUTPUT\-FILE\fR] +.TE .P \fBzstdmt\fR is equivalent to \fBzstd \-T0\fR -. .P \fBunzstd\fR is equivalent to \fBzstd \-d\fR -. .P \fBzstdcat\fR is equivalent to \fBzstd \-dcf\fR -. .SH "DESCRIPTION" \fBzstd\fR is a fast lossless compression algorithm and data compression tool, with command line syntax similar to \fBgzip\fR(1) and \fBxz\fR(1)\. It is based on the \fBLZ77\fR family, with further FSE & huff0 entropy stages\. \fBzstd\fR offers highly configurable compression speed, from fast modes at > 200 MB/s per core, to strong modes with excellent compression ratios\. It also features a very fast decoder, with speeds > 500 MB/s per core, which remains roughly stable at all compression settings\. -. .P \fBzstd\fR command line syntax is generally similar to gzip, but features the following few differences: -. .IP "\(bu" 4 -Source files are preserved by default\. It\'s possible to remove them automatically by using the \fB\-\-rm\fR command\. -. +Source files are preserved by default\. It's possible to remove them automatically by using the \fB\-\-rm\fR command\. .IP "\(bu" 4 When compressing a single file, \fBzstd\fR displays progress notifications and result summary by default\. Use \fB\-q\fR to turn them off\. -. .IP "\(bu" 4 \fBzstd\fR displays a short help page when command line is an error\. Use \fB\-q\fR to turn it off\. -. .IP "\(bu" 4 -\fBzstd\fR does not accept input from console, though it does accept \fBstdin\fR when it\'s not the console\. -. +\fBzstd\fR does not accept input from console, though it does accept \fBstdin\fR when it's not the console\. .IP "\(bu" 4 -\fBzstd\fR does not store the input\'s filename or attributes, only its contents\. -. +\fBzstd\fR does not store the input's filename or attributes, only its contents\. .IP "" 0 -. .P \fBzstd\fR processes each \fIfile\fR according to the selected operation mode\. If no \fIfiles\fR are given or \fIfile\fR is \fB\-\fR, \fBzstd\fR reads from standard input and writes the processed data to standard output\. \fBzstd\fR will refuse to write compressed data to standard output if it is a terminal: it will display an error message and skip the file\. Similarly, \fBzstd\fR will refuse to read compressed data from standard input if it is a terminal\. -. .P Unless \fB\-\-stdout\fR or \fB\-o\fR is specified, \fIfiles\fR are written to a new file whose name is derived from the source \fIfile\fR name: -. .IP "\(bu" 4 When compressing, the suffix \fB\.zst\fR is appended to the source filename to get the target filename\. -. .IP "\(bu" 4 When decompressing, the \fB\.zst\fR suffix is removed from the source filename to get the target filename -. .IP "" 0 -. .SS "Concatenation with \.zst Files" It is possible to concatenate multiple \fB\.zst\fR files\. \fBzstd\fR will decompress such agglomerated file as if it was a single \fB\.zst\fR file\. -. .SH "OPTIONS" -. .SS "Integer Suffixes and Special Values" In most places where an integer argument is expected, an optional suffix is supported to easily indicate large integers\. There must be no space between the integer and the suffix\. -. .TP \fBKiB\fR -Multiply the integer by 1,024 (2^10)\. \fBKi\fR, \fBK\fR, and \fBKB\fR are accepted as synonyms for \fBKiB\fR\. -. +Multiply the integer by 1,024 (2\e^10)\. \fBKi\fR, \fBK\fR, and \fBKB\fR are accepted as synonyms for \fBKiB\fR\. .TP \fBMiB\fR -Multiply the integer by 1,048,576 (2^20)\. \fBMi\fR, \fBM\fR, and \fBMB\fR are accepted as synonyms for \fBMiB\fR\. -. +Multiply the integer by 1,048,576 (2\e^20)\. \fBMi\fR, \fBM\fR, and \fBMB\fR are accepted as synonyms for \fBMiB\fR\. .SS "Operation Mode" If multiple operation mode options are given, the last one takes effect\. -. .TP \fB\-z\fR, \fB\-\-compress\fR Compress\. This is the default operation mode when no operation mode option is specified and no other operation mode is implied from the command name (for example, \fBunzstd\fR implies \fB\-\-decompress\fR)\. -. .TP \fB\-d\fR, \fB\-\-decompress\fR, \fB\-\-uncompress\fR Decompress\. -. .TP \fB\-t\fR, \fB\-\-test\fR Test the integrity of compressed \fIfiles\fR\. This option is equivalent to \fB\-\-decompress \-\-stdout > /dev/null\fR, decompressed data is discarded and checksummed for errors\. No files are created or removed\. -. .TP \fB\-b#\fR Benchmark file(s) using compression level \fI#\fR\. See \fIBENCHMARK\fR below for a description of this operation\. -. .TP \fB\-\-train FILES\fR Use \fIFILES\fR as a training set to create a dictionary\. The training set should contain a lot of small files (> 100)\. See \fIDICTIONARY BUILDER\fR below for a description of this operation\. -. .TP \fB\-l\fR, \fB\-\-list\fR -Display information related to a zstd compressed file, such as size, ratio, and checksum\. Some of these fields may not be available\. This command\'s output can be augmented with the \fB\-v\fR modifier\. -. +Display information related to a zstd compressed file, such as size, ratio, and checksum\. Some of these fields may not be available\. This command's output can be augmented with the \fB\-v\fR modifier\. .SS "Operation Modifiers" -. .IP "\(bu" 4 -\fB\-#\fR: selects \fB#\fR compression level [1\-19] (default: 3)\. Higher compression levels \fIgenerally\fR produce higher compression ratio at the expense of speed and memory\. A rough rule of thumb is that compression speed is expected to be divided by 2 every 2 levels\. Technically, each level is mapped to a set of advanced parameters (that can also be modified individually, see below)\. Because the compressor\'s behavior highly depends on the content to compress, there\'s no guarantee of a smooth progression from one level to another\. -. +\fB\-#\fR: selects \fB#\fR compression level [1\-19] (default: 3)\. Higher compression levels \fIgenerally\fR produce higher compression ratio at the expense of speed and memory\. A rough rule of thumb is that compression speed is expected to be divided by 2 every 2 levels\. Technically, each level is mapped to a set of advanced parameters (that can also be modified individually, see below)\. Because the compressor's behavior highly depends on the content to compress, there's no guarantee of a smooth progression from one level to another\. .IP "\(bu" 4 \fB\-\-ultra\fR: unlocks high compression levels 20+ (maximum 22), using a lot more memory\. Note that decompression will also require more memory when using these levels\. -. .IP "\(bu" 4 \fB\-\-fast[=#]\fR: switch to ultra\-fast compression levels\. If \fB=#\fR is not present, it defaults to \fB1\fR\. The higher the value, the faster the compression speed, at the cost of some compression ratio\. This setting overwrites compression level if one was set previously\. Similarly, if a compression level is set after \fB\-\-fast\fR, it overrides it\. -. .IP "\(bu" 4 \fB\-T#\fR, \fB\-\-threads=#\fR: Compress using \fB#\fR working threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. In all cases, the nb of threads is capped to \fBZSTDMT_NBWORKERS_MAX\fR, which is either 64 in 32\-bit mode, or 256 for 64\-bit environments\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\. -. .IP "\(bu" 4 \fB\-\-single\-thread\fR: Use a single thread for both I/O and compression\. As compression is serialized with I/O, this can be slightly slower\. Single\-thread mode features significantly lower memory usage, which can be useful for systems with limited amount of memory, such as 32\-bit systems\. -. .IP Note 1: this mode is the only available one when multithread support is disabled\. -. .IP Note 2: this mode is different from \fB\-T1\fR, which spawns 1 compression thread in parallel with I/O\. Final compressed result is also slightly different from \fB\-T1\fR\. -. .IP "\(bu" 4 \fB\-\-auto\-threads={physical,logical} (default: physical)\fR: When using a default amount of threads via \fB\-T0\fR, choose the default based on the number of detected physical or logical cores\. -. .IP "\(bu" 4 \fB\-\-adapt[=min=#,max=#]\fR: \fBzstd\fR will dynamically adapt compression level to perceived I/O conditions\. Compression level adaptation can be observed live by using command \fB\-v\fR\. Adaptation can be constrained between supplied \fBmin\fR and \fBmax\fR levels\. The feature works when combined with multi\-threading and \fB\-\-long\fR mode\. It does not work with \fB\-\-single\-thread\fR\. It sets window size to 8 MiB by default (can be changed manually, see \fBwlog\fR)\. Due to the chaotic nature of dynamic adaptation, compressed result is not reproducible\. -. .IP \fINote\fR: at the time of this writing, \fB\-\-adapt\fR can remain stuck at low speed when combined with multiple worker threads (>=2)\. -. .IP "\(bu" 4 \fB\-\-long[=#]\fR: enables long distance matching with \fB#\fR \fBwindowLog\fR, if \fB#\fR is not present it defaults to \fB27\fR\. This increases the window size (\fBwindowLog\fR) and memory usage for both the compressor and decompressor\. This setting is designed to improve the compression ratio for files with long matches at a large distance\. -. .IP Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \fB\-\-memory=windowSize\fR needs to be passed to the decompressor\. -. .IP "\(bu" 4 \fB\-D DICT\fR: use \fBDICT\fR as Dictionary to compress or decompress FILE(s) -. .IP "\(bu" 4 -\fB\-\-patch\-from FILE\fR: Specify the file to be used as a reference point for zstd\'s diff engine\. This is effectively dictionary compression with some convenient parameter selection, namely that \fIwindowSize\fR > \fIsrcSize\fR\. -. +\fB\-\-patch\-from FILE\fR: Specify the file to be used as a reference point for zstd's diff engine\. This is effectively dictionary compression with some convenient parameter selection, namely that \fIwindowSize\fR > \fIsrcSize\fR\. .IP Note: cannot use both this and \fB\-D\fR together\. -. .IP Note: \fB\-\-long\fR mode will be automatically activated if \fIchainLog\fR < \fIfileLog\fR (\fIfileLog\fR being the \fIwindowLog\fR required to cover the whole file)\. You can also manually force it\. -. .IP -Note: for all levels, you can use \fB\-\-patch\-from\fR in \fB\-\-single\-thread\fR mode to improve compression ratio at the cost of speed\. -. +Note: up to level 15, you can use \fB\-\-patch\-from\fR in \fB\-\-single\-thread\fR mode to improve compression ratio marginally at the cost of speed\. Using '\-\-single\-thread' above level 15 will lead to lower compression ratios\. .IP Note: for level 19, you can get increased compression ratio at the cost of speed by specifying \fB\-\-zstd=targetLength=\fR to be something large (i\.e\. 4096), and by setting a large \fB\-\-zstd=chainLog=\fR\. -. .IP "\(bu" 4 -\fB\-\-rsyncable\fR: \fBzstd\fR will periodically synchronize the compression state to make the compressed file more rsync\-friendly\. There is a negligible impact to compression ratio, and a potential impact to compression speed, perceptible at higher speeds, for example when combining \fB\-\-rsyncable\fR with many parallel worker threads\. This feature does not work with \fB\-\-single\-thread\fR\. You probably don\'t want to use it with long range mode, since it will decrease the effectiveness of the synchronization points, but your mileage may vary\. -. +\fB\-\-rsyncable\fR: \fBzstd\fR will periodically synchronize the compression state to make the compressed file more rsync\-friendly\. There is a negligible impact to compression ratio, and a potential impact to compression speed, perceptible at higher speeds, for example when combining \fB\-\-rsyncable\fR with many parallel worker threads\. This feature does not work with \fB\-\-single\-thread\fR\. You probably don't want to use it with long range mode, since it will decrease the effectiveness of the synchronization points, but your mileage may vary\. .IP "\(bu" 4 \fB\-C\fR, \fB\-\-[no\-]check\fR: add integrity check computed from uncompressed data (default: enabled) -. .IP "\(bu" 4 \fB\-\-[no\-]content\-size\fR: enable / disable whether or not the original size of the file is placed in the header of the compressed file\. The default option is \fB\-\-content\-size\fR (meaning that the original size will be placed in the header)\. -. .IP "\(bu" 4 -\fB\-\-no\-dictID\fR: do not store dictionary ID within frame header (dictionary compression)\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won\'t be able to check if it\'s correct\. -. +\fB\-\-no\-dictID\fR: do not store dictionary ID within frame header (dictionary compression)\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won't be able to check if it's correct\. .IP "\(bu" 4 \fB\-M#\fR, \fB\-\-memory=#\fR: Set a memory usage limit\. By default, \fBzstd\fR uses 128 MiB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can override this manually if need be in either direction (i\.e\. you can increase or decrease it)\. -. .IP This is also used during compression when using with \fB\-\-patch\-from=\fR\. In this case, this parameter overrides that maximum size allowed for a dictionary\. (128 MiB)\. -. .IP Additionally, this can be used to limit memory for dictionary training\. This parameter overrides the default limit of 2 GiB\. zstd will load training samples up to the memory limit and ignore the rest\. -. .IP "\(bu" 4 \fB\-\-stream\-size=#\fR: Sets the pledged source size of input coming from a stream\. This value must be exact, as it will be included in the produced frame header\. Incorrect stream sizes will cause an error\. This information will be used to better optimize compression parameters, resulting in better and potentially faster compression, especially for smaller source sizes\. -. .IP "\(bu" 4 \fB\-\-size\-hint=#\fR: When handling input from a stream, \fBzstd\fR must guess how large the source size will be when optimizing compression parameters\. If the stream size is relatively small, this guess may be a poor one, resulting in a higher compression ratio than expected\. This feature allows for controlling the guess when needed\. Exact guesses result in better compression ratios\. Overestimates result in slightly degraded compression ratios, while underestimates may result in significant degradation\. -. .IP "\(bu" 4 \fB\-\-target\-compressed\-block\-size=#\fR: Attempt to produce compressed blocks of approximately this size\. This will split larger blocks in order to approach this target\. This feature is notably useful for improved latency, when the receiver can leverage receiving early incomplete data\. This parameter defines a loose target: compressed blocks will target this size "on average", but individual blocks can still be larger or smaller\. Enabling this feature can decrease compression speed by up to ~10% at level 1\. Higher levels will see smaller relative speed regression, becoming invisible at higher settings\. -. .IP "\(bu" 4 \fB\-f\fR, \fB\-\-force\fR: disable input and output checks\. Allows overwriting existing files, input from console, output to stdout, operating on links, block devices, etc\. During decompression and when the output destination is stdout, pass\-through unrecognized formats as\-is\. -. .IP "\(bu" 4 \fB\-c\fR, \fB\-\-stdout\fR: write to standard output (even if it is the console); keep original files (disable \fB\-\-rm\fR)\. -. .IP "\(bu" 4 \fB\-o FILE\fR: save result into \fBFILE\fR\. Note that this operation is in conflict with \fB\-c\fR\. If both operations are present on the command line, the last expressed one wins\. -. .IP "\(bu" 4 \fB\-\-[no\-]sparse\fR: enable / disable sparse FS support, to make files with many zeroes smaller on disk\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\. default: enabled when output is into a file, and disabled when output is stdout\. This setting overrides default and can force sparse mode over stdout\. -. .IP "\(bu" 4 \fB\-\-[no\-]pass\-through\fR enable / disable passing through uncompressed files as\-is\. During decompression when pass\-through is enabled, unrecognized formats will be copied as\-is from the input to the output\. By default, pass\-through will occur when the output destination is stdout and the force (\fB\-f\fR) option is set\. -. .IP "\(bu" 4 \fB\-\-rm\fR: remove source file(s) after successful compression or decompression\. This command is silently ignored if output is \fBstdout\fR\. If used in combination with \fB\-o\fR, triggers a confirmation prompt (which can be silenced with \fB\-f\fR), as this is a destructive operation\. -. .IP "\(bu" 4 \fB\-k\fR, \fB\-\-keep\fR: keep source file(s) after successful compression or decompression\. This is the default behavior\. -. .IP "\(bu" 4 \fB\-r\fR: operate recursively on directories\. It selects all files in the named directory and all its subdirectories\. This can be useful both to reduce command line typing, and to circumvent shell expansion limitations, when there are a lot of files and naming breaks the maximum size of a command line\. -. .IP "\(bu" 4 \fB\-\-filelist FILE\fR read a list of files to process as content from \fBFILE\fR\. Format is compatible with \fBls\fR output, with one file per line\. -. .IP "\(bu" 4 \fB\-\-output\-dir\-flat DIR\fR: resulting files are stored into target \fBDIR\fR directory, instead of same directory as origin file\. Be aware that this command can introduce name collision issues, if multiple files, from different directories, end up having the same name\. Collision resolution ensures first file with a given name will be present in \fBDIR\fR, while in combination with \fB\-f\fR, the last file will be present instead\. -. .IP "\(bu" 4 \fB\-\-output\-dir\-mirror DIR\fR: similar to \fB\-\-output\-dir\-flat\fR, the output files are stored underneath target \fBDIR\fR directory, but this option will replicate input directory hierarchy into output \fBDIR\fR\. -. .IP If input directory contains "\.\.", the files in this directory will be ignored\. If input directory is an absolute directory (i\.e\. "/var/tmp/abc"), it will be stored into the "output\-dir/var/tmp/abc"\. If there are multiple input files or directories, name collision resolution will follow the same rules as \fB\-\-output\-dir\-flat\fR\. -. .IP "\(bu" 4 \fB\-\-format=FORMAT\fR: compress and decompress in other formats\. If compiled with support, zstd can compress to or decompress from other compression algorithm formats\. Possibly available options are \fBzstd\fR, \fBgzip\fR, \fBxz\fR, \fBlzma\fR, and \fBlz4\fR\. If no such format is provided, \fBzstd\fR is the default\. -. .IP "\(bu" 4 \fB\-h\fR/\fB\-H\fR, \fB\-\-help\fR: display help/long help and exit -. .IP "\(bu" 4 \fB\-V\fR, \fB\-\-version\fR: display version number and immediately exit\. note that, since it exits, flags specified after \fB\-V\fR are effectively ignored\. Advanced: \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\. \fB\-qV\fR will only display the version number, suitable for machine reading\. -. .IP "\(bu" 4 \fB\-v\fR, \fB\-\-verbose\fR: verbose mode, display more information -. .IP "\(bu" 4 \fB\-q\fR, \fB\-\-quiet\fR: suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\. -. .IP "\(bu" 4 \fB\-\-no\-progress\fR: do not display the progress bar, but keep all other messages\. -. .IP "\(bu" 4 \fB\-\-show\-default\-cparams\fR: shows the default compression parameters that will be used for a particular input file, based on the provided compression level and the input size\. If the provided file is not a regular file (e\.g\. a pipe), this flag will output the parameters used for inputs of unknown size\. -. .IP "\(bu" 4 \fB\-\-exclude\-compressed\fR: only compress files that are not already compressed\. -. .IP "\(bu" 4 \fB\-\-\fR: All arguments after \fB\-\-\fR are treated as files -. .IP "" 0 -. .SS "gzip Operation Modifiers" When invoked via a \fBgzip\fR symlink, \fBzstd\fR will support further options that intend to mimic the \fBgzip\fR behavior: -. .TP \fB\-n\fR, \fB\-\-no\-name\fR do not store the original filename and timestamps when compressing a file\. This is the default behavior and hence a no\-op\. -. .TP \fB\-\-best\fR alias to the option \fB\-9\fR\. -. .SS "Environment Variables" Employing environment variables to set parameters has security implications\. Therefore, this avenue is intentionally limited\. Only \fBZSTD_CLEVEL\fR and \fBZSTD_NBTHREADS\fR are currently supported\. They set the default compression level and number of threads to use during compression, respectively\. -. .P \fBZSTD_CLEVEL\fR can be used to set the level between 1 and 19 (the "normal" range)\. If the value of \fBZSTD_CLEVEL\fR is not a valid integer, it will be ignored with a warning message\. \fBZSTD_CLEVEL\fR just replaces the default compression level (\fB3\fR)\. -. .P \fBZSTD_NBTHREADS\fR can be used to set the number of threads \fBzstd\fR will attempt to use during compression\. If the value of \fBZSTD_NBTHREADS\fR is not a valid unsigned integer, it will be ignored with a warning message\. \fBZSTD_NBTHREADS\fR has a default value of (\fB1\fR), and is capped at ZSTDMT_NBWORKERS_MAX==200\. \fBzstd\fR must be compiled with multithread support for this variable to have any effect\. -. .P They can both be overridden by corresponding command line arguments: \fB\-#\fR for compression level and \fB\-T#\fR for number of compression threads\. -. .SH "ADVANCED COMPRESSION OPTIONS" \fBzstd\fR provides 22 predefined regular compression levels plus the fast levels\. A compression level is translated internally into multiple advanced parameters that control the behavior of the compressor (one can observe the result of this translation with \fB\-\-show\-default\-cparams\fR)\. These advanced parameters can be overridden using advanced compression options\. -. .SS "\-\-zstd[=options]:" The \fIoptions\fR are provided as a comma\-separated list\. You may specify only the options you want to change and the rest will be taken from the selected or default compression level\. The list of available \fIoptions\fR: -. .TP \fBstrategy\fR=\fIstrat\fR, \fBstrat\fR=\fIstrat\fR Specify a strategy used by a match finder\. -. .IP There are 9 strategies numbered from 1 to 9, from fastest to strongest: 1=\fBZSTD_fast\fR, 2=\fBZSTD_dfast\fR, 3=\fBZSTD_greedy\fR, 4=\fBZSTD_lazy\fR, 5=\fBZSTD_lazy2\fR, 6=\fBZSTD_btlazy2\fR, 7=\fBZSTD_btopt\fR, 8=\fBZSTD_btultra\fR, 9=\fBZSTD_btultra2\fR\. -. .TP \fBwindowLog\fR=\fIwlog\fR, \fBwlog\fR=\fIwlog\fR Specify the maximum number of bits for a match distance\. -. .IP The higher number of increases the chance to find a match which usually improves compression ratio\. It also increases memory requirements for the compressor and decompressor\. The minimum \fIwlog\fR is 10 (1 KiB) and the maximum is 30 (1 GiB) on 32\-bit platforms and 31 (2 GiB) on 64\-bit platforms\. -. .IP Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \fB\-\-memory=windowSize\fR needs to be passed to the decompressor\. -. .TP \fBhashLog\fR=\fIhlog\fR, \fBhlog\fR=\fIhlog\fR Specify the maximum number of bits for a hash table\. -. .IP Bigger hash tables cause fewer collisions which usually makes compression faster, but requires more memory during compression\. -. .IP The minimum \fIhlog\fR is 6 (64 entries / 256 B) and the maximum is 30 (1B entries / 4 GiB)\. -. .TP \fBchainLog\fR=\fIclog\fR, \fBclog\fR=\fIclog\fR Specify the maximum number of bits for the secondary search structure, whose form depends on the selected \fBstrategy\fR\. -. .IP Higher numbers of bits increases the chance to find a match which usually improves compression ratio\. It also slows down compression speed and increases memory requirements for compression\. This option is ignored for the \fBZSTD_fast\fR \fBstrategy\fR, which only has the primary hash table\. -. .IP The minimum \fIclog\fR is 6 (64 entries / 256 B) and the maximum is 29 (512M entries / 2 GiB) on 32\-bit platforms and 30 (1B entries / 4 GiB) on 64\-bit platforms\. -. .TP \fBsearchLog\fR=\fIslog\fR, \fBslog\fR=\fIslog\fR Specify the maximum number of searches in a hash chain or a binary tree using logarithmic scale\. -. .IP More searches increases the chance to find a match which usually increases compression ratio but decreases compression speed\. -. .IP -The minimum \fIslog\fR is 1 and the maximum is \'windowLog\' \- 1\. -. +The minimum \fIslog\fR is 1 and the maximum is 'windowLog' \- 1\. .TP \fBminMatch\fR=\fImml\fR, \fBmml\fR=\fImml\fR Specify the minimum searched length of a match in a hash table\. -. .IP Larger search lengths usually decrease compression ratio but improve decompression speed\. -. .IP The minimum \fImml\fR is 3 and the maximum is 7\. -. .TP \fBtargetLength\fR=\fItlen\fR, \fBtlen\fR=\fItlen\fR The impact of this field vary depending on selected strategy\. -. .IP For \fBZSTD_btopt\fR, \fBZSTD_btultra\fR and \fBZSTD_btultra2\fR, it specifies the minimum match length that causes match finder to stop searching\. A larger \fBtargetLength\fR usually improves compression ratio but decreases compression speed\. -. .IP For \fBZSTD_fast\fR, it triggers ultra\-fast mode when > 0\. The value represents the amount of data skipped between match sampling\. Impact is reversed: a larger \fBtargetLength\fR increases compression speed but decreases compression ratio\. -. .IP For all other strategies, this field has no impact\. -. .IP The minimum \fItlen\fR is 0 and the maximum is 128 KiB\. -. .TP \fBoverlapLog\fR=\fIovlog\fR, \fBovlog\fR=\fIovlog\fR Determine \fBoverlapSize\fR, amount of data reloaded from previous job\. This parameter is only available when multithreading is enabled\. Reloading more data improves compression ratio, but decreases speed\. -. .IP The minimum \fIovlog\fR is 0, and the maximum is 9\. 1 means "no overlap", hence completely independent jobs\. 9 means "full overlap", meaning up to \fBwindowSize\fR is reloaded from previous job\. Reducing \fIovlog\fR by 1 reduces the reloaded amount by a factor 2\. For example, 8 means "windowSize/2", and 6 means "windowSize/8"\. Value 0 is special and means "default": \fIovlog\fR is automatically determined by \fBzstd\fR\. In which case, \fIovlog\fR will range from 6 to 9, depending on selected \fIstrat\fR\. -. .TP \fBldmHashLog\fR=\fIlhlog\fR, \fBlhlog\fR=\fIlhlog\fR Specify the maximum size for a hash table used for long distance matching\. -. .IP This option is ignored unless long distance matching is enabled\. -. .IP Bigger hash tables usually improve compression ratio at the expense of more memory during compression and a decrease in compression speed\. -. .IP The minimum \fIlhlog\fR is 6 and the maximum is 30 (default: 20)\. -. .TP \fBldmMinMatch\fR=\fIlmml\fR, \fBlmml\fR=\fIlmml\fR Specify the minimum searched length of a match for long distance matching\. -. .IP This option is ignored unless long distance matching is enabled\. -. .IP Larger/very small values usually decrease compression ratio\. -. .IP The minimum \fIlmml\fR is 4 and the maximum is 4096 (default: 64)\. -. .TP \fBldmBucketSizeLog\fR=\fIlblog\fR, \fBlblog\fR=\fIlblog\fR Specify the size of each bucket for the hash table used for long distance matching\. -. .IP This option is ignored unless long distance matching is enabled\. -. .IP Larger bucket sizes improve collision resolution but decrease compression speed\. -. .IP The minimum \fIlblog\fR is 1 and the maximum is 8 (default: 3)\. -. .TP \fBldmHashRateLog\fR=\fIlhrlog\fR, \fBlhrlog\fR=\fIlhrlog\fR Specify the frequency of inserting entries into the long distance matching hash table\. -. .IP This option is ignored unless long distance matching is enabled\. -. .IP Larger values will improve compression speed\. Deviating far from the default value will likely result in a decrease in compression ratio\. -. .IP The default value is \fBwlog \- lhlog\fR\. -. .SS "Example" The following parameters sets advanced compression options to something similar to predefined level 19 for files bigger than 256 KB: -. .P \fB\-\-zstd\fR=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6 -. .SS "\-B#:" Specify the size of each compression job\. This parameter is only available when multi\-threading is enabled\. Each compression job is run in parallel, so this value indirectly impacts the nb of active threads\. Default job size varies depending on compression level (generally \fB4 * windowSize\fR)\. \fB\-B#\fR makes it possible to manually select a custom size\. Note that job size must respect a minimum value which is enforced transparently\. This minimum is either 512 KB, or \fBoverlapSize\fR, whichever is largest\. Different job sizes will lead to non\-identical compressed frames\. -. .SH "DICTIONARY BUILDER" -\fBzstd\fR offers \fIdictionary\fR compression, which greatly improves efficiency on small files and messages\. It\'s possible to train \fBzstd\fR with a set of samples, the result of which is saved into a file called a \fBdictionary\fR\. Then, during compression and decompression, reference the same dictionary, using command \fB\-D dictionaryFileName\fR\. Compression of small files similar to the sample set will be greatly improved\. -. +\fBzstd\fR offers \fIdictionary\fR compression, which greatly improves efficiency on small files and messages\. It's possible to train \fBzstd\fR with a set of samples, the result of which is saved into a file called a \fBdictionary\fR\. Then, during compression and decompression, reference the same dictionary, using command \fB\-D dictionaryFileName\fR\. Compression of small files similar to the sample set will be greatly improved\. .TP \fB\-\-train FILEs\fR Use FILEs as training set to create a dictionary\. The training set should ideally contain a lot of samples (> 100), and weight typically 100x the target dictionary size (for example, ~10 MB for a 100 KB dictionary)\. \fB\-\-train\fR can be combined with \fB\-r\fR to indicate a directory rather than listing all the files, which can be useful to circumvent shell expansion limits\. -. .IP Since dictionary compression is mostly effective for small files, the expectation is that the training set will only contain small files\. In the case where some samples happen to be large, only the first 128 KiB of these samples will be used for training\. -. .IP \fB\-\-train\fR supports multithreading if \fBzstd\fR is compiled with threading support (default)\. Additional advanced parameters can be specified with \fB\-\-train\-fastcover\fR\. The legacy dictionary builder can be accessed with \fB\-\-train\-legacy\fR\. The slower cover dictionary builder can be accessed with \fB\-\-train\-cover\fR\. Default \fB\-\-train\fR is equivalent to \fB\-\-train\-fastcover=d=8,steps=4\fR\. -. .TP \fB\-o FILE\fR Dictionary saved into \fBFILE\fR (default name: dictionary)\. -. .TP \fB\-\-maxdict=#\fR -Limit dictionary to specified size (default: 112640 bytes)\. As usual, quantities are expressed in bytes by default, and it\'s possible to employ suffixes (like \fBKB\fR or \fBMB\fR) to specify larger values\. -. +Limit dictionary to specified size (default: 112640 bytes)\. As usual, quantities are expressed in bytes by default, and it's possible to employ suffixes (like \fBKB\fR or \fBMB\fR) to specify larger values\. .TP \fB\-#\fR Use \fB#\fR compression level during training (optional)\. Will generate statistics more tuned for selected compression level, resulting in a \fIsmall\fR compression ratio improvement for this level\. -. .TP \fB\-B#\fR Split input files into blocks of size # (default: no split) -. .TP \fB\-M#\fR, \fB\-\-memory=#\fR Limit the amount of sample data loaded for training (default: 2 GB)\. Note that the default (2 GB) is also the maximum\. This parameter can be useful in situations where the training set size is not well controlled and could be potentially very large\. Since speed of the training process is directly correlated to the size of the training sample set, a smaller sample set leads to faster training\. -. .IP In situations where the training set is larger than maximum memory, the CLI will randomly select samples among the available ones, up to the maximum allowed memory budget\. This is meant to improve dictionary relevance by mitigating the potential impact of clustering, such as selecting only files from the beginning of a list sorted by modification date, or sorted by alphabetical order\. The randomization process is deterministic, so training of the same list of files with the same parameters will lead to the creation of the same dictionary\. -. .TP \fB\-\-dictID=#\fR -A dictionary ID is a locally unique ID\. The decoder will use this value to verify it is using the right dictionary\. By default, zstd will create a 4\-bytes random number ID\. It\'s possible to provide an explicit number ID instead\. It\'s up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\. Note that short numbers have an advantage: an ID < 256 will only need 1 byte in the compressed frame header, and an ID < 65536 will only need 2 bytes\. This compares favorably to 4 bytes default\. -. +A dictionary ID is a locally unique ID\. The decoder will use this value to verify it is using the right dictionary\. By default, zstd will create a 4\-bytes random number ID\. It's possible to provide an explicit number ID instead\. It's up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\. Note that short numbers have an advantage: an ID < 256 will only need 1 byte in the compressed frame header, and an ID < 65536 will only need 2 bytes\. This compares favorably to 4 bytes default\. .IP -Note that RFC8878 reserves IDs less than 32768 and greater than or equal to 2^31, so they should not be used in public\. -. +Note that RFC8878 reserves IDs less than 32768 and greater than or equal to 2\e^31, so they should not be used in public\. .TP \fB\-\-train\-cover[=k#,d=#,steps=#,split=#,shrink[=#]]\fR Select parameters for the default dictionary builder algorithm named cover\. If \fId\fR is not specified, then it tries \fId\fR = 6 and \fId\fR = 8\. If \fIk\fR is not specified, then it tries \fIsteps\fR values in the range [50, 2000]\. If \fIsteps\fR is not specified, then the default value of 40 is used\. If \fIsplit\fR is not specified or split <= 0, then the default value of 100 is used\. Requires that \fId\fR <= \fIk\fR\. If \fIshrink\fR flag is not used, then the default value for \fIshrinkDict\fR of 0 is used\. If \fIshrink\fR is not specified, then the default value for \fIshrinkDictMaxRegression\fR of 1 is used\. -. .IP Selects segments of size \fIk\fR with highest score to put in the dictionary\. The score of a segment is computed by the sum of the frequencies of all the subsegments of size \fId\fR\. Generally \fId\fR should be in the range [6, 8], occasionally up to 16, but the algorithm will run faster with d <= \fI8\fR\. Good values for \fIk\fR vary widely based on the input data, but a safe range is [2 * \fId\fR, 2000]\. If \fIsplit\fR is 100, all input samples are used for both training and testing to find optimal \fId\fR and \fIk\fR to build dictionary\. Supports multithreading if \fBzstd\fR is compiled with threading support\. Having \fIshrink\fR enabled takes a truncated dictionary of minimum size and doubles in size until compression ratio of the truncated dictionary is at most \fIshrinkDictMaxRegression%\fR worse than the compression ratio of the largest dictionary\. -. .IP Examples: -. .IP \fBzstd \-\-train\-cover FILEs\fR -. .IP \fBzstd \-\-train\-cover=k=50,d=8 FILEs\fR -. .IP \fBzstd \-\-train\-cover=d=8,steps=500 FILEs\fR -. .IP \fBzstd \-\-train\-cover=k=50 FILEs\fR -. .IP \fBzstd \-\-train\-cover=k=50,split=60 FILEs\fR -. .IP \fBzstd \-\-train\-cover=shrink FILEs\fR -. .IP \fBzstd \-\-train\-cover=shrink=2 FILEs\fR -. .TP \fB\-\-train\-fastcover[=k#,d=#,f=#,steps=#,split=#,accel=#]\fR Same as cover but with extra parameters \fIf\fR and \fIaccel\fR and different default value of split If \fIsplit\fR is not specified, then it tries \fIsplit\fR = 75\. If \fIf\fR is not specified, then it tries \fIf\fR = 20\. Requires that 0 < \fIf\fR < 32\. If \fIaccel\fR is not specified, then it tries \fIaccel\fR = 1\. Requires that 0 < \fIaccel\fR <= 10\. Requires that \fId\fR = 6 or \fId\fR = 8\. -. .IP \fIf\fR is log of size of array that keeps track of frequency of subsegments of size \fId\fR\. The subsegment is hashed to an index in the range [0,2^\fIf\fR \- 1]\. It is possible that 2 different subsegments are hashed to the same index, and they are considered as the same subsegment when computing frequency\. Using a higher \fIf\fR reduces collision but takes longer\. -. .IP Examples: -. .IP \fBzstd \-\-train\-fastcover FILEs\fR -. .IP \fBzstd \-\-train\-fastcover=d=8,f=15,accel=2 FILEs\fR -. .TP \fB\-\-train\-legacy[=selectivity=#]\fR Use legacy dictionary builder algorithm with the given dictionary \fIselectivity\fR (default: 9)\. The smaller the \fIselectivity\fR value, the denser the dictionary, improving its efficiency but reducing its achievable maximum size\. \fB\-\-train\-legacy=s=#\fR is also accepted\. -. .IP Examples: -. .IP \fBzstd \-\-train\-legacy FILEs\fR -. .IP \fBzstd \-\-train\-legacy=selectivity=8 FILEs\fR -. .SH "BENCHMARK" -The \fBzstd\fR CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer\'s performance\. Note that the results are highly dependent on the content being compressed\. -. -.TP -\fB\-b#\fR -benchmark file(s) using compression level # -. -.TP -\fB\-e#\fR -benchmark file(s) using multiple compression levels, from \fB\-b#\fR to \fB\-e#\fR (inclusive) -. -.TP -\fB\-d\fR -benchmark decompression speed only (requires providing an already zstd\-compressed content) -. -.TP -\fB\-i#\fR -minimum evaluation time, in seconds (default: 3s), benchmark mode only -. -.TP -\fB\-B#\fR, \fB\-\-block\-size=#\fR -cut file(s) into independent chunks of size # (default: no chunking) -. -.TP -\fB\-\-priority=rt\fR -set process priority to real\-time (Windows) -. +The \fBzstd\fR CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer's performance\. \fBzstd \-b [FILE(s)]\fR will benchmark \fBzstd\fR for both compression and decompression using default compression level\. Note that results are very dependent on the content being compressed\. It's possible to pass multiple files to the benchmark, and even a directory with \fB\-r DIRECTORY\fR\. When no \fBFILE\fR is provided, the benchmark will use a procedurally generated \fBlorem ipsum\fR text\. +.IP "\(bu" 4 +\fB\-b#\fR: benchmark file(s) using compression level # +.IP "\(bu" 4 +\fB\-e#\fR: benchmark file(s) using multiple compression levels, from \fB\-b#\fR to \fB\-e#\fR (inclusive) +.IP "\(bu" 4 +\fB\-d\fR: benchmark decompression speed only (requires providing a zstd\-compressed content) +.IP "\(bu" 4 +\fB\-i#\fR: minimum evaluation time, in seconds (default: 3s), benchmark mode only +.IP "\(bu" 4 +\fB\-B#\fR, \fB\-\-block\-size=#\fR: cut file(s) into independent chunks of size # (default: no chunking) +.IP "\(bu" 4 +\fB\-S\fR: output one benchmark result per input file (default: consolidated result) +.IP "\(bu" 4 +\fB\-D dictionary\fR benchmark using dictionary +.IP "\(bu" 4 +\fB\-\-priority=rt\fR: set process priority to real\-time (Windows) +.IP "" 0 +.P +Beyond compression levels, benchmarking is also compatible with other parameters, such as number of threads (\fB\-T#\fR), advanced compression parameters (\fB\-\-zstd=###\fR), dictionary compression (\fB\-D dictionary\fR), or even disabling checksum verification for example\. .P \fBOutput Format:\fR CompressionLevel#Filename: InputSize \-> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed -. .P -\fBMethodology:\fR For both compression and decompression speed, the entire input is compressed/decompressed in\-memory to measure speed\. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy\. -. +\fBMethodology:\fR For speed measurement, the entire input is compressed/decompressed in\-memory to measure speed\. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy\. .SH "SEE ALSO" \fBzstdgrep\fR(1), \fBzstdless\fR(1), \fBgzip\fR(1), \fBxz\fR(1) -. .P -The \fIzstandard\fR format is specified in Y\. Collet, "Zstandard Compression and the \'application/zstd\' Media Type", https://www\.ietf\.org/rfc/rfc8878\.txt, Internet RFC 8878 (February 2021)\. -. +The \fIzstandard\fR format is specified in Y\. Collet, "Zstandard Compression and the 'application/zstd' Media Type", https://www\.ietf\.org/rfc/rfc8878\.txt, Internet RFC 8878 (February 2021)\. .SH "BUGS" Report bugs at: https://github\.com/facebook/zstd/issues -. .SH "AUTHOR" Yann Collet diff --git a/programs/zstd.1.md b/programs/zstd.1.md index d0473fa47..fabf8d6fc 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -662,14 +662,17 @@ Compression of small files similar to the sample set will be greatly improved. BENCHMARK --------- The `zstd` CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer's performance. -Note that the results are highly dependent on the content being compressed. +`zstd -b [FILE(s)]` will benchmark `zstd` for both compression and decompression using default compression level. +Note that results are very dependent on the content being compressed. +It's possible to pass multiple files to the benchmark, and even a directory with `-r DIRECTORY`. +When no `FILE` is provided, the benchmark will use a procedurally generated `lorem ipsum` text. * `-b#`: benchmark file(s) using compression level # * `-e#`: benchmark file(s) using multiple compression levels, from `-b#` to `-e#` (inclusive) * `-d`: - benchmark decompression speed only (requires providing an already zstd-compressed content) + benchmark decompression speed only (requires providing a zstd-compressed content) * `-i#`: minimum evaluation time, in seconds (default: 3s), benchmark mode only * `-B#`, `--block-size=#`: @@ -681,9 +684,11 @@ Note that the results are highly dependent on the content being compressed. * `--priority=rt`: set process priority to real-time (Windows) +Beyond compression levels, benchmarking is also compatible with other parameters, such as number of threads (`-T#`), advanced compression parameters (`--zstd=###`), dictionary compression (`-D dictionary`), or even disabling checksum verification for example. + **Output Format:** CompressionLevel#Filename: InputSize -> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed -**Methodology:** For both compression and decompression speed, the entire input is compressed/decompressed in-memory to measure speed. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy. +**Methodology:** For speed measurement, the entire input is compressed/decompressed in-memory to measure speed. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy. SEE ALSO diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 438e9c970..8f94352fe 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1391,6 +1391,7 @@ int main(int argCount, const char* argv[]) } benchParams.literalCompressionMode = literalCompressionMode; + if (benchParams.mode == BMK_decodeOnly) cLevel = cLevelLast = 0; if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel(); if (cLevelLast < cLevel) cLevelLast = cLevel; From a5bce4ae84daa5885e61753fa98903964c3348bd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 14:35:29 -0700 Subject: [PATCH 101/405] XP: add a pre-splitter instead of ingesting only full blocks, make an analysis of data, and infer where to split. --- lib/compress/zstd_compress.c | 31 ++++++-- lib/compress/zstd_preSplit.c | 139 +++++++++++++++++++++++++++++++++++ lib/compress/zstd_preSplit.h | 26 +++++++ 3 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 lib/compress/zstd_preSplit.c create mode 100644 lib/compress/zstd_preSplit.h diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index aad25049d..040333e59 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -883,7 +883,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, value = ZSTDMT_JOBSIZE_MIN; FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); assert(value >= 0); - CCtxParams->jobSize = value; + CCtxParams->jobSize = (size_t)value; return CCtxParams->jobSize; #endif @@ -1002,7 +1002,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_maxBlockSize: if (value!=0) /* 0 ==> default */ BOUNDCHECK(ZSTD_c_maxBlockSize, value); - CCtxParams->maxBlockSize = value; + assert(value>=0); + CCtxParams->maxBlockSize = (size_t)value; return CCtxParams->maxBlockSize; case ZSTD_c_searchForExternalRepcodes: @@ -2444,7 +2445,8 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, } /* Zero the hashTable3, since the cdict never fills it */ - { int const h3log = cctx->blockState.matchState.hashLog3; + assert(cctx->blockState.matchState.hashLog3 <= 31); + { U32 const h3log = cctx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; assert(cdict->matchState.hashLog3 == 0); ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); @@ -4484,6 +4486,18 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, } } +#include "zstd_preSplit.h" + +static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat) +{ + if (srcSize <= 128 KB || blockSizeMax < 128 KB) + return MIN(srcSize, blockSizeMax); + (void)strat; + if (strat >= ZSTD_btlazy2) + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + return 92 KB; +} + /*! ZSTD_compress_frameChunk() : * Compress a chunk of data into one or multiple blocks. * All blocks will be terminated, all input will be consumed. @@ -4496,7 +4510,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, const void* src, size_t srcSize, U32 lastFrameChunk) { - size_t blockSize = cctx->blockSize; + size_t blockSizeMax = cctx->blockSize; size_t remaining = srcSize; const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; @@ -4505,20 +4519,21 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); + DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSizeMax=%u)", (unsigned)blockSizeMax); if (cctx->appliedParams.fParams.checksumFlag && srcSize) XXH64_update(&cctx->xxhState, src, srcSize); while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); + U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); + size_t blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy); + assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding * additional 1. We need to revisit and change this logic to be more consistent */ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE + 1, dstSize_tooSmall, "not enough space to store compressed block"); - if (remaining < blockSize) blockSize = remaining; ZSTD_overflowCorrectIfNeeded( ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize); @@ -5022,7 +5037,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); } } } - return dictPtr - (const BYTE*)dict; + return (size_t)(dictPtr - (const BYTE*)dict); } /* Dictionary format : diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c new file mode 100644 index 000000000..eaa1c0516 --- /dev/null +++ b/lib/compress/zstd_preSplit.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include "../common/mem.h" /* U64 */ +#include "zstd_preSplit.h" + + +#define BLOCKSIZE_MIN 3500 +#define THRESHOLD_PENALTY_RATE 16 +#define THRESHOLD_BASE (THRESHOLD_PENALTY_RATE - 2) +#define THRESHOLD_PENALTY 4 + +#define HASHLENGTH 2 +#define HASHLOG 10 +#define HASHTABLESIZE (1 << HASHLOG) +#define HASHMASK (HASHTABLESIZE - 1) +#define KNUTH 0x9e3779b9 + +static unsigned hash2(const void *p) +{ + return (U32)(MEM_read16(p)) * KNUTH >> (32 - HASHLOG); +} + + +/* ==================================== */ +/* Global array -> for testing only !!! */ +/* ==================================== */ +typedef struct { + int events[HASHTABLESIZE]; + S64 nbEvents; +} FingerPrint; +static FingerPrint pastEvents = {}; +static FingerPrint newEvents = {}; + +static void initStats(void) { + memset(&pastEvents, 0, sizeof(pastEvents)); + memset(&newEvents, 0, sizeof(newEvents)); +} +/* ==================================== */ + +static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { + const char* p = src; + size_t limit = s - HASHLENGTH + 1; + assert(s >= HASHLENGTH); + for (size_t n = 0; n < limit; n++) { + fp->events[hash2(p++)]++; + } + fp->nbEvents += limit; +} + +static void recordFingerprint(FingerPrint *fp, const void *src, size_t s) { + memset(fp, 0, sizeof(*fp)); + addToFingerprint(fp, src, s); +} + +static S64 abs64(S64 i) { return (i < 0) ? -i : i; } + +static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { + S64 distance = 0; + for (size_t n = 0; n < HASHTABLESIZE; n++) { + distance += + abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); + } + return distance; +} + +// Compare newEvents with pastEvents +// return 1 when considered "too different" +// debug:write Deviation value in % +static int compareFingerprints(const FingerPrint *ref, + const FingerPrint *new, + int penalty) +{ + if (ref->nbEvents <= BLOCKSIZE_MIN) + return 0; + { S64 p50 = ref->nbEvents * new->nbEvents; + S64 deviation = fpDistance(ref, new); + // printf("Deviation: %.2f%% \n", (double)deviation / (double)ref * 100.); + S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; + return deviation >= threshold; + } +} + +static void mergeEvents(FingerPrint *acc, const FingerPrint *new) { + for (size_t n = 0; n < HASHTABLESIZE; n++) { + acc->events[n] += new->events[n]; + } + acc->nbEvents += new->nbEvents; +} + +static void flushEvents(void) { + for (size_t n = 0; n < HASHTABLESIZE; n++) { + pastEvents.events[n] = newEvents.events[n]; + } + pastEvents.nbEvents = newEvents.nbEvents; + memset(&newEvents, 0, sizeof(newEvents)); +} + +static void removeEvents(FingerPrint *acc, const FingerPrint *slice) { + for (size_t n = 0; n < HASHTABLESIZE; n++) { + assert(acc->events[n] >= slice->events[n]); + acc->events[n] -= slice->events[n]; + } + acc->nbEvents -= slice->nbEvents; +} + +#define CHUNKSIZE (8 << 10) +/* Note: technically, we use CHUNKSIZE, so that's 8 KB */ +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) +{ + const char* p = src; + int penalty = THRESHOLD_PENALTY; + size_t pos = 0; + if (srcSize <= blockSizeMax) return srcSize; + assert(blockSizeMax == (128 << 10)); + + initStats(); + for (pos = 0; pos < blockSizeMax;) { + assert(pos <= blockSizeMax - CHUNKSIZE); + recordFingerprint(&newEvents, p + pos, CHUNKSIZE); + if (compareFingerprints(&pastEvents, &newEvents, penalty)) { + return pos; + } else { + mergeEvents(&pastEvents, &newEvents); + memset(&newEvents, 0, sizeof(newEvents)); + penalty = penalty - 1 + (penalty == 0); + } + pos += CHUNKSIZE; + } + return blockSizeMax; + (void)flushEvents; (void)removeEvents; +} diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h new file mode 100644 index 000000000..148fc1936 --- /dev/null +++ b/lib/compress/zstd_preSplit.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_PRESPLIT_H +#define ZSTD_PRESPLIT_H + +#include /* size_t */ + +#if defined (__cplusplus) +extern "C" { +#endif + +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax); + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_PRESPLIT_H */ From 9e52789962bc5d47ee62bc3e499c52435c693e89 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:44:30 -0700 Subject: [PATCH 102/405] fixed strict C90 semantic --- lib/compress/zstd_preSplit.c | 56 ++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index eaa1c0516..f2319986c 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -36,8 +36,8 @@ typedef struct { int events[HASHTABLESIZE]; S64 nbEvents; } FingerPrint; -static FingerPrint pastEvents = {}; -static FingerPrint newEvents = {}; +static FingerPrint pastEvents; +static FingerPrint newEvents; static void initStats(void) { memset(&pastEvents, 0, sizeof(pastEvents)); @@ -48,8 +48,9 @@ static void initStats(void) { static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { const char* p = src; size_t limit = s - HASHLENGTH + 1; + size_t n; assert(s >= HASHLENGTH); - for (size_t n = 0; n < limit; n++) { + for (n = 0; n < limit; n++) { fp->events[hash2(p++)]++; } fp->nbEvents += limit; @@ -64,7 +65,8 @@ static S64 abs64(S64 i) { return (i < 0) ? -i : i; } static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { S64 distance = 0; - for (size_t n = 0; n < HASHTABLESIZE; n++) { + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { distance += abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); } @@ -73,42 +75,46 @@ static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { // Compare newEvents with pastEvents // return 1 when considered "too different" -// debug:write Deviation value in % -static int compareFingerprints(const FingerPrint *ref, - const FingerPrint *new, +static int compareFingerprints(const FingerPrint* ref, + const FingerPrint* new, int penalty) { if (ref->nbEvents <= BLOCKSIZE_MIN) return 0; { S64 p50 = ref->nbEvents * new->nbEvents; S64 deviation = fpDistance(ref, new); - // printf("Deviation: %.2f%% \n", (double)deviation / (double)ref * 100.); S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } } -static void mergeEvents(FingerPrint *acc, const FingerPrint *new) { - for (size_t n = 0; n < HASHTABLESIZE; n++) { - acc->events[n] += new->events[n]; - } - acc->nbEvents += new->nbEvents; +static void mergeEvents(FingerPrint* acc, const FingerPrint* new) +{ + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + acc->events[n] += new->events[n]; + } + acc->nbEvents += new->nbEvents; } -static void flushEvents(void) { - for (size_t n = 0; n < HASHTABLESIZE; n++) { - pastEvents.events[n] = newEvents.events[n]; - } - pastEvents.nbEvents = newEvents.nbEvents; - memset(&newEvents, 0, sizeof(newEvents)); +static void flushEvents(void) +{ + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + pastEvents.events[n] = newEvents.events[n]; + } + pastEvents.nbEvents = newEvents.nbEvents; + memset(&newEvents, 0, sizeof(newEvents)); } -static void removeEvents(FingerPrint *acc, const FingerPrint *slice) { - for (size_t n = 0; n < HASHTABLESIZE; n++) { - assert(acc->events[n] >= slice->events[n]); - acc->events[n] -= slice->events[n]; - } - acc->nbEvents -= slice->nbEvents; +static void removeEvents(FingerPrint* acc, const FingerPrint* slice) +{ + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + assert(acc->events[n] >= slice->events[n]); + acc->events[n] -= slice->events[n]; + } + acc->nbEvents -= slice->nbEvents; } #define CHUNKSIZE (8 << 10) From 586ca96fec794cde09f4aa01fe792a9779b62368 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:48:52 -0700 Subject: [PATCH 103/405] do not use `new` as variable name --- lib/compress/zstd_preSplit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index f2319986c..bba348927 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -76,25 +76,25 @@ static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { // Compare newEvents with pastEvents // return 1 when considered "too different" static int compareFingerprints(const FingerPrint* ref, - const FingerPrint* new, + const FingerPrint* newfp, int penalty) { if (ref->nbEvents <= BLOCKSIZE_MIN) return 0; - { S64 p50 = ref->nbEvents * new->nbEvents; - S64 deviation = fpDistance(ref, new); + { S64 p50 = ref->nbEvents * newfp->nbEvents; + S64 deviation = fpDistance(ref, newfp); S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } } -static void mergeEvents(FingerPrint* acc, const FingerPrint* new) +static void mergeEvents(FingerPrint* acc, const FingerPrint* newfp) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { - acc->events[n] += new->events[n]; + acc->events[n] += newfp->events[n]; } - acc->nbEvents += new->nbEvents; + acc->nbEvents += newfp->nbEvents; } static void flushEvents(void) From e2d7d08888f915667c94e6dbbadaee38a5d50fa5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:52:10 -0700 Subject: [PATCH 104/405] use ZSTD_memset() for better portability on Linux kernel --- lib/compress/zstd_preSplit.c | 50 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index bba348927..8db742c4d 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -39,38 +39,42 @@ typedef struct { static FingerPrint pastEvents; static FingerPrint newEvents; -static void initStats(void) { - memset(&pastEvents, 0, sizeof(pastEvents)); - memset(&newEvents, 0, sizeof(newEvents)); +static void initStats(void) +{ + ZSTD_memset(&pastEvents, 0, sizeof(pastEvents)); + ZSTD_memset(&newEvents, 0, sizeof(newEvents)); } /* ==================================== */ -static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { - const char* p = src; - size_t limit = s - HASHLENGTH + 1; - size_t n; - assert(s >= HASHLENGTH); - for (n = 0; n < limit; n++) { - fp->events[hash2(p++)]++; - } - fp->nbEvents += limit; +static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) +{ + const char* p = src; + size_t limit = s - HASHLENGTH + 1; + size_t n; + assert(s >= HASHLENGTH); + for (n = 0; n < limit; n++) { + fp->events[hash2(p++)]++; + } + fp->nbEvents += limit; } -static void recordFingerprint(FingerPrint *fp, const void *src, size_t s) { - memset(fp, 0, sizeof(*fp)); - addToFingerprint(fp, src, s); +static void recordFingerprint(FingerPrint* fp, const void* src, size_t s) +{ + memset(fp, 0, sizeof(*fp)); + addToFingerprint(fp, src, s); } static S64 abs64(S64 i) { return (i < 0) ? -i : i; } -static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { - S64 distance = 0; - size_t n; - for (n = 0; n < HASHTABLESIZE; n++) { - distance += - abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); - } - return distance; +static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) +{ + S64 distance = 0; + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + distance += + abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); + } + return distance; } // Compare newEvents with pastEvents From 6021b6663a4705f446f7cf856d944819caa575c3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:54:36 -0700 Subject: [PATCH 105/405] minor C++-ism though I really wonder if this is a property worth maintaining. --- lib/compress/zstd_preSplit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 8db742c4d..7d9a32c8f 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -48,7 +48,7 @@ static void initStats(void) static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { - const char* p = src; + const char* p = (const char*)src; size_t limit = s - HASHLENGTH + 1; size_t n; assert(s >= HASHLENGTH); @@ -125,7 +125,7 @@ static void removeEvents(FingerPrint* acc, const FingerPrint* slice) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) { - const char* p = src; + const char* p = (const char*)src; int penalty = THRESHOLD_PENALTY; size_t pos = 0; if (srcSize <= blockSizeMax) return srcSize; From fa147cbb4d3fbd8c31b1f35c7984ae62f4c6ea03 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:59:06 -0700 Subject: [PATCH 106/405] more ZSTD_memset() to apply --- lib/compress/zstd_preSplit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 7d9a32c8f..9c84c2b4a 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -60,7 +60,7 @@ static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) static void recordFingerprint(FingerPrint* fp, const void* src, size_t s) { - memset(fp, 0, sizeof(*fp)); + ZSTD_memset(fp, 0, sizeof(*fp)); addToFingerprint(fp, src, s); } @@ -108,7 +108,7 @@ static void flushEvents(void) pastEvents.events[n] = newEvents.events[n]; } pastEvents.nbEvents = newEvents.nbEvents; - memset(&newEvents, 0, sizeof(newEvents)); + ZSTD_memset(&newEvents, 0, sizeof(newEvents)); } static void removeEvents(FingerPrint* acc, const FingerPrint* slice) @@ -139,7 +139,7 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) return pos; } else { mergeEvents(&pastEvents, &newEvents); - memset(&newEvents, 0, sizeof(newEvents)); + ZSTD_memset(&newEvents, 0, sizeof(newEvents)); penalty = penalty - 1 + (penalty == 0); } pos += CHUNKSIZE; From 83a3402a928ef07700b1431c86534bec902ad11d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 12:55:08 -0700 Subject: [PATCH 107/405] fix overlap write scenario in presence of incompressible data --- lib/compress/zstd_compress.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 040333e59..eb7b06df9 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1631,7 +1631,8 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( { ZSTD_compressionParameters cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { - srcSizeHint = CCtxParams->srcSizeHint; + assert(srcSizeHint>=0); + srcSizeHint = (U64)CCtxParams->srcSizeHint; } cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; @@ -4488,14 +4489,18 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" -static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat) +static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { if (srcSize <= 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); (void)strat; if (strat >= ZSTD_btlazy2) return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); - return 92 KB; + /* blind split strategy + * heuristic, just tested as being "generally better" + * do not split incompressible data though: just respect the 3 bytes per block overhead limit. + */ + return savings ? 92 KB : 128 KB; } /*! ZSTD_compress_frameChunk() : @@ -4516,6 +4521,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; + S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); @@ -4526,7 +4532,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); - size_t blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy); + size_t const blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding @@ -4571,7 +4577,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ - + if (cSize < blockSize) savings += (blockSize - cSize); ip += blockSize; assert(remaining >= blockSize); remaining -= blockSize; From f83ed087f6310a8cf51267ea431ec4a7b7ffd94f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 13:21:55 -0700 Subject: [PATCH 108/405] fixed RLE detection test --- lib/compress/zstd_compress.c | 10 +++++----- tests/fuzzer.c | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index eb7b06df9..25a11f070 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4491,14 +4491,14 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - if (srcSize <= 128 KB || blockSizeMax < 128 KB) - return MIN(srcSize, blockSizeMax); - (void)strat; if (strat >= ZSTD_btlazy2) return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + if (srcSize <= 128 KB || blockSizeMax < 128 KB) + return MIN(srcSize, blockSizeMax); /* blind split strategy - * heuristic, just tested as being "generally better" - * do not split incompressible data though: just respect the 3 bytes per block overhead limit. + * no cpu cost, but can over-split homegeneous data. + * heuristic, tested as being "generally better". + * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ return savings ? 92 KB : 128 KB; } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index ead3cc8dd..f5a894354 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3653,16 +3653,19 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_freeDCtx(dctx); } - /* long rle test */ + /* rle detection test: must compress better blocks with a single identical byte repeated */ { size_t sampleSize = 0; - size_t expectedCompressedSize = 39; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */ - DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++); - memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1); - sampleSize += 256 KB - 1; - memset((char*)CNBuffer+sampleSize, 'A', 96 KB); - sampleSize += 96 KB; + size_t maxCompressedSize = 46; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */ + DISPLAYLEVEL(3, "test%3i : RLE detection test : ", testNb++); + memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 2); + sampleSize += 256 KB - 2; + memset((char*)CNBuffer+sampleSize, 'A', 100 KB); + sampleSize += 100 KB; cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1); - if (ZSTD_isError(cSize) || cSize > expectedCompressedSize) goto _output_error; + if (ZSTD_isError(cSize) || cSize > maxCompressedSize) { + DISPLAYLEVEL(4, "error: cSize %u > %u expected ! \n", (unsigned)cSize, (unsigned)maxCompressedSize); + goto _output_error; + } { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize)); if (regenSize!=sampleSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); From 8b3887f579f7e98d09ec3823736b467ceaebbcd1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 13:26:57 -0700 Subject: [PATCH 109/405] fixed kernel build --- lib/compress/zstd_preSplit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 9c84c2b4a..93e77248b 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -8,7 +8,8 @@ * You may select, at your option, one of the above-listed licenses. */ -#include "../common/mem.h" /* U64 */ +#include "../common/mem.h" /* S64 */ +#include "../common/zstd_deps.h" /* ZSTD_memset */ #include "zstd_preSplit.h" From dd38c677ebd680f29afdf4eab5c08d7a01eb8f39 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:41:26 -0700 Subject: [PATCH 110/405] fixed single-library build --- build/single_file_libs/zstd-in.c | 1 + 1 file changed, 1 insertion(+) diff --git a/build/single_file_libs/zstd-in.c b/build/single_file_libs/zstd-in.c index e6fca9e4a..f381ecc4f 100644 --- a/build/single_file_libs/zstd-in.c +++ b/build/single_file_libs/zstd-in.c @@ -69,6 +69,7 @@ #include "compress/zstd_compress_literals.c" #include "compress/zstd_compress_sequences.c" #include "compress/zstd_compress_superblock.c" +#include "compress/zstd_preSplit.c" #include "compress/zstd_compress.c" #include "compress/zstd_double_fast.c" #include "compress/zstd_fast.c" From 0d4b52065791a8e96faf8eb7665cb701b29d186e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:46:47 -0700 Subject: [PATCH 111/405] only split full blocks short term simplification --- lib/compress/zstd_compress.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 25a11f070..11c8ceabd 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4491,10 +4491,15 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + /* note: we currenly only split full blocks (128 KB) + * and when there is more than 128 KB input remaining + */ if (srcSize <= 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); + /* dynamic splitting has a cpu cost for analysis, + * due to that cost it's only used for btlazy2+ strategies */ + if (strat >= ZSTD_btlazy2) + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". From 20c3d176cd8871d01fe8135bdc7693a208d739bc Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:50:46 -0700 Subject: [PATCH 112/405] fix assert --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 11c8ceabd..d9f10f849 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1631,7 +1631,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( { ZSTD_compressionParameters cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { - assert(srcSizeHint>=0); + assert(CCtxParams->srcSizeHint>=0); srcSizeHint = (U64)CCtxParams->srcSizeHint; } cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); From 6dc52122e6e8b28b8477a202726dfff7d0ce0b9c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:52:49 -0700 Subject: [PATCH 113/405] fixed c90 comment style --- lib/compress/zstd_preSplit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 93e77248b..3256905df 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -78,8 +78,9 @@ static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) return distance; } -// Compare newEvents with pastEvents -// return 1 when considered "too different" +/* Compare newEvents with pastEvents + * return 1 when considered "too different" + */ static int compareFingerprints(const FingerPrint* ref, const FingerPrint* newfp, int penalty) From 80a912dec1e5ec1fad6e6a698cfe04685c0d865e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:16:57 -0700 Subject: [PATCH 114/405] fixed zstreamtest --- tests/zstreamtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 2c25adf3c..93032d21e 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -958,7 +958,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) break; out.size = MIN(out.size + cSize / 4, compressedBufferSize); } - CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize)); + CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, out.pos)); DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() ZSTD_c_stableInBuffer modify buffer : ", testNb++); From 6939235f010255bbe513dc5b18b1796cbee39d52 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:35:56 -0700 Subject: [PATCH 115/405] fixed meson build --- build/meson/lib/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/build/meson/lib/meson.build b/build/meson/lib/meson.build index 4ff926f9c..d086fc2d7 100644 --- a/build/meson/lib/meson.build +++ b/build/meson/lib/meson.build @@ -30,6 +30,7 @@ libzstd_sources = [join_paths(zstd_rootdir, 'lib/common/entropy_common.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_compress_literals.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_compress_sequences.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_compress_superblock.c'), + join_paths(zstd_rootdir, 'lib/compress/zstd_preSplit.c'), join_paths(zstd_rootdir, 'lib/compress/zstdmt_compress.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_fast.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_double_fast.c'), From cdddcaaec9111c4ab086a55e4d0337131ca13fd0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:42:02 -0700 Subject: [PATCH 116/405] new Makefile target mesonbuild for easier local testing --- .github/workflows/dev-short-tests.yml | 8 ++++---- Makefile | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 7713a897c..99aa166c9 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -232,10 +232,10 @@ jobs: -Dbin_tests=true \ -Dbin_contrib=true \ -Ddefault_library=both \ - build/meson builddir - ninja -C builddir/ - meson test -C builddir/ --print-errorlogs - meson install -C builddir --destdir staging/ + build/meson mesonBuild + ninja -C mesonBuild/ + meson test -C mesonBuild/ --print-errorlogs + meson install -C mesonBuild --destdir staging/ meson-mingw-cross-compilation: runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 5598cdd03..95d45afb4 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ clean: $(Q)$(MAKE) -C contrib/largeNbDicts $@ > $(VOID) $(Q)$(MAKE) -C contrib/externalSequenceProducer $@ > $(VOID) $(Q)$(RM) zstd$(EXT) zstdmt$(EXT) tmp* - $(Q)$(RM) -r lz4 cmakebuild install + $(Q)$(RM) -r lz4 cmakebuild mesonbuild install @echo Cleaning completed #------------------------------------------------------------------------------ @@ -415,6 +415,24 @@ cmakebuild: $(CMAKE) --build cmakebuild --target install -- -j V=1 cd cmakebuild; ctest -V -L Medium +MESON ?= meson +NINJA ?= ninja + +.PHONY: mesonbuild +mesonbuild: + $(MESON) setup \ + --buildtype=debugoptimized \ + -Db_lundef=false \ + -Dauto_features=enabled \ + -Dbin_programs=true \ + -Dbin_tests=true \ + -Dbin_contrib=true \ + -Ddefault_library=both \ + build/meson mesonbuild + $(NINJA) -C mesonbuild/ + $(MESON) test -C mesonbuild/ --print-errorlogs + $(MESON) install -C mesonbuild --destdir staging/ + .PHONY: c89build gnu90build c99build gnu99build c11build bmix64build bmix32build bmi32build staticAnalyze c89build: clean $(CC) -v From 76ad1d69039c4900e5a0dca8eec7f3da2bebc050 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:44:51 -0700 Subject: [PATCH 117/405] fixed VS2010 solution --- build/VS2010/fullbench/fullbench.vcxproj | 1 + build/VS2010/fuzzer/fuzzer.vcxproj | 1 + build/VS2010/libzstd-dll/libzstd-dll.vcxproj | 1 + build/VS2010/libzstd/libzstd.vcxproj | 1 + build/VS2010/zstd/zstd.vcxproj | 1 + 5 files changed, 5 insertions(+) diff --git a/build/VS2010/fullbench/fullbench.vcxproj b/build/VS2010/fullbench/fullbench.vcxproj index 2e0a042b0..f60cfe726 100644 --- a/build/VS2010/fullbench/fullbench.vcxproj +++ b/build/VS2010/fullbench/fullbench.vcxproj @@ -170,6 +170,7 @@ + diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj index 91974ec7f..ccbd2517d 100644 --- a/build/VS2010/fuzzer/fuzzer.vcxproj +++ b/build/VS2010/fuzzer/fuzzer.vcxproj @@ -170,6 +170,7 @@ + diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj index 97ad2fcb2..6925e0f9e 100644 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj @@ -34,6 +34,7 @@ + diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index 614e6292a..82a2d8268 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -34,6 +34,7 @@ + diff --git a/build/VS2010/zstd/zstd.vcxproj b/build/VS2010/zstd/zstd.vcxproj index 5a5237f0e..0558687f5 100644 --- a/build/VS2010/zstd/zstd.vcxproj +++ b/build/VS2010/zstd/zstd.vcxproj @@ -35,6 +35,7 @@ + From 31d48e9ffadde779e5fd9b290dee44f616b050fa Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 16:23:05 -0700 Subject: [PATCH 118/405] fixing minor formatting issue in 32-bit mode with logs enabled --- lib/compress/zstd_compress_internal.h | 4 ++-- lib/compress/zstd_opt.c | 18 +++++++++--------- lib/decompress/zstd_decompress.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 622903398..042b5e5ca 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -798,8 +798,8 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match, size_t const matchLength = ZSTD_count(ip, match, vEnd); if (match + matchLength != mEnd) return matchLength; DEBUGLOG(7, "ZSTD_count_2segments: found a 2-parts match (current length==%zu)", matchLength); - DEBUGLOG(7, "distance from match beginning to end dictionary = %zi", mEnd - match); - DEBUGLOG(7, "distance from current pos to end buffer = %zi", iEnd - ip); + DEBUGLOG(7, "distance from match beginning to end dictionary = %i", (int)(mEnd - match)); + DEBUGLOG(7, "distance from current pos to end buffer = %i", (int)(iEnd - ip)); DEBUGLOG(7, "next byte : ip==%02X, istart==%02X", ip[matchLength], *iStart); DEBUGLOG(7, "final match length = %zu", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd)); return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 8a4345b31..e4a8ee81e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1197,7 +1197,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, for (cur = 1; cur <= last_pos; cur++) { const BYTE* const inr = ip + cur; assert(cur <= ZSTD_OPT_NUM); - DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur); + DEBUGLOG(7, "cPos:%i==rPos:%u", (int)(inr-istart), cur); /* Fix current position with one literal if cheaper */ { U32 const litlen = opt[cur-1].litlen + 1; @@ -1207,8 +1207,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, assert(price < 1000000000); /* overflow check */ if (price <= opt[cur].price) { ZSTD_optimal_t const prevMatch = opt[cur]; - DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)", - inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen, + DEBUGLOG(7, "cPos:%i==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)", + (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen, opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]); opt[cur] = opt[cur-1]; opt[cur].litlen = litlen; @@ -1240,8 +1240,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } } } else { - DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f)", - inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price)); + DEBUGLOG(7, "cPos:%i==rPos:%u : literal would cost more (%.2f>%.2f)", + (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price)); } } @@ -1284,8 +1284,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } { U32 const longestML = matches[nbMatches-1].len; - DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of longest ML=%u", - inr-istart, cur, nbMatches, longestML); + DEBUGLOG(7, "cPos:%i==rPos:%u, found %u matches, of longest ML=%u", + (int)(inr-istart), cur, nbMatches, longestML); if ( (longestML > sufficient_len) || (cur + longestML >= ZSTD_OPT_NUM) @@ -1411,8 +1411,8 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ U32 const mlen = opt[storePos].mlen; U32 const offBase = opt[storePos].off; U32 const advance = llen + mlen; - DEBUGLOG(6, "considering seq starting at %zi, llen=%u, mlen=%u", - anchor - istart, (unsigned)llen, (unsigned)mlen); + DEBUGLOG(6, "considering seq starting at %i, llen=%u, mlen=%u", + (int)(anchor - istart), (unsigned)llen, (unsigned)mlen); if (mlen==0) { /* only literals => must be last "sequence", actually starting a new stream of sequences */ assert(storePos == storeEnd); /* must be last sequence */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 26c9457fb..6aac5dd3f 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1057,7 +1057,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, } ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0); /* Allow caller to get size read */ - DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr); + DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %i, consuming %i bytes of input", (int)(op-ostart), (int)(ip - (const BYTE*)*srcPtr)); *srcPtr = ip; *srcSizePtr = remainingSrcSize; return (size_t)(op-ostart); From 7f015c2fd799d3c273c5986a63059ef9536b701e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 17:05:17 -0700 Subject: [PATCH 119/405] replaced uasan32 test by asan32 test --- .github/workflows/dev-long-tests.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index deb5242b0..fa603e401 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -156,15 +156,30 @@ jobs: make libc6install CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest - clang-asan-ubsan-fuzz32: + clang-asan-fuzz32: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: clang + ASan + UBSan + Fuzz Test 32bit + - name: clang + ASan + Fuzz Test 32bit run: | sudo apt-get -qqq update make libc6install - CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest + CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make asan-fuzztest + +# The following test seems to have issues on github CI specifically, +# it does not provide the `__mulodi4` instruction emulation +# required for signed 64-bit multiplication. +# Replaced by asan-only test (above) +# +# clang-asan-ubsan-fuzz32: +# runs-on: ubuntu-20.04 +# steps: +# - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 +# - name: clang + ASan + UBSan + Fuzz Test 32bit +# run: | +# sudo apt-get -qqq update +# make libc6install +# CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest asan-ubsan-regression: runs-on: ubuntu-20.04 From 73a665365350668757ec542277472ca73267603a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 18:40:47 -0700 Subject: [PATCH 120/405] ZSTD_splitBlock_4k() uses externally provided workspace ideally, this workspace would be provided from the ZSTD_CCtx* state --- lib/compress/zstd_compress.c | 9 +++++--- lib/compress/zstd_preSplit.c | 43 ++++++++++++++++++++---------------- lib/compress/zstd_preSplit.h | 8 ++++++- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d9f10f849..37b87336c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4489,8 +4489,11 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" -static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) + +static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { + S64 workspace[ZSTD_SLIPBLOCK_WORKSPACESIZE / 8]; + (void)cctx; /* note: we currenly only split full blocks (128 KB) * and when there is more than 128 KB input remaining */ @@ -4499,7 +4502,7 @@ static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t bloc /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for btlazy2+ strategies */ if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, workspace, sizeof(workspace)); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". @@ -4537,7 +4540,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); - size_t const blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); + size_t const blockSize = ZSTD_optimalBlockSize(cctx, ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 3256905df..ba9dc6487 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -10,6 +10,7 @@ #include "../common/mem.h" /* S64 */ #include "../common/zstd_deps.h" /* ZSTD_memset */ +#include "../common/zstd_internal.h" /* ZSTD_STATIC_ASSERT */ #include "zstd_preSplit.h" @@ -30,22 +31,19 @@ static unsigned hash2(const void *p) } -/* ==================================== */ -/* Global array -> for testing only !!! */ -/* ==================================== */ typedef struct { int events[HASHTABLESIZE]; S64 nbEvents; } FingerPrint; -static FingerPrint pastEvents; -static FingerPrint newEvents; +typedef struct { + FingerPrint pastEvents; + FingerPrint newEvents; +} FPStats; -static void initStats(void) +static void initStats(FPStats* fpstats) { - ZSTD_memset(&pastEvents, 0, sizeof(pastEvents)); - ZSTD_memset(&newEvents, 0, sizeof(newEvents)); + ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -/* ==================================== */ static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { @@ -103,14 +101,14 @@ static void mergeEvents(FingerPrint* acc, const FingerPrint* newfp) acc->nbEvents += newfp->nbEvents; } -static void flushEvents(void) +static void flushEvents(FPStats* fpstats) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { - pastEvents.events[n] = newEvents.events[n]; + fpstats->pastEvents.events[n] = fpstats->newEvents.events[n]; } - pastEvents.nbEvents = newEvents.nbEvents; - ZSTD_memset(&newEvents, 0, sizeof(newEvents)); + fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents; + ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); } static void removeEvents(FingerPrint* acc, const FingerPrint* slice) @@ -125,23 +123,30 @@ static void removeEvents(FingerPrint* acc, const FingerPrint* slice) #define CHUNKSIZE (8 << 10) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, + size_t blockSizeMax, + void* workspace, size_t wkspSize) { + FPStats* const fpstats = (FPStats*)workspace; const char* p = (const char*)src; int penalty = THRESHOLD_PENALTY; size_t pos = 0; if (srcSize <= blockSizeMax) return srcSize; assert(blockSizeMax == (128 << 10)); + assert(workspace != NULL); + assert((size_t)workspace % 8 == 0); + ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE == sizeof(FPStats)); + assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; - initStats(); + initStats(fpstats); for (pos = 0; pos < blockSizeMax;) { assert(pos <= blockSizeMax - CHUNKSIZE); - recordFingerprint(&newEvents, p + pos, CHUNKSIZE); - if (compareFingerprints(&pastEvents, &newEvents, penalty)) { + recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE); + if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; } else { - mergeEvents(&pastEvents, &newEvents); - ZSTD_memset(&newEvents, 0, sizeof(newEvents)); + mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); + ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); penalty = penalty - 1 + (penalty == 0); } pos += CHUNKSIZE; diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 148fc1936..b0b6bb762 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -17,7 +17,13 @@ extern "C" { #endif -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax); +#define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 + +/* note: + * @workspace must be aligned on 8-bytes boundaries + * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE + */ +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax, void* workspace, size_t wkspSize); #if defined (__cplusplus) } From 433f4598ad96a4e661cfd877b50c9000ea174897 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 11:16:49 -0700 Subject: [PATCH 121/405] fixed minor conversion warnings on Visual --- tests/zstreamtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 93032d21e..8df86d985 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -441,7 +441,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize); if (gfhError!=0) goto _output_error; DISPLAYLEVEL(5, " (windowSize : %u) ", (unsigned)fhi.windowSize); - { size_t const s = ZSTD_estimateDStreamSize(fhi.windowSize) + { size_t const s = ZSTD_estimateDStreamSize((size_t)fhi.windowSize) /* uses ZSTD_initDStream_usingDict() */ + ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy); if (ZSTD_isError(s)) goto _output_error; @@ -1551,7 +1551,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : check dictionary FSE tables can represent every code : ", testNb++); { unsigned const kMaxWindowLog = 24; unsigned value; - ZSTD_compressionParameters cParams = ZSTD_getCParams(3, 1U << kMaxWindowLog, 1024); + ZSTD_compressionParameters cParams = ZSTD_getCParams(3, 1ULL << kMaxWindowLog, 1024); ZSTD_CDict* cdict; ZSTD_DDict* ddict; SEQ_stream seq = SEQ_initStream(0x87654321); From 4685eafa81d4c31048577aeb461883043ca96c2f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 11:20:54 -0700 Subject: [PATCH 122/405] fix alignment test for non 64-bit systems --- lib/compress/zstd_preSplit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index ba9dc6487..ceac5c91f 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -8,6 +8,7 @@ * You may select, at your option, one of the above-listed licenses. */ +#include "../common/compiler.h" /* ZSTD_ALIGNOF */ #include "../common/mem.h" /* S64 */ #include "../common/zstd_deps.h" /* ZSTD_memset */ #include "../common/zstd_internal.h" /* ZSTD_STATIC_ASSERT */ @@ -134,7 +135,7 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, if (srcSize <= blockSizeMax) return srcSize; assert(blockSizeMax == (128 << 10)); assert(workspace != NULL); - assert((size_t)workspace % 8 == 0); + assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0); ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE == sizeof(FPStats)); assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; From cae8d13294904c0b6095a5533d0cda72d7e6a7ff Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 16:00:36 -0700 Subject: [PATCH 123/405] splitter workspace is now provided by ZSTD_CCtx* --- lib/compress/zstd_compress.c | 59 ++++++++++++------------- lib/compress/zstd_compress_internal.h | 5 ++- lib/compress/zstd_compress_superblock.c | 4 +- lib/compress/zstd_cwksp.h | 36 ++++++++++----- 4 files changed, 60 insertions(+), 44 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 37b87336c..40d3afaae 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -137,11 +137,12 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) ZSTD_cwksp_move(&cctx->workspace, &ws); cctx->staticSize = workspaceSize; - /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ + /* statically sized space. tmpWorkspace never moves (but prev/next block swap places) */ if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE); + cctx->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(&cctx->workspace, TMP_WORKSPACE_SIZE, sizeof(S64)); + cctx->tmpWkspSize = TMP_WORKSPACE_SIZE; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; } @@ -1661,14 +1662,14 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, + hSize * sizeof(U32) + h3Size * sizeof(U32); size_t const optPotentialSpace = - ZSTD_cwksp_aligned_alloc_size((MaxML+1) * sizeof(U32)) - + ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32)) - + ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32)) - + ZSTD_cwksp_aligned_alloc_size((1<strategy, useRowMatchFinder) - ? ZSTD_cwksp_aligned_alloc_size(hSize) + ? ZSTD_cwksp_aligned64_alloc_size(hSize) : 0; size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt)) ? optPotentialSpace @@ -1706,16 +1707,16 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer); size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef)) + + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(seqDef)) + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE); + size_t const tmpWorkSpace = ZSTD_cwksp_aligned_alloc_size(TMP_WORKSPACE_SIZE, sizeof(S64)); size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams); size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize); size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ? - ZSTD_cwksp_aligned_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; + ZSTD_cwksp_aligned64_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) @@ -1725,12 +1726,12 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize); size_t const externalSeqSpace = useSequenceProducer - ? ZSTD_cwksp_aligned_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence)) + ? ZSTD_cwksp_aligned64_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence)) : 0; size_t const neededSpace = cctxSpace + - entropySpace + + tmpWorkSpace + blockStateSpace + ldmSpace + ldmSeqSpace + @@ -2166,15 +2167,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, DEBUGLOG(5, "reserving object space"); /* Statically sized space. - * entropyWorkspace never moves, + * tmpWorkspace never moves, * though prev/next block swap places */ assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t))); zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE); - RETURN_ERROR_IF(zc->entropyWorkspace == NULL, memory_allocation, "couldn't allocate entropyWorkspace"); + zc->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(ws, TMP_WORKSPACE_SIZE, sizeof(S64)); + RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, "couldn't allocate tmpWorkspace"); + zc->tmpWkspSize = TMP_WORKSPACE_SIZE; } } ZSTD_cwksp_clear(ws); @@ -3894,14 +3896,14 @@ ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CC &zc->blockState.nextCBlock->entropy, &zc->appliedParams, entropyMetadata, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE), ""); + zc->tmpWorkspace, zc->tmpWkspSize), ""); return ZSTD_estimateBlockSize( seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart), seqStore->ofCode, seqStore->llCode, seqStore->mlCode, (size_t)(seqStore->sequences - seqStore->sequencesStart), &zc->blockState.nextCBlock->entropy, entropyMetadata, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE, + zc->tmpWorkspace, zc->tmpWkspSize, (int)(entropyMetadata->hufMetadata.hType == set_compressed), 1); } @@ -4067,7 +4069,7 @@ ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, &zc->appliedParams, op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize, srcSize, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */, zc->bmi2); FORWARD_IF_ERROR(cSeqsSize, "ZSTD_entropyCompressSeqStore failed!"); @@ -4357,7 +4359,7 @@ ZSTD_compressBlock_internal(ZSTD_CCtx* zc, &zc->appliedParams, dst, dstCapacity, srcSize, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */, zc->bmi2); if (frame && @@ -4489,20 +4491,17 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" - static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - S64 workspace[ZSTD_SLIPBLOCK_WORKSPACESIZE / 8]; - (void)cctx; - /* note: we currenly only split full blocks (128 KB) - * and when there is more than 128 KB input remaining + /* note: conservatively only split full blocks (128 KB) currently, + * and even then only if there is more than 128 KB input remaining. */ if (srcSize <= 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for btlazy2+ strategies */ if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, workspace, sizeof(workspace)); + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". @@ -5174,11 +5173,11 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, cdict->dictContentSize, cdict->dictContentType, dtlm, - ZSTD_tfp_forCCtx, cctx->entropyWorkspace) + ZSTD_tfp_forCCtx, cctx->tmpWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, - dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->entropyWorkspace); + dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->tmpWorkspace); FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); assert(dictID <= UINT_MAX); cctx->dictID = (U32)dictID; @@ -6876,7 +6875,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, &cctx->appliedParams, op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, blockSize, - cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */, cctx->bmi2); FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 042b5e5ca..e76bbda71 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -24,6 +24,7 @@ # include "zstdmt_compress.h" #endif #include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */ +#include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */ #if defined (__cplusplus) extern "C" { @@ -376,6 +377,7 @@ struct ZSTD_CCtx_params_s { #define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2)) #define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE) +#define TMP_WORKSPACE_SIZE (MAX(ENTROPY_WORKSPACE_SIZE, ZSTD_SLIPBLOCK_WORKSPACESIZE)) /** * Indicates whether this compression proceeds directly from user-provided @@ -432,7 +434,8 @@ struct ZSTD_CCtx_s { size_t maxNbLdmSequences; rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ ZSTD_blockState_t blockState; - U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */ + void* tmpWorkspace; /* used as substitute of stack space - must be aligned for S64 type */ + size_t tmpWkspSize; /* Whether we are streaming or not */ ZSTD_buffered_policy_e bufferedPolicy; diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 628a2dccd..97321bc76 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -674,7 +674,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, &entropyMetadata, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */), ""); return ZSTD_compressSubBlock_multi(&zc->seqStore, zc->blockState.prevCBlock, @@ -684,5 +684,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, dst, dstCapacity, src, srcSize, zc->bmi2, lastBlock, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */); + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */); } diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index dcd485cb5..239fcf6d2 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -222,7 +222,7 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { * to figure out how much space you need for the matchState tables. Everything * else is though. * - * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size(). + * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned64_alloc_size(). */ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { if (size == 0) @@ -234,12 +234,16 @@ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { #endif } +MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size, size_t alignment) { + return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, alignment)); +} + /** * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes. * Used to determine the number of bytes required for a given "aligned". */ -MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) { - return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES)); +MEM_STATIC size_t ZSTD_cwksp_aligned64_alloc_size(size_t size) { + return ZSTD_cwksp_aligned_alloc_size(size, ZSTD_CWKSP_ALIGNMENT_BYTES); } /** @@ -272,7 +276,7 @@ MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignByt * which we can allocate from the end of the workspace. */ MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) { - return (void*)((size_t)ws->workspaceEnd & ~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); + return (void*)((size_t)ws->workspaceEnd & (size_t)~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); } /** @@ -426,8 +430,9 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t byt */ MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) { - void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), - ZSTD_cwksp_alloc_aligned); + void* const ptr = ZSTD_cwksp_reserve_internal(ws, + ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), + ZSTD_cwksp_alloc_aligned); assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); return ptr; } @@ -479,12 +484,12 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) } /** - * Aligned on sizeof(void*). * Note : should happen only once, at workspace first initialization */ -MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +MEM_STATIC void* +ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment) { - size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*)); + size_t const roundedBytes = ZSTD_cwksp_align(bytes, alignment); void* alloc = ws->objectEnd; void* end = (BYTE*)alloc + roundedBytes; @@ -496,8 +501,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) DEBUGLOG(4, "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining", alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes); - assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0); - assert(bytes % ZSTD_ALIGNOF(void*) == 0); + assert((size_t)alloc % alignment == 0); + assert(bytes % alignment == 0); ZSTD_cwksp_assert_internal_consistency(ws); /* we must be in the first phase, no advance is possible */ if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) { @@ -521,6 +526,15 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) return alloc; } +/** + * Aligned on sizeof(void*). + * Note : should happen only once, at workspace first initialization + */ +MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +{ + return ZSTD_cwksp_reserve_object_aligned(ws, bytes, sizeof(void*)); +} + MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty"); From 4ce91cbf2bfecefcd99973a5e68711c388684d41 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 16:47:41 -0700 Subject: [PATCH 124/405] fixed workspace alignment on non 64-bit systems --- lib/common/compiler.h | 2 ++ lib/compress/zstd_compress.c | 22 ++++++++++----------- lib/compress/zstd_cwksp.h | 37 ++++++++++++++++++++---------------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index fdf0dd18a..f4caeb5c0 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -278,6 +278,8 @@ * Alignment check *****************************************************************/ +#define ZSTD_IS_POWER_2(a) (((a) & ((a)-1)) == 0) + /* this test was initially positioned in mem.h, * but this file is removed (or replaced) for linux kernel * so it's now hosted in compiler.h, diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 40d3afaae..fcef55bf1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2032,7 +2032,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, ZSTD_advanceHashSalt(ms); } else { /* When we are not salting we want to always memset the memory */ - ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned(ws, tagTableSize); + ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned64(ws, tagTableSize); ZSTD_memset(ms->tagTable, 0, tagTableSize); ms->hashSalt = 0; } @@ -2046,12 +2046,12 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, /* opt parser space */ if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) { DEBUGLOG(4, "reserving optimal parser space"); - ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned)); - ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned)); - ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned)); - ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t)); - ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t)); + ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (1<opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxLL+1) * sizeof(unsigned)); + ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxML+1) * sizeof(unsigned)); + ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxOff+1) * sizeof(unsigned)); + ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t)); + ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t)); } ms->cParams = *cParams; @@ -2209,15 +2209,15 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, needsIndexReset, ZSTD_resetTarget_CCtx), ""); - zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef)); + zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned64(ws, maxNbSeq * sizeof(seqDef)); /* ldm hash table */ if (params->ldmParams.enableLdm == ZSTD_ps_enable) { /* TODO: avoid memset? */ size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog; - zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t)); + zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned64(ws, ldmHSize * sizeof(ldmEntry_t)); ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); - zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); + zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned64(ws, maxNbLdmSeq * sizeof(rawSeq)); zc->maxNbLdmSequences = maxNbLdmSeq; ZSTD_window_init(&zc->ldmState.window); @@ -2229,7 +2229,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize); zc->extSeqBufCapacity = maxNbExternalSeq; zc->extSeqBuf = - (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence)); + (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned64(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence)); } /* buffers */ diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 239fcf6d2..dc0142098 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -206,9 +206,9 @@ MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) { /** * Align must be a power of 2. */ -MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { +MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) { size_t const mask = align - 1; - assert((align & mask) == 0); + assert(ZSTD_IS_POWER_2(align)); return (size + mask) & ~mask; } @@ -266,7 +266,7 @@ MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) { MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) { size_t const alignBytesMask = alignBytes - 1; size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask; - assert((alignBytes & alignBytesMask) == 0); + assert(ZSTD_IS_POWER_2(alignBytes)); assert(bytes < alignBytes); return bytes; } @@ -408,7 +408,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t byt { size_t const alignedBytes = ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES); void* ptr = ZSTD_cwksp_reserve_internal(ws, alignedBytes, ZSTD_cwksp_alloc_aligned_init_once); - assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); if(ptr && ptr < ws->initOnceStart) { /* We assume the memory following the current allocation is either: * 1. Not usable as initOnce memory (end of workspace) @@ -428,12 +428,12 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t byt /** * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes). */ -MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) +MEM_STATIC void* ZSTD_cwksp_reserve_aligned64(ZSTD_cwksp* ws, size_t bytes) { void* const ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), ZSTD_cwksp_alloc_aligned); - assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); return ptr; } @@ -479,17 +479,17 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) #endif assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); - assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); return alloc; } /** + * Aligned on sizeof(void*). * Note : should happen only once, at workspace first initialization */ -MEM_STATIC void* -ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment) +MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { - size_t const roundedBytes = ZSTD_cwksp_align(bytes, alignment); + size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*)); void* alloc = ws->objectEnd; void* end = (BYTE*)alloc + roundedBytes; @@ -501,8 +501,8 @@ ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment DEBUGLOG(4, "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining", alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes); - assert((size_t)alloc % alignment == 0); - assert(bytes % alignment == 0); + assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0); + assert(bytes % ZSTD_ALIGNOF(void*) == 0); ZSTD_cwksp_assert_internal_consistency(ws); /* we must be in the first phase, no advance is possible */ if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) { @@ -525,14 +525,19 @@ ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment return alloc; } - /** - * Aligned on sizeof(void*). + * with alignment control * Note : should happen only once, at workspace first initialization */ -MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +MEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSize, size_t alignment) { - return ZSTD_cwksp_reserve_object_aligned(ws, bytes, sizeof(void*)); + size_t const mask = alignment - 1; + size_t const surplus = (alignment > sizeof(void*)) ? alignment - sizeof(void*) : 0; + void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus); + if (start == NULL) return NULL; + if (surplus == 0) return start; + assert(ZSTD_IS_POWER_2(alignment)); + return (void*)(((size_t)start + surplus) & ~mask); } MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) From dac26eaeac5f500a3dd2ada7f51fbdbf937ce2ac Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 20 Oct 2024 17:07:43 -0700 Subject: [PATCH 125/405] updated regression test results --- tests/regression/results.csv | 914 +++++++++++++++++------------------ 1 file changed, 457 insertions(+), 457 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index e39abd66d..b32db43de 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -1,63 +1,63 @@ Data, Config, Method, Total compressed size -silesia.tar, level -5, compress simple, 6861055 -silesia.tar, level -3, compress simple, 6505483 -silesia.tar, level -1, compress simple, 6179047 -silesia.tar, level 0, compress simple, 4851407 -silesia.tar, level 1, compress simple, 5327717 -silesia.tar, level 3, compress simple, 4851407 -silesia.tar, level 4, compress simple, 4788821 -silesia.tar, level 5, compress simple, 4679004 -silesia.tar, level 6, compress simple, 4614561 -silesia.tar, level 7, compress simple, 4579828 -silesia.tar, level 9, compress simple, 4555448 -silesia.tar, level 13, compress simple, 4502956 -silesia.tar, level 16, compress simple, 4360385 -silesia.tar, level 19, compress simple, 4260939 -silesia.tar, uncompressed literals, compress simple, 4851407 -silesia.tar, uncompressed literals optimal, compress simple, 4260939 -silesia.tar, huffman literals, compress simple, 6179047 -github.tar, level -5, compress simple, 52115 -github.tar, level -3, compress simple, 45678 -github.tar, level -1, compress simple, 42560 -github.tar, level 0, compress simple, 38884 -github.tar, level 1, compress simple, 39200 -github.tar, level 3, compress simple, 38884 -github.tar, level 4, compress simple, 38880 -github.tar, level 5, compress simple, 39651 -github.tar, level 6, compress simple, 39282 -github.tar, level 7, compress simple, 38005 -github.tar, level 9, compress simple, 36723 +silesia.tar, level -5, compress simple, 6860782 +silesia.tar, level -3, compress simple, 6507448 +silesia.tar, level -1, compress simple, 6175582 +silesia.tar, level 0, compress simple, 4843429 +silesia.tar, level 1, compress simple, 5316794 +silesia.tar, level 3, compress simple, 4843429 +silesia.tar, level 4, compress simple, 4780657 +silesia.tar, level 5, compress simple, 4669650 +silesia.tar, level 6, compress simple, 4604925 +silesia.tar, level 7, compress simple, 4570873 +silesia.tar, level 9, compress simple, 4546477 +silesia.tar, level 13, compress simple, 4486256 +silesia.tar, level 16, compress simple, 4355572 +silesia.tar, level 19, compress simple, 4257629 +silesia.tar, uncompressed literals, compress simple, 4843429 +silesia.tar, uncompressed literals optimal, compress simple, 4257629 +silesia.tar, huffman literals, compress simple, 6175582 +github.tar, level -5, compress simple, 52320 +github.tar, level -3, compress simple, 45823 +github.tar, level -1, compress simple, 42740 +github.tar, level 0, compress simple, 39073 +github.tar, level 1, compress simple, 39444 +github.tar, level 3, compress simple, 39073 +github.tar, level 4, compress simple, 39068 +github.tar, level 5, compress simple, 39808 +github.tar, level 6, compress simple, 39455 +github.tar, level 7, compress simple, 38168 +github.tar, level 9, compress simple, 36897 github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 github.tar, level 19, compress simple, 32262 -github.tar, uncompressed literals, compress simple, 38884 +github.tar, uncompressed literals, compress simple, 39073 github.tar, uncompressed literals optimal, compress simple, 32262 -github.tar, huffman literals, compress simple, 42560 -silesia, level -5, compress cctx, 6857372 -silesia, level -3, compress cctx, 6503412 -silesia, level -1, compress cctx, 6172202 -silesia, level 0, compress cctx, 4839431 -silesia, level 1, compress cctx, 5306632 -silesia, level 3, compress cctx, 4839431 -silesia, level 4, compress cctx, 4776557 -silesia, level 5, compress cctx, 4667668 -silesia, level 6, compress cctx, 4604351 -silesia, level 7, compress cctx, 4570271 -silesia, level 9, compress cctx, 4545850 -silesia, level 13, compress cctx, 4493990 -silesia, level 16, compress cctx, 4359652 -silesia, level 19, compress cctx, 4266582 -silesia, long distance mode, compress cctx, 4839431 -silesia, multithreaded, compress cctx, 4839431 -silesia, multithreaded long distance mode, compress cctx, 4839431 +github.tar, huffman literals, compress simple, 42740 +silesia, level -5, compress cctx, 6857776 +silesia, level -3, compress cctx, 6504756 +silesia, level -1, compress cctx, 6174127 +silesia, level 0, compress cctx, 4838417 +silesia, level 1, compress cctx, 5306931 +silesia, level 3, compress cctx, 4838417 +silesia, level 4, compress cctx, 4775359 +silesia, level 5, compress cctx, 4666524 +silesia, level 6, compress cctx, 4602031 +silesia, level 7, compress cctx, 4567954 +silesia, level 9, compress cctx, 4543669 +silesia, level 13, compress cctx, 4484875 +silesia, level 16, compress cctx, 4356207 +silesia, level 19, compress cctx, 4266751 +silesia, long distance mode, compress cctx, 4838417 +silesia, multithreaded, compress cctx, 4838417 +silesia, multithreaded long distance mode, compress cctx, 4838417 silesia, small window log, compress cctx, 7082907 -silesia, small hash log, compress cctx, 6526141 -silesia, small chain log, compress cctx, 4912197 -silesia, explicit params, compress cctx, 4794318 -silesia, uncompressed literals, compress cctx, 4839431 -silesia, uncompressed literals optimal, compress cctx, 4266582 -silesia, huffman literals, compress cctx, 6172202 -silesia, multithreaded with advanced params, compress cctx, 4839431 +silesia, small hash log, compress cctx, 6524931 +silesia, small chain log, compress cctx, 4912322 +silesia, explicit params, compress cctx, 4792640 +silesia, uncompressed literals, compress cctx, 4838417 +silesia, uncompressed literals optimal, compress cctx, 4266751 +silesia, huffman literals, compress cctx, 6174127 +silesia, multithreaded with advanced params, compress cctx, 4838417 github, level -5, compress cctx, 204407 github, level -5 with dict, compress cctx, 47581 github, level -3, compress cctx, 193253 @@ -97,57 +97,57 @@ github, uncompressed literals, compress github, uncompressed literals optimal, compress cctx, 132879 github, huffman literals, compress cctx, 175468 github, multithreaded with advanced params, compress cctx, 141069 -silesia, level -5, zstdcli, 6857420 -silesia, level -3, zstdcli, 6503460 -silesia, level -1, zstdcli, 6172250 -silesia, level 0, zstdcli, 4839479 -silesia, level 1, zstdcli, 5306680 -silesia, level 3, zstdcli, 4839479 -silesia, level 4, zstdcli, 4776605 -silesia, level 5, zstdcli, 4667716 -silesia, level 6, zstdcli, 4604399 -silesia, level 7, zstdcli, 4570319 -silesia, level 9, zstdcli, 4545898 -silesia, level 13, zstdcli, 4494038 -silesia, level 16, zstdcli, 4359700 -silesia, level 19, zstdcli, 4266630 -silesia, long distance mode, zstdcli, 4831224 -silesia, multithreaded, zstdcli, 4839479 -silesia, multithreaded long distance mode, zstdcli, 4831224 +silesia, level -5, zstdcli, 6856076 +silesia, level -3, zstdcli, 6505583 +silesia, level -1, zstdcli, 6172652 +silesia, level 0, zstdcli, 4838997 +silesia, level 1, zstdcli, 5306179 +silesia, level 3, zstdcli, 4838997 +silesia, level 4, zstdcli, 4775769 +silesia, level 5, zstdcli, 4666931 +silesia, level 6, zstdcli, 4602509 +silesia, level 7, zstdcli, 4568265 +silesia, level 9, zstdcli, 4544068 +silesia, level 13, zstdcli, 4484443 +silesia, level 16, zstdcli, 4357591 +silesia, level 19, zstdcli, 4266865 +silesia, long distance mode, zstdcli, 4830467 +silesia, multithreaded, zstdcli, 4838997 +silesia, multithreaded long distance mode, zstdcli, 4830467 silesia, small window log, zstdcli, 7094528 -silesia, small hash log, zstdcli, 6526189 -silesia, small chain log, zstdcli, 4912245 -silesia, explicit params, zstdcli, 4795840 -silesia, uncompressed literals, zstdcli, 5117005 -silesia, uncompressed literals optimal, zstdcli, 4316928 -silesia, huffman literals, zstdcli, 5321417 -silesia, multithreaded with advanced params, zstdcli, 5117005 -silesia.tar, level -5, zstdcli, 6862049 -silesia.tar, level -3, zstdcli, 6506509 -silesia.tar, level -1, zstdcli, 6179789 -silesia.tar, level 0, zstdcli, 4851482 -silesia.tar, level 1, zstdcli, 5329010 -silesia.tar, level 3, zstdcli, 4851482 -silesia.tar, level 4, zstdcli, 4789729 -silesia.tar, level 5, zstdcli, 4679860 -silesia.tar, level 6, zstdcli, 4615355 -silesia.tar, level 7, zstdcli, 4581791 -silesia.tar, level 9, zstdcli, 4555452 -silesia.tar, level 13, zstdcli, 4502960 -silesia.tar, level 16, zstdcli, 4360389 -silesia.tar, level 19, zstdcli, 4260943 -silesia.tar, no source size, zstdcli, 4851478 -silesia.tar, long distance mode, zstdcli, 4843159 -silesia.tar, multithreaded, zstdcli, 4851482 -silesia.tar, multithreaded long distance mode, zstdcli, 4843159 +silesia, small hash log, zstdcli, 6526639 +silesia, small chain log, zstdcli, 4911746 +silesia, explicit params, zstdcli, 4794378 +silesia, uncompressed literals, zstdcli, 5117843 +silesia, uncompressed literals optimal, zstdcli, 4317311 +silesia, huffman literals, zstdcli, 5320793 +silesia, multithreaded with advanced params, zstdcli, 5117843 +silesia.tar, level -5, zstdcli, 6860173 +silesia.tar, level -3, zstdcli, 6507196 +silesia.tar, level -1, zstdcli, 6177719 +silesia.tar, level 0, zstdcli, 4841906 +silesia.tar, level 1, zstdcli, 5313917 +silesia.tar, level 3, zstdcli, 4841906 +silesia.tar, level 4, zstdcli, 4780121 +silesia.tar, level 5, zstdcli, 4671144 +silesia.tar, level 6, zstdcli, 4606407 +silesia.tar, level 7, zstdcli, 4572666 +silesia.tar, level 9, zstdcli, 4546557 +silesia.tar, level 13, zstdcli, 4491076 +silesia.tar, level 16, zstdcli, 4356959 +silesia.tar, level 19, zstdcli, 4259787 +silesia.tar, no source size, zstdcli, 4841902 +silesia.tar, long distance mode, zstdcli, 4834266 +silesia.tar, multithreaded, zstdcli, 4841906 +silesia.tar, multithreaded long distance mode, zstdcli, 4834266 silesia.tar, small window log, zstdcli, 7100110 -silesia.tar, small hash log, zstdcli, 6529264 -silesia.tar, small chain log, zstdcli, 4917022 -silesia.tar, explicit params, zstdcli, 4821112 -silesia.tar, uncompressed literals, zstdcli, 5118944 -silesia.tar, uncompressed literals optimal, zstdcli, 4308455 -silesia.tar, huffman literals, zstdcli, 5342074 -silesia.tar, multithreaded with advanced params, zstdcli, 5118944 +silesia.tar, small hash log, zstdcli, 6530007 +silesia.tar, small chain log, zstdcli, 4916091 +silesia.tar, explicit params, zstdcli, 4809323 +silesia.tar, uncompressed literals, zstdcli, 5116446 +silesia.tar, uncompressed literals optimal, zstdcli, 4306844 +silesia.tar, huffman literals, zstdcli, 5326463 +silesia.tar, multithreaded with advanced params, zstdcli, 5116446 github, level -5, zstdcli, 206407 github, level -5 with dict, zstdcli, 47832 github, level -3, zstdcli, 195253 @@ -187,115 +187,115 @@ github, uncompressed literals, zstdcli, github, uncompressed literals optimal, zstdcli, 154667 github, huffman literals, zstdcli, 144365 github, multithreaded with advanced params, zstdcli, 167909 -github.tar, level -5, zstdcli, 52119 -github.tar, level -5 with dict, zstdcli, 51101 -github.tar, level -3, zstdcli, 45682 -github.tar, level -3 with dict, zstdcli, 44738 -github.tar, level -1, zstdcli, 42564 -github.tar, level -1 with dict, zstdcli, 41357 -github.tar, level 0, zstdcli, 38888 -github.tar, level 0 with dict, zstdcli, 37999 -github.tar, level 1, zstdcli, 39204 -github.tar, level 1 with dict, zstdcli, 38123 -github.tar, level 3, zstdcli, 38888 -github.tar, level 3 with dict, zstdcli, 37999 -github.tar, level 4, zstdcli, 38884 -github.tar, level 4 with dict, zstdcli, 37952 -github.tar, level 5, zstdcli, 39655 -github.tar, level 5 with dict, zstdcli, 39073 -github.tar, level 6, zstdcli, 39286 -github.tar, level 6 with dict, zstdcli, 38647 -github.tar, level 7, zstdcli, 38009 -github.tar, level 7 with dict, zstdcli, 37861 -github.tar, level 9, zstdcli, 36727 -github.tar, level 9 with dict, zstdcli, 36686 +github.tar, level -5, zstdcli, 52308 +github.tar, level -5 with dict, zstdcli, 51318 +github.tar, level -3, zstdcli, 45815 +github.tar, level -3 with dict, zstdcli, 44883 +github.tar, level -1, zstdcli, 42688 +github.tar, level -1 with dict, zstdcli, 41510 +github.tar, level 0, zstdcli, 39071 +github.tar, level 0 with dict, zstdcli, 38140 +github.tar, level 1, zstdcli, 39404 +github.tar, level 1 with dict, zstdcli, 38320 +github.tar, level 3, zstdcli, 39071 +github.tar, level 3 with dict, zstdcli, 38140 +github.tar, level 4, zstdcli, 39067 +github.tar, level 4 with dict, zstdcli, 38082 +github.tar, level 5, zstdcli, 39815 +github.tar, level 5 with dict, zstdcli, 39221 +github.tar, level 6, zstdcli, 39455 +github.tar, level 6 with dict, zstdcli, 38787 +github.tar, level 7, zstdcli, 38177 +github.tar, level 7 with dict, zstdcli, 38009 +github.tar, level 9, zstdcli, 36893 +github.tar, level 9 with dict, zstdcli, 36827 github.tar, level 13, zstdcli, 35505 github.tar, level 13 with dict, zstdcli, 37134 github.tar, level 16, zstdcli, 40470 github.tar, level 16 with dict, zstdcli, 33379 github.tar, level 19, zstdcli, 32266 github.tar, level 19 with dict, zstdcli, 32705 -github.tar, no source size, zstdcli, 38885 -github.tar, no source size with dict, zstdcli, 38115 -github.tar, long distance mode, zstdcli, 40227 -github.tar, multithreaded, zstdcli, 38888 -github.tar, multithreaded long distance mode, zstdcli, 40227 +github.tar, no source size, zstdcli, 39068 +github.tar, no source size with dict, zstdcli, 38274 +github.tar, long distance mode, zstdcli, 40381 +github.tar, multithreaded, zstdcli, 39071 +github.tar, multithreaded long distance mode, zstdcli, 40381 github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 -github.tar, explicit params, zstdcli, 41385 -github.tar, uncompressed literals, zstdcli, 41566 +github.tar, explicit params, zstdcli, 41588 +github.tar, uncompressed literals, zstdcli, 41704 github.tar, uncompressed literals optimal, zstdcli, 35360 -github.tar, huffman literals, zstdcli, 38857 -github.tar, multithreaded with advanced params, zstdcli, 41566 -silesia, level -5, advanced one pass, 6857372 -silesia, level -3, advanced one pass, 6503412 -silesia, level -1, advanced one pass, 6172202 -silesia, level 0, advanced one pass, 4839431 -silesia, level 1, advanced one pass, 5306632 -silesia, level 3, advanced one pass, 4839431 -silesia, level 4, advanced one pass, 4776557 -silesia, level 5 row 1, advanced one pass, 4667668 -silesia, level 5 row 2, advanced one pass, 4670326 -silesia, level 5, advanced one pass, 4667668 -silesia, level 6, advanced one pass, 4604351 -silesia, level 7 row 1, advanced one pass, 4570271 -silesia, level 7 row 2, advanced one pass, 4565169 -silesia, level 7, advanced one pass, 4570271 -silesia, level 9, advanced one pass, 4545850 -silesia, level 11 row 1, advanced one pass, 4505658 -silesia, level 11 row 2, advanced one pass, 4503429 -silesia, level 12 row 1, advanced one pass, 4505658 -silesia, level 12 row 2, advanced one pass, 4503429 -silesia, level 13, advanced one pass, 4493990 -silesia, level 16, advanced one pass, 4359652 -silesia, level 19, advanced one pass, 4266582 -silesia, no source size, advanced one pass, 4839431 -silesia, long distance mode, advanced one pass, 4831158 -silesia, multithreaded, advanced one pass, 4839431 -silesia, multithreaded long distance mode, advanced one pass, 4831176 +github.tar, huffman literals, zstdcli, 39046 +github.tar, multithreaded with advanced params, zstdcli, 41704 +silesia, level -5, advanced one pass, 6857776 +silesia, level -3, advanced one pass, 6504756 +silesia, level -1, advanced one pass, 6174127 +silesia, level 0, advanced one pass, 4838417 +silesia, level 1, advanced one pass, 5306931 +silesia, level 3, advanced one pass, 4838417 +silesia, level 4, advanced one pass, 4775359 +silesia, level 5 row 1, advanced one pass, 4666524 +silesia, level 5 row 2, advanced one pass, 4668976 +silesia, level 5, advanced one pass, 4666524 +silesia, level 6, advanced one pass, 4602031 +silesia, level 7 row 1, advanced one pass, 4567954 +silesia, level 7 row 2, advanced one pass, 4562774 +silesia, level 7, advanced one pass, 4567954 +silesia, level 9, advanced one pass, 4543669 +silesia, level 11 row 1, advanced one pass, 4503577 +silesia, level 11 row 2, advanced one pass, 4501229 +silesia, level 12 row 1, advanced one pass, 4503577 +silesia, level 12 row 2, advanced one pass, 4501229 +silesia, level 13, advanced one pass, 4484875 +silesia, level 16, advanced one pass, 4356207 +silesia, level 19, advanced one pass, 4266751 +silesia, no source size, advanced one pass, 4838417 +silesia, long distance mode, advanced one pass, 4830097 +silesia, multithreaded, advanced one pass, 4838949 +silesia, multithreaded long distance mode, advanced one pass, 4830419 silesia, small window log, advanced one pass, 7094480 -silesia, small hash log, advanced one pass, 6526141 -silesia, small chain log, advanced one pass, 4912197 -silesia, explicit params, advanced one pass, 4795840 -silesia, uncompressed literals, advanced one pass, 5116957 -silesia, uncompressed literals optimal, advanced one pass, 4316880 -silesia, huffman literals, advanced one pass, 5321369 -silesia, multithreaded with advanced params, advanced one pass, 5116957 -silesia.tar, level -5, advanced one pass, 6861055 -silesia.tar, level -3, advanced one pass, 6505483 -silesia.tar, level -1, advanced one pass, 6179047 -silesia.tar, level 0, advanced one pass, 4851407 -silesia.tar, level 1, advanced one pass, 5327717 -silesia.tar, level 3, advanced one pass, 4851407 -silesia.tar, level 4, advanced one pass, 4788821 -silesia.tar, level 5 row 1, advanced one pass, 4679004 -silesia.tar, level 5 row 2, advanced one pass, 4682334 -silesia.tar, level 5, advanced one pass, 4679004 -silesia.tar, level 6, advanced one pass, 4614561 -silesia.tar, level 7 row 1, advanced one pass, 4579828 -silesia.tar, level 7 row 2, advanced one pass, 4575602 -silesia.tar, level 7, advanced one pass, 4579828 -silesia.tar, level 9, advanced one pass, 4555448 -silesia.tar, level 11 row 1, advanced one pass, 4514962 -silesia.tar, level 11 row 2, advanced one pass, 4513816 -silesia.tar, level 12 row 1, advanced one pass, 4514517 -silesia.tar, level 12 row 2, advanced one pass, 4514007 -silesia.tar, level 13, advanced one pass, 4502956 -silesia.tar, level 16, advanced one pass, 4360385 -silesia.tar, level 19, advanced one pass, 4260939 -silesia.tar, no source size, advanced one pass, 4851407 -silesia.tar, long distance mode, advanced one pass, 4837775 -silesia.tar, multithreaded, advanced one pass, 4851478 -silesia.tar, multithreaded long distance mode, advanced one pass, 4843155 +silesia, small hash log, advanced one pass, 6524931 +silesia, small chain log, advanced one pass, 4912322 +silesia, explicit params, advanced one pass, 4794219 +silesia, uncompressed literals, advanced one pass, 5117482 +silesia, uncompressed literals optimal, advanced one pass, 4317186 +silesia, huffman literals, advanced one pass, 5321686 +silesia, multithreaded with advanced params, advanced one pass, 5117795 +silesia.tar, level -5, advanced one pass, 6860782 +silesia.tar, level -3, advanced one pass, 6507448 +silesia.tar, level -1, advanced one pass, 6175582 +silesia.tar, level 0, advanced one pass, 4843429 +silesia.tar, level 1, advanced one pass, 5316794 +silesia.tar, level 3, advanced one pass, 4843429 +silesia.tar, level 4, advanced one pass, 4780657 +silesia.tar, level 5 row 1, advanced one pass, 4669650 +silesia.tar, level 5 row 2, advanced one pass, 4673119 +silesia.tar, level 5, advanced one pass, 4669650 +silesia.tar, level 6, advanced one pass, 4604925 +silesia.tar, level 7 row 1, advanced one pass, 4570873 +silesia.tar, level 7 row 2, advanced one pass, 4566314 +silesia.tar, level 7, advanced one pass, 4570873 +silesia.tar, level 9, advanced one pass, 4546477 +silesia.tar, level 11 row 1, advanced one pass, 4505875 +silesia.tar, level 11 row 2, advanced one pass, 4504435 +silesia.tar, level 12 row 1, advanced one pass, 4505461 +silesia.tar, level 12 row 2, advanced one pass, 4504644 +silesia.tar, level 13, advanced one pass, 4486256 +silesia.tar, level 16, advanced one pass, 4355572 +silesia.tar, level 19, advanced one pass, 4257629 +silesia.tar, no source size, advanced one pass, 4843429 +silesia.tar, long distance mode, advanced one pass, 4830453 +silesia.tar, multithreaded, advanced one pass, 4841902 +silesia.tar, multithreaded long distance mode, advanced one pass, 4834262 silesia.tar, small window log, advanced one pass, 7100064 -silesia.tar, small hash log, advanced one pass, 6529206 -silesia.tar, small chain log, advanced one pass, 4917041 -silesia.tar, explicit params, advanced one pass, 4807274 -silesia.tar, uncompressed literals, advanced one pass, 5118848 -silesia.tar, uncompressed literals optimal, advanced one pass, 4308451 -silesia.tar, huffman literals, advanced one pass, 5341705 -silesia.tar, multithreaded with advanced params, advanced one pass, 5118940 +silesia.tar, small hash log, advanced one pass, 6530222 +silesia.tar, small chain log, advanced one pass, 4915689 +silesia.tar, explicit params, advanced one pass, 4797958 +silesia.tar, uncompressed literals, advanced one pass, 5116329 +silesia.tar, uncompressed literals optimal, advanced one pass, 4306289 +silesia.tar, huffman literals, advanced one pass, 5331382 +silesia.tar, multithreaded with advanced params, advanced one pass, 5116442 github, level -5, advanced one pass, 204407 github, level -5 with dict, advanced one pass, 45832 github, level -3, advanced one pass, 193253 @@ -421,100 +421,100 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced one pass, 152667 github, huffman literals, advanced one pass, 142365 github, multithreaded with advanced params, advanced one pass, 165909 -github.tar, level -5, advanced one pass, 52115 -github.tar, level -5 with dict, advanced one pass, 51097 -github.tar, level -3, advanced one pass, 45678 -github.tar, level -3 with dict, advanced one pass, 44734 -github.tar, level -1, advanced one pass, 42560 -github.tar, level -1 with dict, advanced one pass, 41353 -github.tar, level 0, advanced one pass, 38884 -github.tar, level 0 with dict, advanced one pass, 37995 -github.tar, level 0 with dict dms, advanced one pass, 38114 -github.tar, level 0 with dict dds, advanced one pass, 38114 -github.tar, level 0 with dict copy, advanced one pass, 37995 -github.tar, level 0 with dict load, advanced one pass, 37956 -github.tar, level 1, advanced one pass, 39200 -github.tar, level 1 with dict, advanced one pass, 38119 -github.tar, level 1 with dict dms, advanced one pass, 38406 -github.tar, level 1 with dict dds, advanced one pass, 38406 -github.tar, level 1 with dict copy, advanced one pass, 38119 -github.tar, level 1 with dict load, advanced one pass, 38364 -github.tar, level 3, advanced one pass, 38884 -github.tar, level 3 with dict, advanced one pass, 37995 -github.tar, level 3 with dict dms, advanced one pass, 38114 -github.tar, level 3 with dict dds, advanced one pass, 38114 -github.tar, level 3 with dict copy, advanced one pass, 37995 -github.tar, level 3 with dict load, advanced one pass, 37956 -github.tar, level 4, advanced one pass, 38880 -github.tar, level 4 with dict, advanced one pass, 37948 -github.tar, level 4 with dict dms, advanced one pass, 37995 -github.tar, level 4 with dict dds, advanced one pass, 37995 -github.tar, level 4 with dict copy, advanced one pass, 37948 -github.tar, level 4 with dict load, advanced one pass, 37927 -github.tar, level 5 row 1, advanced one pass, 39651 -github.tar, level 5 row 1 with dict dms, advanced one pass, 39043 -github.tar, level 5 row 1 with dict dds, advanced one pass, 39069 -github.tar, level 5 row 1 with dict copy, advanced one pass, 39145 -github.tar, level 5 row 1 with dict load, advanced one pass, 39000 -github.tar, level 5 row 2, advanced one pass, 39701 -github.tar, level 5 row 2 with dict dms, advanced one pass, 39365 -github.tar, level 5 row 2 with dict dds, advanced one pass, 39233 -github.tar, level 5 row 2 with dict copy, advanced one pass, 39715 -github.tar, level 5 row 2 with dict load, advanced one pass, 39158 -github.tar, level 5, advanced one pass, 39651 -github.tar, level 5 with dict, advanced one pass, 39145 -github.tar, level 5 with dict dms, advanced one pass, 39043 -github.tar, level 5 with dict dds, advanced one pass, 39069 -github.tar, level 5 with dict copy, advanced one pass, 39145 -github.tar, level 5 with dict load, advanced one pass, 39000 -github.tar, level 6, advanced one pass, 39282 -github.tar, level 6 with dict, advanced one pass, 38656 -github.tar, level 6 with dict dms, advanced one pass, 38640 -github.tar, level 6 with dict dds, advanced one pass, 38643 -github.tar, level 6 with dict copy, advanced one pass, 38656 -github.tar, level 6 with dict load, advanced one pass, 38647 -github.tar, level 7 row 1, advanced one pass, 38005 -github.tar, level 7 row 1 with dict dms, advanced one pass, 37832 -github.tar, level 7 row 1 with dict dds, advanced one pass, 37857 -github.tar, level 7 row 1 with dict copy, advanced one pass, 37839 -github.tar, level 7 row 1 with dict load, advanced one pass, 37286 -github.tar, level 7 row 2, advanced one pass, 38077 -github.tar, level 7 row 2 with dict dms, advanced one pass, 38012 -github.tar, level 7 row 2 with dict dds, advanced one pass, 38014 -github.tar, level 7 row 2 with dict copy, advanced one pass, 38101 -github.tar, level 7 row 2 with dict load, advanced one pass, 37402 -github.tar, level 7, advanced one pass, 38005 -github.tar, level 7 with dict, advanced one pass, 37839 -github.tar, level 7 with dict dms, advanced one pass, 37832 -github.tar, level 7 with dict dds, advanced one pass, 37857 -github.tar, level 7 with dict copy, advanced one pass, 37839 -github.tar, level 7 with dict load, advanced one pass, 37286 -github.tar, level 9, advanced one pass, 36723 -github.tar, level 9 with dict, advanced one pass, 36531 -github.tar, level 9 with dict dms, advanced one pass, 36615 -github.tar, level 9 with dict dds, advanced one pass, 36682 -github.tar, level 9 with dict copy, advanced one pass, 36531 -github.tar, level 9 with dict load, advanced one pass, 36322 -github.tar, level 11 row 1, advanced one pass, 36085 +github.tar, level -5, advanced one pass, 52320 +github.tar, level -5 with dict, advanced one pass, 51321 +github.tar, level -3, advanced one pass, 45823 +github.tar, level -3 with dict, advanced one pass, 44882 +github.tar, level -1, advanced one pass, 42740 +github.tar, level -1 with dict, advanced one pass, 41506 +github.tar, level 0, advanced one pass, 39073 +github.tar, level 0 with dict, advanced one pass, 38146 +github.tar, level 0 with dict dms, advanced one pass, 38262 +github.tar, level 0 with dict dds, advanced one pass, 38262 +github.tar, level 0 with dict copy, advanced one pass, 38146 +github.tar, level 0 with dict load, advanced one pass, 38107 +github.tar, level 1, advanced one pass, 39444 +github.tar, level 1 with dict, advanced one pass, 38338 +github.tar, level 1 with dict dms, advanced one pass, 38641 +github.tar, level 1 with dict dds, advanced one pass, 38641 +github.tar, level 1 with dict copy, advanced one pass, 38338 +github.tar, level 1 with dict load, advanced one pass, 38592 +github.tar, level 3, advanced one pass, 39073 +github.tar, level 3 with dict, advanced one pass, 38146 +github.tar, level 3 with dict dms, advanced one pass, 38262 +github.tar, level 3 with dict dds, advanced one pass, 38262 +github.tar, level 3 with dict copy, advanced one pass, 38146 +github.tar, level 3 with dict load, advanced one pass, 38107 +github.tar, level 4, advanced one pass, 39068 +github.tar, level 4 with dict, advanced one pass, 38081 +github.tar, level 4 with dict dms, advanced one pass, 38135 +github.tar, level 4 with dict dds, advanced one pass, 38135 +github.tar, level 4 with dict copy, advanced one pass, 38081 +github.tar, level 4 with dict load, advanced one pass, 38088 +github.tar, level 5 row 1, advanced one pass, 39808 +github.tar, level 5 row 1 with dict dms, advanced one pass, 39185 +github.tar, level 5 row 1 with dict dds, advanced one pass, 39213 +github.tar, level 5 row 1 with dict copy, advanced one pass, 39284 +github.tar, level 5 row 1 with dict load, advanced one pass, 39155 +github.tar, level 5 row 2, advanced one pass, 39851 +github.tar, level 5 row 2 with dict dms, advanced one pass, 39498 +github.tar, level 5 row 2 with dict dds, advanced one pass, 39364 +github.tar, level 5 row 2 with dict copy, advanced one pass, 39843 +github.tar, level 5 row 2 with dict load, advanced one pass, 39312 +github.tar, level 5, advanced one pass, 39808 +github.tar, level 5 with dict, advanced one pass, 39284 +github.tar, level 5 with dict dms, advanced one pass, 39185 +github.tar, level 5 with dict dds, advanced one pass, 39213 +github.tar, level 5 with dict copy, advanced one pass, 39284 +github.tar, level 5 with dict load, advanced one pass, 39155 +github.tar, level 6, advanced one pass, 39455 +github.tar, level 6 with dict, advanced one pass, 38808 +github.tar, level 6 with dict dms, advanced one pass, 38792 +github.tar, level 6 with dict dds, advanced one pass, 38790 +github.tar, level 6 with dict copy, advanced one pass, 38808 +github.tar, level 6 with dict load, advanced one pass, 38796 +github.tar, level 7 row 1, advanced one pass, 38168 +github.tar, level 7 row 1 with dict dms, advanced one pass, 38001 +github.tar, level 7 row 1 with dict dds, advanced one pass, 38008 +github.tar, level 7 row 1 with dict copy, advanced one pass, 37975 +github.tar, level 7 row 1 with dict load, advanced one pass, 37445 +github.tar, level 7 row 2, advanced one pass, 38235 +github.tar, level 7 row 2 with dict dms, advanced one pass, 38164 +github.tar, level 7 row 2 with dict dds, advanced one pass, 38169 +github.tar, level 7 row 2 with dict copy, advanced one pass, 38294 +github.tar, level 7 row 2 with dict load, advanced one pass, 37552 +github.tar, level 7, advanced one pass, 38168 +github.tar, level 7 with dict, advanced one pass, 37975 +github.tar, level 7 with dict dms, advanced one pass, 38001 +github.tar, level 7 with dict dds, advanced one pass, 38008 +github.tar, level 7 with dict copy, advanced one pass, 37975 +github.tar, level 7 with dict load, advanced one pass, 37445 +github.tar, level 9, advanced one pass, 36897 +github.tar, level 9 with dict, advanced one pass, 36689 +github.tar, level 9 with dict dms, advanced one pass, 36756 +github.tar, level 9 with dict dds, advanced one pass, 36817 +github.tar, level 9 with dict copy, advanced one pass, 36689 +github.tar, level 9 with dict load, advanced one pass, 36484 +github.tar, level 11 row 1, advanced one pass, 36234 github.tar, level 11 row 1 with dict dms, advanced one pass, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass, 36423 -github.tar, level 11 row 2, advanced one pass, 36110 +github.tar, level 11 row 1 with dict load, advanced one pass, 36567 +github.tar, level 11 row 2, advanced one pass, 36217 github.tar, level 11 row 2 with dict dms, advanced one pass, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass, 36459 -github.tar, level 12 row 1, advanced one pass, 36085 +github.tar, level 11 row 2 with dict load, advanced one pass, 36586 +github.tar, level 12 row 1, advanced one pass, 36234 github.tar, level 12 row 1 with dict dms, advanced one pass, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass, 36423 -github.tar, level 12 row 2, advanced one pass, 36110 +github.tar, level 12 row 1 with dict load, advanced one pass, 36567 +github.tar, level 12 row 2, advanced one pass, 36217 github.tar, level 12 row 2 with dict dms, advanced one pass, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass, 36459 +github.tar, level 12 row 2 with dict load, advanced one pass, 36586 github.tar, level 13, advanced one pass, 35501 github.tar, level 13 with dict, advanced one pass, 37130 github.tar, level 13 with dict dms, advanced one pass, 37220 @@ -533,87 +533,87 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass, 32565 github.tar, level 19 with dict copy, advanced one pass, 32701 github.tar, level 19 with dict load, advanced one pass, 32428 -github.tar, no source size, advanced one pass, 38884 -github.tar, no source size with dict, advanced one pass, 37995 -github.tar, long distance mode, advanced one pass, 40242 -github.tar, multithreaded, advanced one pass, 38884 -github.tar, multithreaded long distance mode, advanced one pass, 40223 +github.tar, no source size, advanced one pass, 39073 +github.tar, no source size with dict, advanced one pass, 38146 +github.tar, long distance mode, advanced one pass, 40402 +github.tar, multithreaded, advanced one pass, 39067 +github.tar, multithreaded long distance mode, advanced one pass, 40377 github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 -github.tar, explicit params, advanced one pass, 41385 -github.tar, uncompressed literals, advanced one pass, 41562 +github.tar, explicit params, advanced one pass, 41605 +github.tar, uncompressed literals, advanced one pass, 41709 github.tar, uncompressed literals optimal, advanced one pass, 35356 -github.tar, huffman literals, advanced one pass, 38853 -github.tar, multithreaded with advanced params, advanced one pass, 41562 -silesia, level -5, advanced one pass small out, 6857372 -silesia, level -3, advanced one pass small out, 6503412 -silesia, level -1, advanced one pass small out, 6172202 -silesia, level 0, advanced one pass small out, 4839431 -silesia, level 1, advanced one pass small out, 5306632 -silesia, level 3, advanced one pass small out, 4839431 -silesia, level 4, advanced one pass small out, 4776557 -silesia, level 5 row 1, advanced one pass small out, 4667668 -silesia, level 5 row 2, advanced one pass small out, 4670326 -silesia, level 5, advanced one pass small out, 4667668 -silesia, level 6, advanced one pass small out, 4604351 -silesia, level 7 row 1, advanced one pass small out, 4570271 -silesia, level 7 row 2, advanced one pass small out, 4565169 -silesia, level 7, advanced one pass small out, 4570271 -silesia, level 9, advanced one pass small out, 4545850 -silesia, level 11 row 1, advanced one pass small out, 4505658 -silesia, level 11 row 2, advanced one pass small out, 4503429 -silesia, level 12 row 1, advanced one pass small out, 4505658 -silesia, level 12 row 2, advanced one pass small out, 4503429 -silesia, level 13, advanced one pass small out, 4493990 -silesia, level 16, advanced one pass small out, 4359652 -silesia, level 19, advanced one pass small out, 4266582 -silesia, no source size, advanced one pass small out, 4839431 -silesia, long distance mode, advanced one pass small out, 4831158 -silesia, multithreaded, advanced one pass small out, 4839431 -silesia, multithreaded long distance mode, advanced one pass small out, 4831176 +github.tar, huffman literals, advanced one pass, 39099 +github.tar, multithreaded with advanced params, advanced one pass, 41700 +silesia, level -5, advanced one pass small out, 6857776 +silesia, level -3, advanced one pass small out, 6504756 +silesia, level -1, advanced one pass small out, 6174127 +silesia, level 0, advanced one pass small out, 4838417 +silesia, level 1, advanced one pass small out, 5306931 +silesia, level 3, advanced one pass small out, 4838417 +silesia, level 4, advanced one pass small out, 4775359 +silesia, level 5 row 1, advanced one pass small out, 4666524 +silesia, level 5 row 2, advanced one pass small out, 4668976 +silesia, level 5, advanced one pass small out, 4666524 +silesia, level 6, advanced one pass small out, 4602031 +silesia, level 7 row 1, advanced one pass small out, 4567954 +silesia, level 7 row 2, advanced one pass small out, 4562774 +silesia, level 7, advanced one pass small out, 4567954 +silesia, level 9, advanced one pass small out, 4543669 +silesia, level 11 row 1, advanced one pass small out, 4503577 +silesia, level 11 row 2, advanced one pass small out, 4501229 +silesia, level 12 row 1, advanced one pass small out, 4503577 +silesia, level 12 row 2, advanced one pass small out, 4501229 +silesia, level 13, advanced one pass small out, 4484875 +silesia, level 16, advanced one pass small out, 4356207 +silesia, level 19, advanced one pass small out, 4266751 +silesia, no source size, advanced one pass small out, 4838417 +silesia, long distance mode, advanced one pass small out, 4830097 +silesia, multithreaded, advanced one pass small out, 4838949 +silesia, multithreaded long distance mode, advanced one pass small out, 4830419 silesia, small window log, advanced one pass small out, 7094480 -silesia, small hash log, advanced one pass small out, 6526141 -silesia, small chain log, advanced one pass small out, 4912197 -silesia, explicit params, advanced one pass small out, 4795840 -silesia, uncompressed literals, advanced one pass small out, 5116957 -silesia, uncompressed literals optimal, advanced one pass small out, 4316880 -silesia, huffman literals, advanced one pass small out, 5321369 -silesia, multithreaded with advanced params, advanced one pass small out, 5116957 -silesia.tar, level -5, advanced one pass small out, 6861055 -silesia.tar, level -3, advanced one pass small out, 6505483 -silesia.tar, level -1, advanced one pass small out, 6179047 -silesia.tar, level 0, advanced one pass small out, 4851407 -silesia.tar, level 1, advanced one pass small out, 5327717 -silesia.tar, level 3, advanced one pass small out, 4851407 -silesia.tar, level 4, advanced one pass small out, 4788821 -silesia.tar, level 5 row 1, advanced one pass small out, 4679004 -silesia.tar, level 5 row 2, advanced one pass small out, 4682334 -silesia.tar, level 5, advanced one pass small out, 4679004 -silesia.tar, level 6, advanced one pass small out, 4614561 -silesia.tar, level 7 row 1, advanced one pass small out, 4579828 -silesia.tar, level 7 row 2, advanced one pass small out, 4575602 -silesia.tar, level 7, advanced one pass small out, 4579828 -silesia.tar, level 9, advanced one pass small out, 4555448 -silesia.tar, level 11 row 1, advanced one pass small out, 4514962 -silesia.tar, level 11 row 2, advanced one pass small out, 4513816 -silesia.tar, level 12 row 1, advanced one pass small out, 4514517 -silesia.tar, level 12 row 2, advanced one pass small out, 4514007 -silesia.tar, level 13, advanced one pass small out, 4502956 -silesia.tar, level 16, advanced one pass small out, 4360385 -silesia.tar, level 19, advanced one pass small out, 4260939 -silesia.tar, no source size, advanced one pass small out, 4851407 -silesia.tar, long distance mode, advanced one pass small out, 4837775 -silesia.tar, multithreaded, advanced one pass small out, 4851478 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4843155 +silesia, small hash log, advanced one pass small out, 6524931 +silesia, small chain log, advanced one pass small out, 4912322 +silesia, explicit params, advanced one pass small out, 4794219 +silesia, uncompressed literals, advanced one pass small out, 5117482 +silesia, uncompressed literals optimal, advanced one pass small out, 4317186 +silesia, huffman literals, advanced one pass small out, 5321686 +silesia, multithreaded with advanced params, advanced one pass small out, 5117795 +silesia.tar, level -5, advanced one pass small out, 6860782 +silesia.tar, level -3, advanced one pass small out, 6507448 +silesia.tar, level -1, advanced one pass small out, 6175582 +silesia.tar, level 0, advanced one pass small out, 4843429 +silesia.tar, level 1, advanced one pass small out, 5316794 +silesia.tar, level 3, advanced one pass small out, 4843429 +silesia.tar, level 4, advanced one pass small out, 4780657 +silesia.tar, level 5 row 1, advanced one pass small out, 4669650 +silesia.tar, level 5 row 2, advanced one pass small out, 4673119 +silesia.tar, level 5, advanced one pass small out, 4669650 +silesia.tar, level 6, advanced one pass small out, 4604925 +silesia.tar, level 7 row 1, advanced one pass small out, 4570873 +silesia.tar, level 7 row 2, advanced one pass small out, 4566314 +silesia.tar, level 7, advanced one pass small out, 4570873 +silesia.tar, level 9, advanced one pass small out, 4546477 +silesia.tar, level 11 row 1, advanced one pass small out, 4505875 +silesia.tar, level 11 row 2, advanced one pass small out, 4504435 +silesia.tar, level 12 row 1, advanced one pass small out, 4505461 +silesia.tar, level 12 row 2, advanced one pass small out, 4504644 +silesia.tar, level 13, advanced one pass small out, 4486256 +silesia.tar, level 16, advanced one pass small out, 4355572 +silesia.tar, level 19, advanced one pass small out, 4257629 +silesia.tar, no source size, advanced one pass small out, 4843429 +silesia.tar, long distance mode, advanced one pass small out, 4830453 +silesia.tar, multithreaded, advanced one pass small out, 4841902 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4834262 silesia.tar, small window log, advanced one pass small out, 7100064 -silesia.tar, small hash log, advanced one pass small out, 6529206 -silesia.tar, small chain log, advanced one pass small out, 4917041 -silesia.tar, explicit params, advanced one pass small out, 4807274 -silesia.tar, uncompressed literals, advanced one pass small out, 5118848 -silesia.tar, uncompressed literals optimal, advanced one pass small out, 4308451 -silesia.tar, huffman literals, advanced one pass small out, 5341705 -silesia.tar, multithreaded with advanced params, advanced one pass small out, 5118940 +silesia.tar, small hash log, advanced one pass small out, 6530222 +silesia.tar, small chain log, advanced one pass small out, 4915689 +silesia.tar, explicit params, advanced one pass small out, 4797958 +silesia.tar, uncompressed literals, advanced one pass small out, 5116329 +silesia.tar, uncompressed literals optimal, advanced one pass small out, 4306289 +silesia.tar, huffman literals, advanced one pass small out, 5331382 +silesia.tar, multithreaded with advanced params, advanced one pass small out, 5116442 github, level -5, advanced one pass small out, 204407 github, level -5 with dict, advanced one pass small out, 45832 github, level -3, advanced one pass small out, 193253 @@ -739,100 +739,100 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced one pass small out, 152667 github, huffman literals, advanced one pass small out, 142365 github, multithreaded with advanced params, advanced one pass small out, 165909 -github.tar, level -5, advanced one pass small out, 52115 -github.tar, level -5 with dict, advanced one pass small out, 51097 -github.tar, level -3, advanced one pass small out, 45678 -github.tar, level -3 with dict, advanced one pass small out, 44734 -github.tar, level -1, advanced one pass small out, 42560 -github.tar, level -1 with dict, advanced one pass small out, 41353 -github.tar, level 0, advanced one pass small out, 38884 -github.tar, level 0 with dict, advanced one pass small out, 37995 -github.tar, level 0 with dict dms, advanced one pass small out, 38114 -github.tar, level 0 with dict dds, advanced one pass small out, 38114 -github.tar, level 0 with dict copy, advanced one pass small out, 37995 -github.tar, level 0 with dict load, advanced one pass small out, 37956 -github.tar, level 1, advanced one pass small out, 39200 -github.tar, level 1 with dict, advanced one pass small out, 38119 -github.tar, level 1 with dict dms, advanced one pass small out, 38406 -github.tar, level 1 with dict dds, advanced one pass small out, 38406 -github.tar, level 1 with dict copy, advanced one pass small out, 38119 -github.tar, level 1 with dict load, advanced one pass small out, 38364 -github.tar, level 3, advanced one pass small out, 38884 -github.tar, level 3 with dict, advanced one pass small out, 37995 -github.tar, level 3 with dict dms, advanced one pass small out, 38114 -github.tar, level 3 with dict dds, advanced one pass small out, 38114 -github.tar, level 3 with dict copy, advanced one pass small out, 37995 -github.tar, level 3 with dict load, advanced one pass small out, 37956 -github.tar, level 4, advanced one pass small out, 38880 -github.tar, level 4 with dict, advanced one pass small out, 37948 -github.tar, level 4 with dict dms, advanced one pass small out, 37995 -github.tar, level 4 with dict dds, advanced one pass small out, 37995 -github.tar, level 4 with dict copy, advanced one pass small out, 37948 -github.tar, level 4 with dict load, advanced one pass small out, 37927 -github.tar, level 5 row 1, advanced one pass small out, 39651 -github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39043 -github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39069 -github.tar, level 5 row 1 with dict copy, advanced one pass small out, 39145 -github.tar, level 5 row 1 with dict load, advanced one pass small out, 39000 -github.tar, level 5 row 2, advanced one pass small out, 39701 -github.tar, level 5 row 2 with dict dms, advanced one pass small out, 39365 -github.tar, level 5 row 2 with dict dds, advanced one pass small out, 39233 -github.tar, level 5 row 2 with dict copy, advanced one pass small out, 39715 -github.tar, level 5 row 2 with dict load, advanced one pass small out, 39158 -github.tar, level 5, advanced one pass small out, 39651 -github.tar, level 5 with dict, advanced one pass small out, 39145 -github.tar, level 5 with dict dms, advanced one pass small out, 39043 -github.tar, level 5 with dict dds, advanced one pass small out, 39069 -github.tar, level 5 with dict copy, advanced one pass small out, 39145 -github.tar, level 5 with dict load, advanced one pass small out, 39000 -github.tar, level 6, advanced one pass small out, 39282 -github.tar, level 6 with dict, advanced one pass small out, 38656 -github.tar, level 6 with dict dms, advanced one pass small out, 38640 -github.tar, level 6 with dict dds, advanced one pass small out, 38643 -github.tar, level 6 with dict copy, advanced one pass small out, 38656 -github.tar, level 6 with dict load, advanced one pass small out, 38647 -github.tar, level 7 row 1, advanced one pass small out, 38005 -github.tar, level 7 row 1 with dict dms, advanced one pass small out, 37832 -github.tar, level 7 row 1 with dict dds, advanced one pass small out, 37857 -github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37839 -github.tar, level 7 row 1 with dict load, advanced one pass small out, 37286 -github.tar, level 7 row 2, advanced one pass small out, 38077 -github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38012 -github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38014 -github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38101 -github.tar, level 7 row 2 with dict load, advanced one pass small out, 37402 -github.tar, level 7, advanced one pass small out, 38005 -github.tar, level 7 with dict, advanced one pass small out, 37839 -github.tar, level 7 with dict dms, advanced one pass small out, 37832 -github.tar, level 7 with dict dds, advanced one pass small out, 37857 -github.tar, level 7 with dict copy, advanced one pass small out, 37839 -github.tar, level 7 with dict load, advanced one pass small out, 37286 -github.tar, level 9, advanced one pass small out, 36723 -github.tar, level 9 with dict, advanced one pass small out, 36531 -github.tar, level 9 with dict dms, advanced one pass small out, 36615 -github.tar, level 9 with dict dds, advanced one pass small out, 36682 -github.tar, level 9 with dict copy, advanced one pass small out, 36531 -github.tar, level 9 with dict load, advanced one pass small out, 36322 -github.tar, level 11 row 1, advanced one pass small out, 36085 +github.tar, level -5, advanced one pass small out, 52320 +github.tar, level -5 with dict, advanced one pass small out, 51321 +github.tar, level -3, advanced one pass small out, 45823 +github.tar, level -3 with dict, advanced one pass small out, 44882 +github.tar, level -1, advanced one pass small out, 42740 +github.tar, level -1 with dict, advanced one pass small out, 41506 +github.tar, level 0, advanced one pass small out, 39073 +github.tar, level 0 with dict, advanced one pass small out, 38146 +github.tar, level 0 with dict dms, advanced one pass small out, 38262 +github.tar, level 0 with dict dds, advanced one pass small out, 38262 +github.tar, level 0 with dict copy, advanced one pass small out, 38146 +github.tar, level 0 with dict load, advanced one pass small out, 38107 +github.tar, level 1, advanced one pass small out, 39444 +github.tar, level 1 with dict, advanced one pass small out, 38338 +github.tar, level 1 with dict dms, advanced one pass small out, 38641 +github.tar, level 1 with dict dds, advanced one pass small out, 38641 +github.tar, level 1 with dict copy, advanced one pass small out, 38338 +github.tar, level 1 with dict load, advanced one pass small out, 38592 +github.tar, level 3, advanced one pass small out, 39073 +github.tar, level 3 with dict, advanced one pass small out, 38146 +github.tar, level 3 with dict dms, advanced one pass small out, 38262 +github.tar, level 3 with dict dds, advanced one pass small out, 38262 +github.tar, level 3 with dict copy, advanced one pass small out, 38146 +github.tar, level 3 with dict load, advanced one pass small out, 38107 +github.tar, level 4, advanced one pass small out, 39068 +github.tar, level 4 with dict, advanced one pass small out, 38081 +github.tar, level 4 with dict dms, advanced one pass small out, 38135 +github.tar, level 4 with dict dds, advanced one pass small out, 38135 +github.tar, level 4 with dict copy, advanced one pass small out, 38081 +github.tar, level 4 with dict load, advanced one pass small out, 38088 +github.tar, level 5 row 1, advanced one pass small out, 39808 +github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39185 +github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39213 +github.tar, level 5 row 1 with dict copy, advanced one pass small out, 39284 +github.tar, level 5 row 1 with dict load, advanced one pass small out, 39155 +github.tar, level 5 row 2, advanced one pass small out, 39851 +github.tar, level 5 row 2 with dict dms, advanced one pass small out, 39498 +github.tar, level 5 row 2 with dict dds, advanced one pass small out, 39364 +github.tar, level 5 row 2 with dict copy, advanced one pass small out, 39843 +github.tar, level 5 row 2 with dict load, advanced one pass small out, 39312 +github.tar, level 5, advanced one pass small out, 39808 +github.tar, level 5 with dict, advanced one pass small out, 39284 +github.tar, level 5 with dict dms, advanced one pass small out, 39185 +github.tar, level 5 with dict dds, advanced one pass small out, 39213 +github.tar, level 5 with dict copy, advanced one pass small out, 39284 +github.tar, level 5 with dict load, advanced one pass small out, 39155 +github.tar, level 6, advanced one pass small out, 39455 +github.tar, level 6 with dict, advanced one pass small out, 38808 +github.tar, level 6 with dict dms, advanced one pass small out, 38792 +github.tar, level 6 with dict dds, advanced one pass small out, 38790 +github.tar, level 6 with dict copy, advanced one pass small out, 38808 +github.tar, level 6 with dict load, advanced one pass small out, 38796 +github.tar, level 7 row 1, advanced one pass small out, 38168 +github.tar, level 7 row 1 with dict dms, advanced one pass small out, 38001 +github.tar, level 7 row 1 with dict dds, advanced one pass small out, 38008 +github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 row 1 with dict load, advanced one pass small out, 37445 +github.tar, level 7 row 2, advanced one pass small out, 38235 +github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38164 +github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38169 +github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38294 +github.tar, level 7 row 2 with dict load, advanced one pass small out, 37552 +github.tar, level 7, advanced one pass small out, 38168 +github.tar, level 7 with dict, advanced one pass small out, 37975 +github.tar, level 7 with dict dms, advanced one pass small out, 38001 +github.tar, level 7 with dict dds, advanced one pass small out, 38008 +github.tar, level 7 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 with dict load, advanced one pass small out, 37445 +github.tar, level 9, advanced one pass small out, 36897 +github.tar, level 9 with dict, advanced one pass small out, 36689 +github.tar, level 9 with dict dms, advanced one pass small out, 36756 +github.tar, level 9 with dict dds, advanced one pass small out, 36817 +github.tar, level 9 with dict copy, advanced one pass small out, 36689 +github.tar, level 9 with dict load, advanced one pass small out, 36484 +github.tar, level 11 row 1, advanced one pass small out, 36234 github.tar, level 11 row 1 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass small out, 36423 -github.tar, level 11 row 2, advanced one pass small out, 36110 +github.tar, level 11 row 1 with dict load, advanced one pass small out, 36567 +github.tar, level 11 row 2, advanced one pass small out, 36217 github.tar, level 11 row 2 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass small out, 36459 -github.tar, level 12 row 1, advanced one pass small out, 36085 +github.tar, level 11 row 2 with dict load, advanced one pass small out, 36586 +github.tar, level 12 row 1, advanced one pass small out, 36234 github.tar, level 12 row 1 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass small out, 36423 -github.tar, level 12 row 2, advanced one pass small out, 36110 +github.tar, level 12 row 1 with dict load, advanced one pass small out, 36567 +github.tar, level 12 row 2, advanced one pass small out, 36217 github.tar, level 12 row 2 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass small out, 36459 +github.tar, level 12 row 2 with dict load, advanced one pass small out, 36586 github.tar, level 13, advanced one pass small out, 35501 github.tar, level 13 with dict, advanced one pass small out, 37130 github.tar, level 13 with dict dms, advanced one pass small out, 37220 @@ -851,19 +851,19 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass small out, 32565 github.tar, level 19 with dict copy, advanced one pass small out, 32701 github.tar, level 19 with dict load, advanced one pass small out, 32428 -github.tar, no source size, advanced one pass small out, 38884 -github.tar, no source size with dict, advanced one pass small out, 37995 -github.tar, long distance mode, advanced one pass small out, 40242 -github.tar, multithreaded, advanced one pass small out, 38884 -github.tar, multithreaded long distance mode, advanced one pass small out, 40223 +github.tar, no source size, advanced one pass small out, 39073 +github.tar, no source size with dict, advanced one pass small out, 38146 +github.tar, long distance mode, advanced one pass small out, 40402 +github.tar, multithreaded, advanced one pass small out, 39067 +github.tar, multithreaded long distance mode, advanced one pass small out, 40377 github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 -github.tar, explicit params, advanced one pass small out, 41385 -github.tar, uncompressed literals, advanced one pass small out, 41562 +github.tar, explicit params, advanced one pass small out, 41605 +github.tar, uncompressed literals, advanced one pass small out, 41709 github.tar, uncompressed literals optimal, advanced one pass small out, 35356 -github.tar, huffman literals, advanced one pass small out, 38853 -github.tar, multithreaded with advanced params, advanced one pass small out, 41562 +github.tar, huffman literals, advanced one pass small out, 39099 +github.tar, multithreaded with advanced params, advanced one pass small out, 41700 silesia, level -5, advanced streaming, 6854744 silesia, level -3, advanced streaming, 6503319 silesia, level -1, advanced streaming, 6172207 @@ -888,8 +888,8 @@ silesia, level 16, advanced silesia, level 19, advanced streaming, 4266582 silesia, no source size, advanced streaming, 4839395 silesia, long distance mode, advanced streaming, 4831158 -silesia, multithreaded, advanced streaming, 4839431 -silesia, multithreaded long distance mode, advanced streaming, 4831176 +silesia, multithreaded, advanced streaming, 4838949 +silesia, multithreaded long distance mode, advanced streaming, 4830419 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6526141 silesia, small chain log, advanced streaming, 4912197 @@ -897,7 +897,7 @@ silesia, explicit params, advanced silesia, uncompressed literals, advanced streaming, 5116957 silesia, uncompressed literals optimal, advanced streaming, 4316880 silesia, huffman literals, advanced streaming, 5321370 -silesia, multithreaded with advanced params, advanced streaming, 5116957 +silesia, multithreaded with advanced params, advanced streaming, 5117795 silesia.tar, level -5, advanced streaming, 6856523 silesia.tar, level -3, advanced streaming, 6505954 silesia.tar, level -1, advanced streaming, 6179056 @@ -922,8 +922,8 @@ silesia.tar, level 16, advanced silesia.tar, level 19, advanced streaming, 4260939 silesia.tar, no source size, advanced streaming, 4858628 silesia.tar, long distance mode, advanced streaming, 4837775 -silesia.tar, multithreaded, advanced streaming, 4851478 -silesia.tar, multithreaded long distance mode, advanced streaming, 4843155 +silesia.tar, multithreaded, advanced streaming, 4841902 +silesia.tar, multithreaded long distance mode, advanced streaming, 4834262 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529209 silesia.tar, small chain log, advanced streaming, 4917021 @@ -931,7 +931,7 @@ silesia.tar, explicit params, advanced silesia.tar, uncompressed literals, advanced streaming, 5126542 silesia.tar, uncompressed literals optimal, advanced streaming, 4308451 silesia.tar, huffman literals, advanced streaming, 5341712 -silesia.tar, multithreaded with advanced params, advanced streaming, 5118940 +silesia.tar, multithreaded with advanced params, advanced streaming, 5116442 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 github, level -3, advanced streaming, 193253 @@ -1172,8 +1172,8 @@ github.tar, level 19 with dict load, advanced github.tar, no source size, advanced streaming, 38881 github.tar, no source size with dict, advanced streaming, 38111 github.tar, long distance mode, advanced streaming, 40242 -github.tar, multithreaded, advanced streaming, 38884 -github.tar, multithreaded long distance mode, advanced streaming, 40223 +github.tar, multithreaded, advanced streaming, 39067 +github.tar, multithreaded long distance mode, advanced streaming, 40377 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 @@ -1181,7 +1181,7 @@ github.tar, explicit params, advanced github.tar, uncompressed literals, advanced streaming, 41562 github.tar, uncompressed literals optimal, advanced streaming, 35356 github.tar, huffman literals, advanced streaming, 38853 -github.tar, multithreaded with advanced params, advanced streaming, 41562 +github.tar, multithreaded with advanced params, advanced streaming, 41700 silesia, level -5, old streaming, 6854744 silesia, level -3, old streaming, 6503319 silesia, level -1, old streaming, 6172207 From 1c62e714ab9f53aefd6478e033ce448597b68fab Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 20 Oct 2024 17:16:17 -0700 Subject: [PATCH 126/405] minor split optimization let's fill the initial stats directly into target fingerprint --- lib/compress/zstd_preSplit.c | 10 +++++----- lib/compress/zstd_preSplit.h | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index ceac5c91f..f831dabde 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -18,7 +18,7 @@ #define BLOCKSIZE_MIN 3500 #define THRESHOLD_PENALTY_RATE 16 #define THRESHOLD_BASE (THRESHOLD_PENALTY_RATE - 2) -#define THRESHOLD_PENALTY 4 +#define THRESHOLD_PENALTY 3 #define HASHLENGTH 2 #define HASHLOG 10 @@ -84,8 +84,8 @@ static int compareFingerprints(const FingerPrint* ref, const FingerPrint* newfp, int penalty) { - if (ref->nbEvents <= BLOCKSIZE_MIN) - return 0; + assert(ref->nbEvents > 0); + assert(newfp->nbEvents > 0); { S64 p50 = ref->nbEvents * newfp->nbEvents; S64 deviation = fpDistance(ref, newfp); S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; @@ -140,7 +140,8 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); - for (pos = 0; pos < blockSizeMax;) { + recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE); + for (pos = CHUNKSIZE; pos < blockSizeMax; pos += CHUNKSIZE) { assert(pos <= blockSizeMax - CHUNKSIZE); recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { @@ -150,7 +151,6 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); penalty = penalty - 1 + (penalty == 0); } - pos += CHUNKSIZE; } return blockSizeMax; (void)flushEvents; (void)removeEvents; diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index b0b6bb762..7b6aadd0b 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -22,6 +22,10 @@ extern "C" { /* note: * @workspace must be aligned on 8-bytes boundaries * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE + * note2: + * for the time being, this function only accepts full 128 KB blocks, + * therefore @blockSizeMax must be == 128 KB. + * This could be extended to smaller sizes in the future. */ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax, void* workspace, size_t wkspSize); From a167571db535377070c43098932a7747d859177c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 21 Oct 2024 14:56:43 -0700 Subject: [PATCH 127/405] added a faster block splitter variant that samples 1 in 5 positions. This variant is fast enough for lazy2 and btlazy2, but it's less good in combination with post-splitter at higher levels (>= btopt). --- lib/compress/zstd_compress.c | 6 +++-- lib/compress/zstd_preSplit.c | 50 ++++++++++++++++++++++++++---------- lib/compress/zstd_preSplit.h | 6 ++++- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index fcef55bf1..e7a07a484 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4500,8 +4500,10 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src return MIN(srcSize, blockSizeMax); /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for btlazy2+ strategies */ - if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, cctx->tmpWorkspace, cctx->tmpWkspSize); + if (strat >= ZSTD_btopt) + return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); + if (strat >= ZSTD_lazy2) + return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index f831dabde..721a52deb 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -46,22 +46,36 @@ static void initStats(FPStats* fpstats) ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) +FORCE_INLINE_TEMPLATE void addEvents_generic(FingerPrint* fp, const void* src, size_t srcSize, size_t samplingRate) { const char* p = (const char*)src; - size_t limit = s - HASHLENGTH + 1; + size_t limit = srcSize - HASHLENGTH + 1; size_t n; - assert(s >= HASHLENGTH); - for (n = 0; n < limit; n++) { - fp->events[hash2(p++)]++; + assert(srcSize >= HASHLENGTH); + for (n = 0; n < limit; n+=samplingRate) { + fp->events[hash2(p+n)]++; } - fp->nbEvents += limit; + fp->nbEvents += limit/samplingRate; } -static void recordFingerprint(FingerPrint* fp, const void* src, size_t s) +#define ADDEVENTS_RATE(_rate) ZSTD_addEvents_##_rate + +#define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ + static void ADDEVENTS_RATE(_rate)(FingerPrint* fp, const void* src, size_t srcSize) \ + { \ + return addEvents_generic(fp, src, srcSize, _rate); \ + } + +ZSTD_GEN_ADDEVENTS_SAMPLE(1); +ZSTD_GEN_ADDEVENTS_SAMPLE(5); + + +typedef void (*addEvents_f)(FingerPrint* fp, const void* src, size_t srcSize); + +static void recordFingerprint(FingerPrint* fp, const void* src, size_t s, addEvents_f addEvents) { ZSTD_memset(fp, 0, sizeof(*fp)); - addToFingerprint(fp, src, s); + addEvents(fp, src, s); } static S64 abs64(S64 i) { return (i < 0) ? -i : i; } @@ -124,8 +138,8 @@ static void removeEvents(FingerPrint* acc, const FingerPrint* slice) #define CHUNKSIZE (8 << 10) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, - size_t blockSizeMax, +static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, + size_t blockSizeMax, addEvents_f f, void* workspace, size_t wkspSize) { FPStats* const fpstats = (FPStats*)workspace; @@ -140,18 +154,28 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); - recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE); + recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE, f); for (pos = CHUNKSIZE; pos < blockSizeMax; pos += CHUNKSIZE) { assert(pos <= blockSizeMax - CHUNKSIZE); - recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE); + recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE, f); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; } else { mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); - ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); penalty = penalty - 1 + (penalty == 0); } } return blockSizeMax; (void)flushEvents; (void)removeEvents; } + +size_t ZSTD_splitBlock(const void* src, size_t srcSize, + size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, + void* workspace, size_t wkspSize) +{ + if (splitStrat == split_lvl2) + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(1), workspace, wkspSize); + + assert(splitStrat == split_lvl1); + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(5), workspace, wkspSize); +} diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 7b6aadd0b..2c87d34a6 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -17,6 +17,8 @@ extern "C" { #endif +typedef enum { split_lvl1, split_lvl2 } ZSTD_SplitBlock_strategy_e; + #define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 /* note: @@ -27,7 +29,9 @@ extern "C" { * therefore @blockSizeMax must be == 128 KB. * This could be extended to smaller sizes in the future. */ -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax, void* workspace, size_t wkspSize); +size_t ZSTD_splitBlock(const void* src, size_t srcSize, + size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, + void* workspace, size_t wkspSize); #if defined (__cplusplus) } From 7bad787d8bcae57cf0bdcbca00b3f106ae557b75 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:12:46 -0700 Subject: [PATCH 128/405] made ZSTD_isPower2() an inline function --- lib/common/compiler.h | 6 +++++- lib/compress/zstd_cwksp.h | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index f4caeb5c0..b6cbcee03 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -278,7 +278,11 @@ * Alignment check *****************************************************************/ -#define ZSTD_IS_POWER_2(a) (((a) & ((a)-1)) == 0) +/* @return 1 if @u is a 2^n value, 0 otherwise + * useful to check a value is valid for alignment restrictions */ +MEM_STATIC int ZSTD_isPower2(size_t u) { + return (u & (u-1)) == 0; +} /* this test was initially positioned in mem.h, * but this file is removed (or replaced) for linux kernel diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index dc0142098..77715e22e 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -208,7 +208,7 @@ MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) { */ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) { size_t const mask = align - 1; - assert(ZSTD_IS_POWER_2(align)); + assert(ZSTD_isPower2(align)); return (size + mask) & ~mask; } @@ -266,7 +266,7 @@ MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) { MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) { size_t const alignBytesMask = alignBytes - 1; size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask; - assert(ZSTD_IS_POWER_2(alignBytes)); + assert(ZSTD_isPower2(alignBytes)); assert(bytes < alignBytes); return bytes; } @@ -536,7 +536,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSi void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus); if (start == NULL) return NULL; if (surplus == 0) return start; - assert(ZSTD_IS_POWER_2(alignment)); + assert(ZSTD_isPower2(alignment)); return (void*)(((size_t)start + surplus) & ~mask); } From 5ae34e4c96265f1face970f3458836b3edf2e76d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:19:06 -0700 Subject: [PATCH 129/405] ensure `lastBlock` is correctly determined reported by @terrelln --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e7a07a484..edb71ae50 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4540,8 +4540,8 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); size_t const blockSize = ZSTD_optimalBlockSize(cctx, ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); + U32 const lastBlock = lastFrameChunk & (blockSize == remaining); assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding From ea85dc7af6f97cbfc7fd1e6ff1515660e58501a3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:25:45 -0700 Subject: [PATCH 130/405] conservatively estimate over-splitting in presence of incompressible loss ensure data can never be expanded by more than 3 bytes per full block. --- lib/compress/zstd_compress.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index edb71ae50..85966d888 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4587,6 +4587,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ if (cSize < blockSize) savings += (blockSize - cSize); + else if (savings) savings--; ip += blockSize; assert(remaining >= blockSize); remaining -= blockSize; From 4662f6e646395b3f1902bc280991b82aefc1ba5d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:32:11 -0700 Subject: [PATCH 131/405] renamed: FingerPrint => Fingerprint suggested by @terrelln --- lib/compress/zstd_preSplit.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 721a52deb..e0ac9a9e9 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -35,10 +35,10 @@ static unsigned hash2(const void *p) typedef struct { int events[HASHTABLESIZE]; S64 nbEvents; -} FingerPrint; +} Fingerprint; typedef struct { - FingerPrint pastEvents; - FingerPrint newEvents; + Fingerprint pastEvents; + Fingerprint newEvents; } FPStats; static void initStats(FPStats* fpstats) @@ -46,7 +46,7 @@ static void initStats(FPStats* fpstats) ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -FORCE_INLINE_TEMPLATE void addEvents_generic(FingerPrint* fp, const void* src, size_t srcSize, size_t samplingRate) +FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) { const char* p = (const char*)src; size_t limit = srcSize - HASHLENGTH + 1; @@ -61,7 +61,7 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(FingerPrint* fp, const void* src, s #define ADDEVENTS_RATE(_rate) ZSTD_addEvents_##_rate #define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ - static void ADDEVENTS_RATE(_rate)(FingerPrint* fp, const void* src, size_t srcSize) \ + static void ADDEVENTS_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ { \ return addEvents_generic(fp, src, srcSize, _rate); \ } @@ -70,9 +70,9 @@ ZSTD_GEN_ADDEVENTS_SAMPLE(1); ZSTD_GEN_ADDEVENTS_SAMPLE(5); -typedef void (*addEvents_f)(FingerPrint* fp, const void* src, size_t srcSize); +typedef void (*addEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); -static void recordFingerprint(FingerPrint* fp, const void* src, size_t s, addEvents_f addEvents) +static void recordFingerprint(Fingerprint* fp, const void* src, size_t s, addEvents_f addEvents) { ZSTD_memset(fp, 0, sizeof(*fp)); addEvents(fp, src, s); @@ -80,7 +80,7 @@ static void recordFingerprint(FingerPrint* fp, const void* src, size_t s, addEve static S64 abs64(S64 i) { return (i < 0) ? -i : i; } -static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) +static S64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) { S64 distance = 0; size_t n; @@ -94,8 +94,8 @@ static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) /* Compare newEvents with pastEvents * return 1 when considered "too different" */ -static int compareFingerprints(const FingerPrint* ref, - const FingerPrint* newfp, +static int compareFingerprints(const Fingerprint* ref, + const Fingerprint* newfp, int penalty) { assert(ref->nbEvents > 0); @@ -107,7 +107,7 @@ static int compareFingerprints(const FingerPrint* ref, } } -static void mergeEvents(FingerPrint* acc, const FingerPrint* newfp) +static void mergeEvents(Fingerprint* acc, const Fingerprint* newfp) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { @@ -126,7 +126,7 @@ static void flushEvents(FPStats* fpstats) ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); } -static void removeEvents(FingerPrint* acc, const FingerPrint* slice) +static void removeEvents(Fingerprint* acc, const Fingerprint* slice) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { From 1ec5f9f1f6b187095d996248471a6c6f128e9001 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:03:19 -0700 Subject: [PATCH 132/405] changed loop exit condition so that there is no need to assert() within the loop. --- lib/compress/zstd_preSplit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index e0ac9a9e9..02751a0d4 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -155,8 +155,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, initStats(fpstats); recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE, f); - for (pos = CHUNKSIZE; pos < blockSizeMax; pos += CHUNKSIZE) { - assert(pos <= blockSizeMax - CHUNKSIZE); + for (pos = CHUNKSIZE; pos <= blockSizeMax - CHUNKSIZE; pos += CHUNKSIZE) { recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE, f); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; @@ -165,6 +164,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, penalty = penalty - 1 + (penalty == 0); } } + assert(pos == blockSizeMax); return blockSizeMax; (void)flushEvents; (void)removeEvents; } From 16450d0732ff84e3ad367f616d84cee1567cfb8e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:06:07 -0700 Subject: [PATCH 133/405] rewrite penalty update suggested by @terrelln --- lib/compress/zstd_preSplit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 02751a0d4..2e65f88d9 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -161,7 +161,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, return pos; } else { mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); - penalty = penalty - 1 + (penalty == 0); + if (penalty > 0) penalty--; } } assert(pos == blockSizeMax); From 06b7cfabf8f5f3ba48694758cf85aaf7671504d2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:22:17 -0700 Subject: [PATCH 134/405] rewrote ZSTD_cwksp_initialAllocStart() to be easier to read following a discussion with @felixhandte --- lib/compress/zstd_cwksp.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 77715e22e..aa4c3e49e 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -17,6 +17,7 @@ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customFree */ #include "../common/zstd_internal.h" #include "../common/portability_macros.h" +#include "../common/compiler.h" /* ZS2_isPower2 */ #if defined (__cplusplus) extern "C" { @@ -275,8 +276,12 @@ MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignByt * Returns the initial value for allocStart which is used to determine the position from * which we can allocate from the end of the workspace. */ -MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) { - return (void*)((size_t)ws->workspaceEnd & (size_t)~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); +MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) +{ + char* endPtr = (char*)ws->workspaceEnd; + assert(ZSTD_isPower2(ZSTD_CWKSP_ALIGNMENT_BYTES)); + endPtr = endPtr - ((size_t)endPtr % ZSTD_CWKSP_ALIGNMENT_BYTES); + return (void*)endPtr; } /** From 0be334d208b9fadd805a401ebcfdf6f253adae2a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:25:44 -0700 Subject: [PATCH 135/405] fixes static state allocation check detected by @felixhandte --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 85966d888..05c1faa9f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -138,7 +138,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) cctx->staticSize = workspaceSize; /* statically sized space. tmpWorkspace never moves (but prev/next block swap places) */ - if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; + if (!ZSTD_cwksp_check_available(&cctx->workspace, TMP_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(&cctx->workspace, TMP_WORKSPACE_SIZE, sizeof(S64)); From d2eeed53dc8782be8dff36e1ff20e1e41e1d4199 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:33:55 -0700 Subject: [PATCH 136/405] updated compression results due to integration of `sample5` strategy, leading to better compression ratios on a range of levels --- tests/regression/results.csv | 168 +++++++++++++++++------------------ 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index b32db43de..3a14793dd 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -9,8 +9,8 @@ silesia.tar, level 4, compress silesia.tar, level 5, compress simple, 4669650 silesia.tar, level 6, compress simple, 4604925 silesia.tar, level 7, compress simple, 4570873 -silesia.tar, level 9, compress simple, 4546477 -silesia.tar, level 13, compress simple, 4486256 +silesia.tar, level 9, compress simple, 4537558 +silesia.tar, level 13, compress simple, 4484732 silesia.tar, level 16, compress simple, 4355572 silesia.tar, level 19, compress simple, 4257629 silesia.tar, uncompressed literals, compress simple, 4843429 @@ -26,7 +26,7 @@ github.tar, level 4, compress github.tar, level 5, compress simple, 39808 github.tar, level 6, compress simple, 39455 github.tar, level 7, compress simple, 38168 -github.tar, level 9, compress simple, 36897 +github.tar, level 9, compress simple, 36723 github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 github.tar, level 19, compress simple, 32262 @@ -43,8 +43,8 @@ silesia, level 4, compress silesia, level 5, compress cctx, 4666524 silesia, level 6, compress cctx, 4602031 silesia, level 7, compress cctx, 4567954 -silesia, level 9, compress cctx, 4543669 -silesia, level 13, compress cctx, 4484875 +silesia, level 9, compress cctx, 4535624 +silesia, level 13, compress cctx, 4484013 silesia, level 16, compress cctx, 4356207 silesia, level 19, compress cctx, 4266751 silesia, long distance mode, compress cctx, 4838417 @@ -107,8 +107,8 @@ silesia, level 4, zstdcli, silesia, level 5, zstdcli, 4666931 silesia, level 6, zstdcli, 4602509 silesia, level 7, zstdcli, 4568265 -silesia, level 9, zstdcli, 4544068 -silesia, level 13, zstdcli, 4484443 +silesia, level 9, zstdcli, 4535309 +silesia, level 13, zstdcli, 4483601 silesia, level 16, zstdcli, 4357591 silesia, level 19, zstdcli, 4266865 silesia, long distance mode, zstdcli, 4830467 @@ -132,8 +132,8 @@ silesia.tar, level 4, zstdcli, silesia.tar, level 5, zstdcli, 4671144 silesia.tar, level 6, zstdcli, 4606407 silesia.tar, level 7, zstdcli, 4572666 -silesia.tar, level 9, zstdcli, 4546557 -silesia.tar, level 13, zstdcli, 4491076 +silesia.tar, level 9, zstdcli, 4542599 +silesia.tar, level 13, zstdcli, 4489976 silesia.tar, level 16, zstdcli, 4356959 silesia.tar, level 19, zstdcli, 4259787 silesia.tar, no source size, zstdcli, 4841902 @@ -206,9 +206,9 @@ github.tar, level 5 with dict, zstdcli, github.tar, level 6, zstdcli, 39455 github.tar, level 6 with dict, zstdcli, 38787 github.tar, level 7, zstdcli, 38177 -github.tar, level 7 with dict, zstdcli, 38009 -github.tar, level 9, zstdcli, 36893 -github.tar, level 9 with dict, zstdcli, 36827 +github.tar, level 7 with dict, zstdcli, 37861 +github.tar, level 9, zstdcli, 36727 +github.tar, level 9 with dict, zstdcli, 36686 github.tar, level 13, zstdcli, 35505 github.tar, level 13 with dict, zstdcli, 37134 github.tar, level 16, zstdcli, 40470 @@ -242,12 +242,12 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass, 4567954 silesia, level 7 row 2, advanced one pass, 4562774 silesia, level 7, advanced one pass, 4567954 -silesia, level 9, advanced one pass, 4543669 -silesia, level 11 row 1, advanced one pass, 4503577 -silesia, level 11 row 2, advanced one pass, 4501229 -silesia, level 12 row 1, advanced one pass, 4503577 -silesia, level 12 row 2, advanced one pass, 4501229 -silesia, level 13, advanced one pass, 4484875 +silesia, level 9, advanced one pass, 4535624 +silesia, level 11 row 1, advanced one pass, 4495623 +silesia, level 11 row 2, advanced one pass, 4493258 +silesia, level 12 row 1, advanced one pass, 4495623 +silesia, level 12 row 2, advanced one pass, 4493258 +silesia, level 13, advanced one pass, 4484013 silesia, level 16, advanced one pass, 4356207 silesia, level 19, advanced one pass, 4266751 silesia, no source size, advanced one pass, 4838417 @@ -276,12 +276,12 @@ silesia.tar, level 6, advanced silesia.tar, level 7 row 1, advanced one pass, 4570873 silesia.tar, level 7 row 2, advanced one pass, 4566314 silesia.tar, level 7, advanced one pass, 4570873 -silesia.tar, level 9, advanced one pass, 4546477 -silesia.tar, level 11 row 1, advanced one pass, 4505875 -silesia.tar, level 11 row 2, advanced one pass, 4504435 -silesia.tar, level 12 row 1, advanced one pass, 4505461 -silesia.tar, level 12 row 2, advanced one pass, 4504644 -silesia.tar, level 13, advanced one pass, 4486256 +silesia.tar, level 9, advanced one pass, 4537558 +silesia.tar, level 11 row 1, advanced one pass, 4496590 +silesia.tar, level 11 row 2, advanced one pass, 4495225 +silesia.tar, level 12 row 1, advanced one pass, 4496084 +silesia.tar, level 12 row 2, advanced one pass, 4495434 +silesia.tar, level 13, advanced one pass, 4484732 silesia.tar, level 16, advanced one pass, 4355572 silesia.tar, level 19, advanced one pass, 4257629 silesia.tar, no source size, advanced one pass, 4843429 @@ -474,47 +474,47 @@ github.tar, level 6 with dict dds, advanced github.tar, level 6 with dict copy, advanced one pass, 38808 github.tar, level 6 with dict load, advanced one pass, 38796 github.tar, level 7 row 1, advanced one pass, 38168 -github.tar, level 7 row 1 with dict dms, advanced one pass, 38001 -github.tar, level 7 row 1 with dict dds, advanced one pass, 38008 -github.tar, level 7 row 1 with dict copy, advanced one pass, 37975 +github.tar, level 7 row 1 with dict dms, advanced one pass, 37832 +github.tar, level 7 row 1 with dict dds, advanced one pass, 37857 +github.tar, level 7 row 1 with dict copy, advanced one pass, 37839 github.tar, level 7 row 1 with dict load, advanced one pass, 37445 github.tar, level 7 row 2, advanced one pass, 38235 -github.tar, level 7 row 2 with dict dms, advanced one pass, 38164 -github.tar, level 7 row 2 with dict dds, advanced one pass, 38169 -github.tar, level 7 row 2 with dict copy, advanced one pass, 38294 +github.tar, level 7 row 2 with dict dms, advanced one pass, 38012 +github.tar, level 7 row 2 with dict dds, advanced one pass, 38014 +github.tar, level 7 row 2 with dict copy, advanced one pass, 38101 github.tar, level 7 row 2 with dict load, advanced one pass, 37552 github.tar, level 7, advanced one pass, 38168 -github.tar, level 7 with dict, advanced one pass, 37975 -github.tar, level 7 with dict dms, advanced one pass, 38001 -github.tar, level 7 with dict dds, advanced one pass, 38008 -github.tar, level 7 with dict copy, advanced one pass, 37975 +github.tar, level 7 with dict, advanced one pass, 37839 +github.tar, level 7 with dict dms, advanced one pass, 37832 +github.tar, level 7 with dict dds, advanced one pass, 37857 +github.tar, level 7 with dict copy, advanced one pass, 37839 github.tar, level 7 with dict load, advanced one pass, 37445 -github.tar, level 9, advanced one pass, 36897 -github.tar, level 9 with dict, advanced one pass, 36689 -github.tar, level 9 with dict dms, advanced one pass, 36756 -github.tar, level 9 with dict dds, advanced one pass, 36817 -github.tar, level 9 with dict copy, advanced one pass, 36689 -github.tar, level 9 with dict load, advanced one pass, 36484 -github.tar, level 11 row 1, advanced one pass, 36234 +github.tar, level 9, advanced one pass, 36723 +github.tar, level 9 with dict, advanced one pass, 36531 +github.tar, level 9 with dict dms, advanced one pass, 36615 +github.tar, level 9 with dict dds, advanced one pass, 36682 +github.tar, level 9 with dict copy, advanced one pass, 36531 +github.tar, level 9 with dict load, advanced one pass, 36322 +github.tar, level 11 row 1, advanced one pass, 36085 github.tar, level 11 row 1 with dict dms, advanced one pass, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass, 36567 -github.tar, level 11 row 2, advanced one pass, 36217 +github.tar, level 11 row 1 with dict load, advanced one pass, 36423 +github.tar, level 11 row 2, advanced one pass, 36110 github.tar, level 11 row 2 with dict dms, advanced one pass, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass, 36586 -github.tar, level 12 row 1, advanced one pass, 36234 +github.tar, level 11 row 2 with dict load, advanced one pass, 36459 +github.tar, level 12 row 1, advanced one pass, 36085 github.tar, level 12 row 1 with dict dms, advanced one pass, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass, 36567 -github.tar, level 12 row 2, advanced one pass, 36217 +github.tar, level 12 row 1 with dict load, advanced one pass, 36423 +github.tar, level 12 row 2, advanced one pass, 36110 github.tar, level 12 row 2 with dict dms, advanced one pass, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass, 36586 +github.tar, level 12 row 2 with dict load, advanced one pass, 36459 github.tar, level 13, advanced one pass, 35501 github.tar, level 13 with dict, advanced one pass, 37130 github.tar, level 13 with dict dms, advanced one pass, 37220 @@ -560,12 +560,12 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass small out, 4567954 silesia, level 7 row 2, advanced one pass small out, 4562774 silesia, level 7, advanced one pass small out, 4567954 -silesia, level 9, advanced one pass small out, 4543669 -silesia, level 11 row 1, advanced one pass small out, 4503577 -silesia, level 11 row 2, advanced one pass small out, 4501229 -silesia, level 12 row 1, advanced one pass small out, 4503577 -silesia, level 12 row 2, advanced one pass small out, 4501229 -silesia, level 13, advanced one pass small out, 4484875 +silesia, level 9, advanced one pass small out, 4535624 +silesia, level 11 row 1, advanced one pass small out, 4495623 +silesia, level 11 row 2, advanced one pass small out, 4493258 +silesia, level 12 row 1, advanced one pass small out, 4495623 +silesia, level 12 row 2, advanced one pass small out, 4493258 +silesia, level 13, advanced one pass small out, 4484013 silesia, level 16, advanced one pass small out, 4356207 silesia, level 19, advanced one pass small out, 4266751 silesia, no source size, advanced one pass small out, 4838417 @@ -594,12 +594,12 @@ silesia.tar, level 6, advanced silesia.tar, level 7 row 1, advanced one pass small out, 4570873 silesia.tar, level 7 row 2, advanced one pass small out, 4566314 silesia.tar, level 7, advanced one pass small out, 4570873 -silesia.tar, level 9, advanced one pass small out, 4546477 -silesia.tar, level 11 row 1, advanced one pass small out, 4505875 -silesia.tar, level 11 row 2, advanced one pass small out, 4504435 -silesia.tar, level 12 row 1, advanced one pass small out, 4505461 -silesia.tar, level 12 row 2, advanced one pass small out, 4504644 -silesia.tar, level 13, advanced one pass small out, 4486256 +silesia.tar, level 9, advanced one pass small out, 4537558 +silesia.tar, level 11 row 1, advanced one pass small out, 4496590 +silesia.tar, level 11 row 2, advanced one pass small out, 4495225 +silesia.tar, level 12 row 1, advanced one pass small out, 4496084 +silesia.tar, level 12 row 2, advanced one pass small out, 4495434 +silesia.tar, level 13, advanced one pass small out, 4484732 silesia.tar, level 16, advanced one pass small out, 4355572 silesia.tar, level 19, advanced one pass small out, 4257629 silesia.tar, no source size, advanced one pass small out, 4843429 @@ -792,47 +792,47 @@ github.tar, level 6 with dict dds, advanced github.tar, level 6 with dict copy, advanced one pass small out, 38808 github.tar, level 6 with dict load, advanced one pass small out, 38796 github.tar, level 7 row 1, advanced one pass small out, 38168 -github.tar, level 7 row 1 with dict dms, advanced one pass small out, 38001 -github.tar, level 7 row 1 with dict dds, advanced one pass small out, 38008 -github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 row 1 with dict dms, advanced one pass small out, 37832 +github.tar, level 7 row 1 with dict dds, advanced one pass small out, 37857 +github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37839 github.tar, level 7 row 1 with dict load, advanced one pass small out, 37445 github.tar, level 7 row 2, advanced one pass small out, 38235 -github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38164 -github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38169 -github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38294 +github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38012 +github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38014 +github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38101 github.tar, level 7 row 2 with dict load, advanced one pass small out, 37552 github.tar, level 7, advanced one pass small out, 38168 -github.tar, level 7 with dict, advanced one pass small out, 37975 -github.tar, level 7 with dict dms, advanced one pass small out, 38001 -github.tar, level 7 with dict dds, advanced one pass small out, 38008 -github.tar, level 7 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 with dict, advanced one pass small out, 37839 +github.tar, level 7 with dict dms, advanced one pass small out, 37832 +github.tar, level 7 with dict dds, advanced one pass small out, 37857 +github.tar, level 7 with dict copy, advanced one pass small out, 37839 github.tar, level 7 with dict load, advanced one pass small out, 37445 -github.tar, level 9, advanced one pass small out, 36897 -github.tar, level 9 with dict, advanced one pass small out, 36689 -github.tar, level 9 with dict dms, advanced one pass small out, 36756 -github.tar, level 9 with dict dds, advanced one pass small out, 36817 -github.tar, level 9 with dict copy, advanced one pass small out, 36689 -github.tar, level 9 with dict load, advanced one pass small out, 36484 -github.tar, level 11 row 1, advanced one pass small out, 36234 +github.tar, level 9, advanced one pass small out, 36723 +github.tar, level 9 with dict, advanced one pass small out, 36531 +github.tar, level 9 with dict dms, advanced one pass small out, 36615 +github.tar, level 9 with dict dds, advanced one pass small out, 36682 +github.tar, level 9 with dict copy, advanced one pass small out, 36531 +github.tar, level 9 with dict load, advanced one pass small out, 36322 +github.tar, level 11 row 1, advanced one pass small out, 36085 github.tar, level 11 row 1 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass small out, 36567 -github.tar, level 11 row 2, advanced one pass small out, 36217 +github.tar, level 11 row 1 with dict load, advanced one pass small out, 36423 +github.tar, level 11 row 2, advanced one pass small out, 36110 github.tar, level 11 row 2 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass small out, 36586 -github.tar, level 12 row 1, advanced one pass small out, 36234 +github.tar, level 11 row 2 with dict load, advanced one pass small out, 36459 +github.tar, level 12 row 1, advanced one pass small out, 36085 github.tar, level 12 row 1 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass small out, 36567 -github.tar, level 12 row 2, advanced one pass small out, 36217 +github.tar, level 12 row 1 with dict load, advanced one pass small out, 36423 +github.tar, level 12 row 2, advanced one pass small out, 36110 github.tar, level 12 row 2 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass small out, 36586 +github.tar, level 12 row 2 with dict load, advanced one pass small out, 36459 github.tar, level 13, advanced one pass small out, 35501 github.tar, level 13 with dict, advanced one pass small out, 37130 github.tar, level 13 with dict dms, advanced one pass small out, 37220 From 18b1e67223823e48a96ed9f2ae489e8989802e42 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:51:52 -0700 Subject: [PATCH 137/405] fixed extraneous return strict C90 compliance test --- lib/compress/zstd_preSplit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 2e65f88d9..4ca30dfce 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -63,7 +63,7 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, s #define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ static void ADDEVENTS_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ { \ - return addEvents_generic(fp, src, srcSize, _rate); \ + addEvents_generic(fp, src, srcSize, _rate); \ } ZSTD_GEN_ADDEVENTS_SAMPLE(1); From 57239c4d3b5a21529ade206241f3f0a4815f2295 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 21:49:35 -0700 Subject: [PATCH 138/405] fixed minor strict pedantic C90 issue --- lib/compress/zstd_preSplit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 4ca30dfce..e8994dcde 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -66,8 +66,8 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, s addEvents_generic(fp, src, srcSize, _rate); \ } -ZSTD_GEN_ADDEVENTS_SAMPLE(1); -ZSTD_GEN_ADDEVENTS_SAMPLE(5); +ZSTD_GEN_ADDEVENTS_SAMPLE(1) +ZSTD_GEN_ADDEVENTS_SAMPLE(5) typedef void (*addEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); From b68ddce818c274b9651ba47d45e46f7ffb4592ae Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 11:10:07 -0700 Subject: [PATCH 139/405] rewrite fingerprint storage to no longer need 64-bit members so that it can be stored using standard alignment requirement (sizeof(void*)). Distance function still requires 64-bit signed multiplication though, so it won't change the issue regarding the bug in ubsan for clang 32-bit on github ci. --- lib/compress/zstd_compress.c | 6 +++--- lib/compress/zstd_preSplit.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 05c1faa9f..b064e382c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -141,7 +141,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) if (!ZSTD_cwksp_check_available(&cctx->workspace, TMP_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(&cctx->workspace, TMP_WORKSPACE_SIZE, sizeof(S64)); + cctx->tmpWorkspace = ZSTD_cwksp_reserve_object(&cctx->workspace, TMP_WORKSPACE_SIZE); cctx->tmpWkspSize = TMP_WORKSPACE_SIZE; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; @@ -1709,7 +1709,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(seqDef)) + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const tmpWorkSpace = ZSTD_cwksp_aligned_alloc_size(TMP_WORKSPACE_SIZE, sizeof(S64)); + size_t const tmpWorkSpace = ZSTD_cwksp_alloc_size(TMP_WORKSPACE_SIZE); size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); @@ -2174,7 +2174,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(ws, TMP_WORKSPACE_SIZE, sizeof(S64)); + zc->tmpWorkspace = ZSTD_cwksp_reserve_object(ws, TMP_WORKSPACE_SIZE); RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, "couldn't allocate tmpWorkspace"); zc->tmpWkspSize = TMP_WORKSPACE_SIZE; } } diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index e8994dcde..c658f6fe5 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -33,8 +33,8 @@ static unsigned hash2(const void *p) typedef struct { - int events[HASHTABLESIZE]; - S64 nbEvents; + unsigned events[HASHTABLESIZE]; + size_t nbEvents; } Fingerprint; typedef struct { Fingerprint pastEvents; @@ -78,15 +78,15 @@ static void recordFingerprint(Fingerprint* fp, const void* src, size_t s, addEve addEvents(fp, src, s); } -static S64 abs64(S64 i) { return (i < 0) ? -i : i; } +static U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); } -static S64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) +static U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) { - S64 distance = 0; + U64 distance = 0; size_t n; for (n = 0; n < HASHTABLESIZE; n++) { distance += - abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); + abs64((S64)fp1->events[n] * (S64)fp2->nbEvents - (S64)fp2->events[n] * (S64)fp1->nbEvents); } return distance; } @@ -100,9 +100,9 @@ static int compareFingerprints(const Fingerprint* ref, { assert(ref->nbEvents > 0); assert(newfp->nbEvents > 0); - { S64 p50 = ref->nbEvents * newfp->nbEvents; - S64 deviation = fpDistance(ref, newfp); - S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; + { U64 p50 = (U64)ref->nbEvents * (U64)newfp->nbEvents; + U64 deviation = fpDistance(ref, newfp); + U64 threshold = p50 * (U64)(THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } } @@ -150,7 +150,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, assert(blockSizeMax == (128 << 10)); assert(workspace != NULL); assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0); - ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE == sizeof(FPStats)); + ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats)); assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); From 7d3e5e3ba1007635fc991a3b208353463cb2712d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 14:11:49 -0700 Subject: [PATCH 140/405] split all full 128 KB blocks this helps make the streaming behavior more consistent, since it does no longer depend on having more data presented on the input. suggested by @terrelln --- lib/compress/zstd_compress.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b064e382c..9de92cef2 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4493,20 +4493,21 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - /* note: conservatively only split full blocks (128 KB) currently, - * and even then only if there is more than 128 KB input remaining. + /* note: conservatively only split full blocks (128 KB) currently. + * While it's possible to go lower, let's keep it simple for a first implementation. + * Besides, benefits of splitting are reduced when blocks are already small. */ - if (srcSize <= 128 KB || blockSizeMax < 128 KB) + if (srcSize < 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); /* dynamic splitting has a cpu cost for analysis, - * due to that cost it's only used for btlazy2+ strategies */ + * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_lazy2) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy - * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". + * no cpu cost, but can over-split homegeneous data. * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ return savings ? 92 KB : 128 KB; From c80645a055d19f7e77cff3c268d818f811b9e1bb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 14:55:10 -0700 Subject: [PATCH 141/405] stricter limits to ensure expansion factor with blind-split strategy issue reported by @terrelln --- lib/compress/zstd_compress.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9de92cef2..3ab7414d4 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4506,11 +4506,11 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src if (strat >= ZSTD_lazy2) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy - * heuristic, tested as being "generally better". + * heuristic value, tested as being "generally better". * no cpu cost, but can over-split homegeneous data. * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ - return savings ? 92 KB : 128 KB; + return (savings > 3) ? 92 KB : 128 KB; } /*! ZSTD_compress_frameChunk() : @@ -4587,8 +4587,22 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ + /* @savings is employed by the blind-split strategy, + * to authorize splitting into less-than-full blocks, + * and thus avoid oversplitting blocks in case of incompressible data: + * when @savings is not large enough, blind split is disactivated, and full block is used instead. + * If data is incompressible, it's allowed to expand it by 3-bytes per full block. + * For large data, a full block is 128 KB. + * blind-split will instead use 92 KB as block size. + * So it expands incompressible data by 3-bytes per 92 KB block. + * That's an over-expansion of ((128*3) - (92*3)) / 128 = 0.84 bytes per block. + * Therefore, when data doesn't shrink, we subtract a 1 byte malus from @savings. + * This is a conservative estimate, especially as we don't count the 3-bytes header when there are savings, + * but it doesn't matter, the goal is not accuracy, + * the goal is to ensure the 3-bytes expansion limit per 128 KB input can never be breached */ if (cSize < blockSize) savings += (blockSize - cSize); - else if (savings) savings--; + else savings--; + ip += blockSize; assert(remaining >= blockSize); remaining -= blockSize; From bbda1acf85d8e2f4045156e14943817c0a389503 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 15:56:56 -0700 Subject: [PATCH 142/405] update regression results --- tests/regression/results.csv | 482 +++++++++++++++++------------------ 1 file changed, 241 insertions(+), 241 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 3a14793dd..2ac686962 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -97,9 +97,9 @@ github, uncompressed literals, compress github, uncompressed literals optimal, compress cctx, 132879 github, huffman literals, compress cctx, 175468 github, multithreaded with advanced params, compress cctx, 141069 -silesia, level -5, zstdcli, 6856076 -silesia, level -3, zstdcli, 6505583 -silesia, level -1, zstdcli, 6172652 +silesia, level -5, zstdcli, 6856073 +silesia, level -3, zstdcli, 6505580 +silesia, level -1, zstdcli, 6172649 silesia, level 0, zstdcli, 4838997 silesia, level 1, zstdcli, 5306179 silesia, level 3, zstdcli, 4838997 @@ -864,20 +864,20 @@ github.tar, uncompressed literals, advanced github.tar, uncompressed literals optimal, advanced one pass small out, 35356 github.tar, huffman literals, advanced one pass small out, 39099 github.tar, multithreaded with advanced params, advanced one pass small out, 41700 -silesia, level -5, advanced streaming, 6854744 -silesia, level -3, advanced streaming, 6503319 -silesia, level -1, advanced streaming, 6172207 -silesia, level 0, advanced streaming, 4839431 -silesia, level 1, advanced streaming, 5306388 -silesia, level 3, advanced streaming, 4839431 -silesia, level 4, advanced streaming, 4776557 -silesia, level 5 row 1, advanced streaming, 4667668 -silesia, level 5 row 2, advanced streaming, 4670326 -silesia, level 5, advanced streaming, 4667668 -silesia, level 6, advanced streaming, 4604351 -silesia, level 7 row 1, advanced streaming, 4570271 -silesia, level 7 row 2, advanced streaming, 4565169 -silesia, level 7, advanced streaming, 4570271 +silesia, level -5, advanced streaming, 6856699 +silesia, level -3, advanced streaming, 6505694 +silesia, level -1, advanced streaming, 6174139 +silesia, level 0, advanced streaming, 4839173 +silesia, level 1, advanced streaming, 5305682 +silesia, level 3, advanced streaming, 4839173 +silesia, level 4, advanced streaming, 4776074 +silesia, level 5 row 1, advanced streaming, 4667049 +silesia, level 5 row 2, advanced streaming, 4669474 +silesia, level 5, advanced streaming, 4667049 +silesia, level 6, advanced streaming, 4602956 +silesia, level 7 row 1, advanced streaming, 4568785 +silesia, level 7 row 2, advanced streaming, 4563722 +silesia, level 7, advanced streaming, 4568785 silesia, level 9, advanced streaming, 4545850 silesia, level 11 row 1, advanced streaming, 4505658 silesia, level 11 row 2, advanced streaming, 4503429 @@ -886,32 +886,32 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced streaming, 4493990 silesia, level 16, advanced streaming, 4359652 silesia, level 19, advanced streaming, 4266582 -silesia, no source size, advanced streaming, 4839395 -silesia, long distance mode, advanced streaming, 4831158 +silesia, no source size, advanced streaming, 4839137 +silesia, long distance mode, advanced streaming, 4831125 silesia, multithreaded, advanced streaming, 4838949 silesia, multithreaded long distance mode, advanced streaming, 4830419 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6526141 silesia, small chain log, advanced streaming, 4912197 -silesia, explicit params, advanced streaming, 4795857 -silesia, uncompressed literals, advanced streaming, 5116957 +silesia, explicit params, advanced streaming, 4795053 +silesia, uncompressed literals, advanced streaming, 5117625 silesia, uncompressed literals optimal, advanced streaming, 4316880 -silesia, huffman literals, advanced streaming, 5321370 +silesia, huffman literals, advanced streaming, 5321812 silesia, multithreaded with advanced params, advanced streaming, 5117795 -silesia.tar, level -5, advanced streaming, 6856523 -silesia.tar, level -3, advanced streaming, 6505954 -silesia.tar, level -1, advanced streaming, 6179056 -silesia.tar, level 0, advanced streaming, 4858632 -silesia.tar, level 1, advanced streaming, 5327708 -silesia.tar, level 3, advanced streaming, 4858632 -silesia.tar, level 4, advanced streaming, 4796895 -silesia.tar, level 5 row 1, advanced streaming, 4679020 -silesia.tar, level 5 row 2, advanced streaming, 4682355 -silesia.tar, level 5, advanced streaming, 4679020 -silesia.tar, level 6, advanced streaming, 4614558 -silesia.tar, level 7 row 1, advanced streaming, 4579823 -silesia.tar, level 7 row 2, advanced streaming, 4575601 -silesia.tar, level 7, advanced streaming, 4579823 +silesia.tar, level -5, advanced streaming, 6857458 +silesia.tar, level -3, advanced streaming, 6508562 +silesia.tar, level -1, advanced streaming, 6178057 +silesia.tar, level 0, advanced streaming, 4849720 +silesia.tar, level 1, advanced streaming, 5311452 +silesia.tar, level 3, advanced streaming, 4849720 +silesia.tar, level 4, advanced streaming, 4787534 +silesia.tar, level 5 row 1, advanced streaming, 4669420 +silesia.tar, level 5 row 2, advanced streaming, 4673610 +silesia.tar, level 5, advanced streaming, 4669420 +silesia.tar, level 6, advanced streaming, 4604125 +silesia.tar, level 7 row 1, advanced streaming, 4570206 +silesia.tar, level 7 row 2, advanced streaming, 4565792 +silesia.tar, level 7, advanced streaming, 4570206 silesia.tar, level 9, advanced streaming, 4555445 silesia.tar, level 11 row 1, advanced streaming, 4514959 silesia.tar, level 11 row 2, advanced streaming, 4513810 @@ -920,17 +920,17 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced streaming, 4502956 silesia.tar, level 16, advanced streaming, 4360385 silesia.tar, level 19, advanced streaming, 4260939 -silesia.tar, no source size, advanced streaming, 4858628 -silesia.tar, long distance mode, advanced streaming, 4837775 +silesia.tar, no source size, advanced streaming, 4849716 +silesia.tar, long distance mode, advanced streaming, 4829339 silesia.tar, multithreaded, advanced streaming, 4841902 silesia.tar, multithreaded long distance mode, advanced streaming, 4834262 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529209 silesia.tar, small chain log, advanced streaming, 4917021 -silesia.tar, explicit params, advanced streaming, 4807288 -silesia.tar, uncompressed literals, advanced streaming, 5126542 +silesia.tar, explicit params, advanced streaming, 4797673 +silesia.tar, uncompressed literals, advanced streaming, 5124811 silesia.tar, uncompressed literals optimal, advanced streaming, 4308451 -silesia.tar, huffman literals, advanced streaming, 5341712 +silesia.tar, huffman literals, advanced streaming, 5326278 silesia.tar, multithreaded with advanced params, advanced streaming, 5116442 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 @@ -1057,74 +1057,74 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced streaming, 152667 github, huffman literals, advanced streaming, 142365 github, multithreaded with advanced params, advanced streaming, 165909 -github.tar, level -5, advanced streaming, 52152 -github.tar, level -5 with dict, advanced streaming, 51181 -github.tar, level -3, advanced streaming, 45678 -github.tar, level -3 with dict, advanced streaming, 44734 -github.tar, level -1, advanced streaming, 42560 -github.tar, level -1 with dict, advanced streaming, 41353 -github.tar, level 0, advanced streaming, 38884 -github.tar, level 0 with dict, advanced streaming, 37995 -github.tar, level 0 with dict dms, advanced streaming, 38114 -github.tar, level 0 with dict dds, advanced streaming, 38114 -github.tar, level 0 with dict copy, advanced streaming, 37995 -github.tar, level 0 with dict load, advanced streaming, 37956 -github.tar, level 1, advanced streaming, 39200 -github.tar, level 1 with dict, advanced streaming, 38119 -github.tar, level 1 with dict dms, advanced streaming, 38406 -github.tar, level 1 with dict dds, advanced streaming, 38406 -github.tar, level 1 with dict copy, advanced streaming, 38119 -github.tar, level 1 with dict load, advanced streaming, 38364 -github.tar, level 3, advanced streaming, 38884 -github.tar, level 3 with dict, advanced streaming, 37995 -github.tar, level 3 with dict dms, advanced streaming, 38114 -github.tar, level 3 with dict dds, advanced streaming, 38114 -github.tar, level 3 with dict copy, advanced streaming, 37995 -github.tar, level 3 with dict load, advanced streaming, 37956 -github.tar, level 4, advanced streaming, 38880 -github.tar, level 4 with dict, advanced streaming, 37948 -github.tar, level 4 with dict dms, advanced streaming, 37995 -github.tar, level 4 with dict dds, advanced streaming, 37995 -github.tar, level 4 with dict copy, advanced streaming, 37948 -github.tar, level 4 with dict load, advanced streaming, 37927 -github.tar, level 5 row 1, advanced streaming, 39651 -github.tar, level 5 row 1 with dict dms, advanced streaming, 39043 -github.tar, level 5 row 1 with dict dds, advanced streaming, 39069 -github.tar, level 5 row 1 with dict copy, advanced streaming, 39145 -github.tar, level 5 row 1 with dict load, advanced streaming, 39000 -github.tar, level 5 row 2, advanced streaming, 39701 -github.tar, level 5 row 2 with dict dms, advanced streaming, 39365 -github.tar, level 5 row 2 with dict dds, advanced streaming, 39233 -github.tar, level 5 row 2 with dict copy, advanced streaming, 39715 -github.tar, level 5 row 2 with dict load, advanced streaming, 39158 -github.tar, level 5, advanced streaming, 39651 -github.tar, level 5 with dict, advanced streaming, 39145 -github.tar, level 5 with dict dms, advanced streaming, 39043 -github.tar, level 5 with dict dds, advanced streaming, 39069 -github.tar, level 5 with dict copy, advanced streaming, 39145 -github.tar, level 5 with dict load, advanced streaming, 39000 -github.tar, level 6, advanced streaming, 39282 -github.tar, level 6 with dict, advanced streaming, 38656 -github.tar, level 6 with dict dms, advanced streaming, 38640 -github.tar, level 6 with dict dds, advanced streaming, 38643 -github.tar, level 6 with dict copy, advanced streaming, 38656 -github.tar, level 6 with dict load, advanced streaming, 38647 -github.tar, level 7 row 1, advanced streaming, 38005 +github.tar, level -5, advanced streaming, 52384 +github.tar, level -5 with dict, advanced streaming, 51420 +github.tar, level -3, advanced streaming, 45907 +github.tar, level -3 with dict, advanced streaming, 44973 +github.tar, level -1, advanced streaming, 42777 +github.tar, level -1 with dict, advanced streaming, 41603 +github.tar, level 0, advanced streaming, 39249 +github.tar, level 0 with dict, advanced streaming, 38309 +github.tar, level 0 with dict dms, advanced streaming, 38445 +github.tar, level 0 with dict dds, advanced streaming, 38445 +github.tar, level 0 with dict copy, advanced streaming, 38309 +github.tar, level 0 with dict load, advanced streaming, 38281 +github.tar, level 1, advanced streaming, 39550 +github.tar, level 1 with dict, advanced streaming, 38502 +github.tar, level 1 with dict dms, advanced streaming, 38770 +github.tar, level 1 with dict dds, advanced streaming, 38770 +github.tar, level 1 with dict copy, advanced streaming, 38502 +github.tar, level 1 with dict load, advanced streaming, 38716 +github.tar, level 3, advanced streaming, 39249 +github.tar, level 3 with dict, advanced streaming, 38309 +github.tar, level 3 with dict dms, advanced streaming, 38445 +github.tar, level 3 with dict dds, advanced streaming, 38445 +github.tar, level 3 with dict copy, advanced streaming, 38309 +github.tar, level 3 with dict load, advanced streaming, 38281 +github.tar, level 4, advanced streaming, 39247 +github.tar, level 4 with dict, advanced streaming, 38270 +github.tar, level 4 with dict dms, advanced streaming, 38317 +github.tar, level 4 with dict dds, advanced streaming, 38317 +github.tar, level 4 with dict copy, advanced streaming, 38270 +github.tar, level 4 with dict load, advanced streaming, 38259 +github.tar, level 5 row 1, advanced streaming, 39986 +github.tar, level 5 row 1 with dict dms, advanced streaming, 39370 +github.tar, level 5 row 1 with dict dds, advanced streaming, 39396 +github.tar, level 5 row 1 with dict copy, advanced streaming, 39465 +github.tar, level 5 row 1 with dict load, advanced streaming, 39332 +github.tar, level 5 row 2, advanced streaming, 40038 +github.tar, level 5 row 2 with dict dms, advanced streaming, 39690 +github.tar, level 5 row 2 with dict dds, advanced streaming, 39555 +github.tar, level 5 row 2 with dict copy, advanced streaming, 40036 +github.tar, level 5 row 2 with dict load, advanced streaming, 39498 +github.tar, level 5, advanced streaming, 39986 +github.tar, level 5 with dict, advanced streaming, 39465 +github.tar, level 5 with dict dms, advanced streaming, 39370 +github.tar, level 5 with dict dds, advanced streaming, 39396 +github.tar, level 5 with dict copy, advanced streaming, 39465 +github.tar, level 5 with dict load, advanced streaming, 39332 +github.tar, level 6, advanced streaming, 39565 +github.tar, level 6 with dict, advanced streaming, 38894 +github.tar, level 6 with dict dms, advanced streaming, 38901 +github.tar, level 6 with dict dds, advanced streaming, 38903 +github.tar, level 6 with dict copy, advanced streaming, 38894 +github.tar, level 6 with dict load, advanced streaming, 38906 +github.tar, level 7 row 1, advanced streaming, 38295 github.tar, level 7 row 1 with dict dms, advanced streaming, 37832 github.tar, level 7 row 1 with dict dds, advanced streaming, 37857 github.tar, level 7 row 1 with dict copy, advanced streaming, 37839 -github.tar, level 7 row 1 with dict load, advanced streaming, 37286 -github.tar, level 7 row 2, advanced streaming, 38077 +github.tar, level 7 row 1 with dict load, advanced streaming, 37565 +github.tar, level 7 row 2, advanced streaming, 38369 github.tar, level 7 row 2 with dict dms, advanced streaming, 38012 github.tar, level 7 row 2 with dict dds, advanced streaming, 38014 github.tar, level 7 row 2 with dict copy, advanced streaming, 38101 -github.tar, level 7 row 2 with dict load, advanced streaming, 37402 -github.tar, level 7, advanced streaming, 38005 +github.tar, level 7 row 2 with dict load, advanced streaming, 37688 +github.tar, level 7, advanced streaming, 38295 github.tar, level 7 with dict, advanced streaming, 37839 github.tar, level 7 with dict dms, advanced streaming, 37832 github.tar, level 7 with dict dds, advanced streaming, 37857 github.tar, level 7 with dict copy, advanced streaming, 37839 -github.tar, level 7 with dict load, advanced streaming, 37286 +github.tar, level 7 with dict load, advanced streaming, 37565 github.tar, level 9, advanced streaming, 36723 github.tar, level 9 with dict, advanced streaming, 36531 github.tar, level 9 with dict dms, advanced streaming, 36615 @@ -1169,55 +1169,55 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced streaming, 32565 github.tar, level 19 with dict copy, advanced streaming, 32701 github.tar, level 19 with dict load, advanced streaming, 32428 -github.tar, no source size, advanced streaming, 38881 -github.tar, no source size with dict, advanced streaming, 38111 -github.tar, long distance mode, advanced streaming, 40242 +github.tar, no source size, advanced streaming, 39246 +github.tar, no source size with dict, advanced streaming, 38442 +github.tar, long distance mode, advanced streaming, 40569 github.tar, multithreaded, advanced streaming, 39067 github.tar, multithreaded long distance mode, advanced streaming, 40377 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 -github.tar, explicit params, advanced streaming, 41385 -github.tar, uncompressed literals, advanced streaming, 41562 +github.tar, explicit params, advanced streaming, 41768 +github.tar, uncompressed literals, advanced streaming, 41784 github.tar, uncompressed literals optimal, advanced streaming, 35356 -github.tar, huffman literals, advanced streaming, 38853 +github.tar, huffman literals, advanced streaming, 39226 github.tar, multithreaded with advanced params, advanced streaming, 41700 -silesia, level -5, old streaming, 6854744 -silesia, level -3, old streaming, 6503319 -silesia, level -1, old streaming, 6172207 -silesia, level 0, old streaming, 4839431 -silesia, level 1, old streaming, 5306388 -silesia, level 3, old streaming, 4839431 -silesia, level 4, old streaming, 4776557 -silesia, level 5, old streaming, 4667668 -silesia, level 6, old streaming, 4604351 -silesia, level 7, old streaming, 4570271 +silesia, level -5, old streaming, 6856699 +silesia, level -3, old streaming, 6505694 +silesia, level -1, old streaming, 6174139 +silesia, level 0, old streaming, 4839173 +silesia, level 1, old streaming, 5305682 +silesia, level 3, old streaming, 4839173 +silesia, level 4, old streaming, 4776074 +silesia, level 5, old streaming, 4667049 +silesia, level 6, old streaming, 4602956 +silesia, level 7, old streaming, 4568785 silesia, level 9, old streaming, 4545850 silesia, level 13, old streaming, 4493990 silesia, level 16, old streaming, 4359652 silesia, level 19, old streaming, 4266582 -silesia, no source size, old streaming, 4839395 -silesia, uncompressed literals, old streaming, 4839431 +silesia, no source size, old streaming, 4839137 +silesia, uncompressed literals, old streaming, 4839173 silesia, uncompressed literals optimal, old streaming, 4266582 -silesia, huffman literals, old streaming, 6172207 -silesia.tar, level -5, old streaming, 6856523 -silesia.tar, level -3, old streaming, 6505954 -silesia.tar, level -1, old streaming, 6179056 -silesia.tar, level 0, old streaming, 4858632 -silesia.tar, level 1, old streaming, 5327708 -silesia.tar, level 3, old streaming, 4858632 -silesia.tar, level 4, old streaming, 4796895 -silesia.tar, level 5, old streaming, 4679020 -silesia.tar, level 6, old streaming, 4614558 -silesia.tar, level 7, old streaming, 4579823 +silesia, huffman literals, old streaming, 6174139 +silesia.tar, level -5, old streaming, 6857458 +silesia.tar, level -3, old streaming, 6508562 +silesia.tar, level -1, old streaming, 6178057 +silesia.tar, level 0, old streaming, 4849720 +silesia.tar, level 1, old streaming, 5311452 +silesia.tar, level 3, old streaming, 4849720 +silesia.tar, level 4, old streaming, 4787534 +silesia.tar, level 5, old streaming, 4669420 +silesia.tar, level 6, old streaming, 4604125 +silesia.tar, level 7, old streaming, 4570206 silesia.tar, level 9, old streaming, 4555445 silesia.tar, level 13, old streaming, 4502956 silesia.tar, level 16, old streaming, 4360385 silesia.tar, level 19, old streaming, 4260939 -silesia.tar, no source size, old streaming, 4858628 -silesia.tar, uncompressed literals, old streaming, 4858632 +silesia.tar, no source size, old streaming, 4849716 +silesia.tar, uncompressed literals, old streaming, 4849720 silesia.tar, uncompressed literals optimal, old streaming, 4260939 -silesia.tar, huffman literals, old streaming, 6179056 +silesia.tar, huffman literals, old streaming, 6178057 github, level -5, old streaming, 204407 github, level -5 with dict, old streaming, 45832 github, level -3, old streaming, 193253 @@ -1251,25 +1251,25 @@ github, no source size with dict, old stre github, uncompressed literals, old streaming, 136331 github, uncompressed literals optimal, old streaming, 132879 github, huffman literals, old streaming, 175468 -github.tar, level -5, old streaming, 52152 -github.tar, level -5 with dict, old streaming, 51181 -github.tar, level -3, old streaming, 45678 -github.tar, level -3 with dict, old streaming, 44734 -github.tar, level -1, old streaming, 42560 -github.tar, level -1 with dict, old streaming, 41353 -github.tar, level 0, old streaming, 38884 -github.tar, level 0 with dict, old streaming, 37995 -github.tar, level 1, old streaming, 39200 -github.tar, level 1 with dict, old streaming, 38119 -github.tar, level 3, old streaming, 38884 -github.tar, level 3 with dict, old streaming, 37995 -github.tar, level 4, old streaming, 38880 -github.tar, level 4 with dict, old streaming, 37948 -github.tar, level 5, old streaming, 39651 -github.tar, level 5 with dict, old streaming, 39145 -github.tar, level 6, old streaming, 39282 -github.tar, level 6 with dict, old streaming, 38656 -github.tar, level 7, old streaming, 38005 +github.tar, level -5, old streaming, 52384 +github.tar, level -5 with dict, old streaming, 51420 +github.tar, level -3, old streaming, 45907 +github.tar, level -3 with dict, old streaming, 44973 +github.tar, level -1, old streaming, 42777 +github.tar, level -1 with dict, old streaming, 41603 +github.tar, level 0, old streaming, 39249 +github.tar, level 0 with dict, old streaming, 38309 +github.tar, level 1, old streaming, 39550 +github.tar, level 1 with dict, old streaming, 38502 +github.tar, level 3, old streaming, 39249 +github.tar, level 3 with dict, old streaming, 38309 +github.tar, level 4, old streaming, 39247 +github.tar, level 4 with dict, old streaming, 38270 +github.tar, level 5, old streaming, 39986 +github.tar, level 5 with dict, old streaming, 39465 +github.tar, level 6, old streaming, 39565 +github.tar, level 6 with dict, old streaming, 38894 +github.tar, level 7, old streaming, 38295 github.tar, level 7 with dict, old streaming, 37839 github.tar, level 9, old streaming, 36723 github.tar, level 9 with dict, old streaming, 36531 @@ -1279,63 +1279,63 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming, 33375 github.tar, level 19, old streaming, 32262 github.tar, level 19 with dict, old streaming, 32701 -github.tar, no source size, old streaming, 38881 -github.tar, no source size with dict, old streaming, 38111 -github.tar, uncompressed literals, old streaming, 38884 +github.tar, no source size, old streaming, 39246 +github.tar, no source size with dict, old streaming, 38442 +github.tar, uncompressed literals, old streaming, 39249 github.tar, uncompressed literals optimal, old streaming, 32262 -github.tar, huffman literals, old streaming, 42560 -silesia, level -5, old streaming advanced, 6854744 -silesia, level -3, old streaming advanced, 6503319 -silesia, level -1, old streaming advanced, 6172207 -silesia, level 0, old streaming advanced, 4839431 -silesia, level 1, old streaming advanced, 5306388 -silesia, level 3, old streaming advanced, 4839431 -silesia, level 4, old streaming advanced, 4776557 -silesia, level 5, old streaming advanced, 4667668 -silesia, level 6, old streaming advanced, 4604351 -silesia, level 7, old streaming advanced, 4570271 +github.tar, huffman literals, old streaming, 42777 +silesia, level -5, old streaming advanced, 6856699 +silesia, level -3, old streaming advanced, 6505694 +silesia, level -1, old streaming advanced, 6174139 +silesia, level 0, old streaming advanced, 4839173 +silesia, level 1, old streaming advanced, 5305682 +silesia, level 3, old streaming advanced, 4839173 +silesia, level 4, old streaming advanced, 4776074 +silesia, level 5, old streaming advanced, 4667049 +silesia, level 6, old streaming advanced, 4602956 +silesia, level 7, old streaming advanced, 4568785 silesia, level 9, old streaming advanced, 4545850 silesia, level 13, old streaming advanced, 4493990 silesia, level 16, old streaming advanced, 4359652 silesia, level 19, old streaming advanced, 4266582 -silesia, no source size, old streaming advanced, 4839395 -silesia, long distance mode, old streaming advanced, 4839431 -silesia, multithreaded, old streaming advanced, 4839431 -silesia, multithreaded long distance mode, old streaming advanced, 4839431 +silesia, no source size, old streaming advanced, 4839137 +silesia, long distance mode, old streaming advanced, 4839173 +silesia, multithreaded, old streaming advanced, 4839173 +silesia, multithreaded long distance mode, old streaming advanced, 4839173 silesia, small window log, old streaming advanced, 7110591 silesia, small hash log, old streaming advanced, 6526141 silesia, small chain log, old streaming advanced, 4912197 -silesia, explicit params, old streaming advanced, 4795857 -silesia, uncompressed literals, old streaming advanced, 4839431 +silesia, explicit params, old streaming advanced, 4795053 +silesia, uncompressed literals, old streaming advanced, 4839173 silesia, uncompressed literals optimal, old streaming advanced, 4266582 -silesia, huffman literals, old streaming advanced, 6172207 -silesia, multithreaded with advanced params, old streaming advanced, 4839431 -silesia.tar, level -5, old streaming advanced, 6856523 -silesia.tar, level -3, old streaming advanced, 6505954 -silesia.tar, level -1, old streaming advanced, 6179056 -silesia.tar, level 0, old streaming advanced, 4858632 -silesia.tar, level 1, old streaming advanced, 5327708 -silesia.tar, level 3, old streaming advanced, 4858632 -silesia.tar, level 4, old streaming advanced, 4796895 -silesia.tar, level 5, old streaming advanced, 4679020 -silesia.tar, level 6, old streaming advanced, 4614558 -silesia.tar, level 7, old streaming advanced, 4579823 +silesia, huffman literals, old streaming advanced, 6174139 +silesia, multithreaded with advanced params, old streaming advanced, 4839173 +silesia.tar, level -5, old streaming advanced, 6857458 +silesia.tar, level -3, old streaming advanced, 6508562 +silesia.tar, level -1, old streaming advanced, 6178057 +silesia.tar, level 0, old streaming advanced, 4849720 +silesia.tar, level 1, old streaming advanced, 5311452 +silesia.tar, level 3, old streaming advanced, 4849720 +silesia.tar, level 4, old streaming advanced, 4787534 +silesia.tar, level 5, old streaming advanced, 4669420 +silesia.tar, level 6, old streaming advanced, 4604125 +silesia.tar, level 7, old streaming advanced, 4570206 silesia.tar, level 9, old streaming advanced, 4555445 silesia.tar, level 13, old streaming advanced, 4502956 silesia.tar, level 16, old streaming advanced, 4360385 silesia.tar, level 19, old streaming advanced, 4260939 -silesia.tar, no source size, old streaming advanced, 4858628 -silesia.tar, long distance mode, old streaming advanced, 4858632 -silesia.tar, multithreaded, old streaming advanced, 4858632 -silesia.tar, multithreaded long distance mode, old streaming advanced, 4858632 +silesia.tar, no source size, old streaming advanced, 4849716 +silesia.tar, long distance mode, old streaming advanced, 4849720 +silesia.tar, multithreaded, old streaming advanced, 4849720 +silesia.tar, multithreaded long distance mode, old streaming advanced, 4849720 silesia.tar, small window log, old streaming advanced, 7117027 silesia.tar, small hash log, old streaming advanced, 6529209 silesia.tar, small chain log, old streaming advanced, 4917021 -silesia.tar, explicit params, old streaming advanced, 4807288 -silesia.tar, uncompressed literals, old streaming advanced, 4858632 +silesia.tar, explicit params, old streaming advanced, 4797673 +silesia.tar, uncompressed literals, old streaming advanced, 4849720 silesia.tar, uncompressed literals optimal, old streaming advanced, 4260939 -silesia.tar, huffman literals, old streaming advanced, 6179056 -silesia.tar, multithreaded with advanced params, old streaming advanced, 4858632 +silesia.tar, huffman literals, old streaming advanced, 6178057 +silesia.tar, multithreaded with advanced params, old streaming advanced, 4849720 github, level -5, old streaming advanced, 213265 github, level -5 with dict, old streaming advanced, 46708 github, level -3, old streaming advanced, 196126 @@ -1377,26 +1377,26 @@ github, uncompressed literals, old stre github, uncompressed literals optimal, old streaming advanced, 132879 github, huffman literals, old streaming advanced, 181107 github, multithreaded with advanced params, old streaming advanced, 141101 -github.tar, level -5, old streaming advanced, 52152 -github.tar, level -5 with dict, old streaming advanced, 51129 -github.tar, level -3, old streaming advanced, 45678 -github.tar, level -3 with dict, old streaming advanced, 44986 -github.tar, level -1, old streaming advanced, 42560 -github.tar, level -1 with dict, old streaming advanced, 41650 -github.tar, level 0, old streaming advanced, 38884 -github.tar, level 0 with dict, old streaming advanced, 38013 -github.tar, level 1, old streaming advanced, 39200 -github.tar, level 1 with dict, old streaming advanced, 38359 -github.tar, level 3, old streaming advanced, 38884 -github.tar, level 3 with dict, old streaming advanced, 38013 -github.tar, level 4, old streaming advanced, 38880 -github.tar, level 4 with dict, old streaming advanced, 38063 -github.tar, level 5, old streaming advanced, 39651 -github.tar, level 5 with dict, old streaming advanced, 39018 -github.tar, level 6, old streaming advanced, 39282 -github.tar, level 6 with dict, old streaming advanced, 38635 -github.tar, level 7, old streaming advanced, 38005 -github.tar, level 7 with dict, old streaming advanced, 37264 +github.tar, level -5, old streaming advanced, 52384 +github.tar, level -5 with dict, old streaming advanced, 51359 +github.tar, level -3, old streaming advanced, 45907 +github.tar, level -3 with dict, old streaming advanced, 45211 +github.tar, level -1, old streaming advanced, 42777 +github.tar, level -1 with dict, old streaming advanced, 41865 +github.tar, level 0, old streaming advanced, 39249 +github.tar, level 0 with dict, old streaming advanced, 38327 +github.tar, level 1, old streaming advanced, 39550 +github.tar, level 1 with dict, old streaming advanced, 38714 +github.tar, level 3, old streaming advanced, 39249 +github.tar, level 3 with dict, old streaming advanced, 38327 +github.tar, level 4, old streaming advanced, 39247 +github.tar, level 4 with dict, old streaming advanced, 38382 +github.tar, level 5, old streaming advanced, 39986 +github.tar, level 5 with dict, old streaming advanced, 39347 +github.tar, level 6, old streaming advanced, 39565 +github.tar, level 6 with dict, old streaming advanced, 38889 +github.tar, level 7, old streaming advanced, 38295 +github.tar, level 7 with dict, old streaming advanced, 37534 github.tar, level 9, old streaming advanced, 36723 github.tar, level 9 with dict, old streaming advanced, 36241 github.tar, level 13, old streaming advanced, 35501 @@ -1405,19 +1405,19 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming advanced, 38578 github.tar, level 19, old streaming advanced, 32262 github.tar, level 19 with dict, old streaming advanced, 32678 -github.tar, no source size, old streaming advanced, 38881 -github.tar, no source size with dict, old streaming advanced, 38076 -github.tar, long distance mode, old streaming advanced, 38884 -github.tar, multithreaded, old streaming advanced, 38884 -github.tar, multithreaded long distance mode, old streaming advanced, 38884 +github.tar, no source size, old streaming advanced, 39246 +github.tar, no source size with dict, old streaming advanced, 38399 +github.tar, long distance mode, old streaming advanced, 39249 +github.tar, multithreaded, old streaming advanced, 39249 +github.tar, multithreaded long distance mode, old streaming advanced, 39249 github.tar, small window log, old streaming advanced, 199556 github.tar, small hash log, old streaming advanced, 129870 github.tar, small chain log, old streaming advanced, 41669 -github.tar, explicit params, old streaming advanced, 41385 -github.tar, uncompressed literals, old streaming advanced, 38884 +github.tar, explicit params, old streaming advanced, 41768 +github.tar, uncompressed literals, old streaming advanced, 39249 github.tar, uncompressed literals optimal, old streaming advanced, 32262 -github.tar, huffman literals, old streaming advanced, 42560 -github.tar, multithreaded with advanced params, old streaming advanced, 38884 +github.tar, huffman literals, old streaming advanced, 42777 +github.tar, multithreaded with advanced params, old streaming advanced, 39249 github, level -5 with dict, old streaming cdict, 45832 github, level -3 with dict, old streaming cdict, 44671 github, level -1 with dict, old streaming cdict, 41825 @@ -1433,21 +1433,21 @@ github, level 13 with dict, old stre github, level 16 with dict, old streaming cdict, 37902 github, level 19 with dict, old streaming cdict, 37916 github, no source size with dict, old streaming cdict, 40652 -github.tar, level -5 with dict, old streaming cdict, 51286 -github.tar, level -3 with dict, old streaming cdict, 45147 -github.tar, level -1 with dict, old streaming cdict, 41865 -github.tar, level 0 with dict, old streaming cdict, 37956 -github.tar, level 1 with dict, old streaming cdict, 38364 -github.tar, level 3 with dict, old streaming cdict, 37956 -github.tar, level 4 with dict, old streaming cdict, 37927 -github.tar, level 5 with dict, old streaming cdict, 39000 -github.tar, level 6 with dict, old streaming cdict, 38647 -github.tar, level 7 with dict, old streaming cdict, 37286 +github.tar, level -5 with dict, old streaming cdict, 51512 +github.tar, level -3 with dict, old streaming cdict, 45379 +github.tar, level -1 with dict, old streaming cdict, 42084 +github.tar, level 0 with dict, old streaming cdict, 38281 +github.tar, level 1 with dict, old streaming cdict, 38716 +github.tar, level 3 with dict, old streaming cdict, 38281 +github.tar, level 4 with dict, old streaming cdict, 38259 +github.tar, level 5 with dict, old streaming cdict, 39332 +github.tar, level 6 with dict, old streaming cdict, 38906 +github.tar, level 7 with dict, old streaming cdict, 37565 github.tar, level 9 with dict, old streaming cdict, 36322 github.tar, level 13 with dict, old streaming cdict, 36010 github.tar, level 16 with dict, old streaming cdict, 39081 github.tar, level 19 with dict, old streaming cdict, 32428 -github.tar, no source size with dict, old streaming cdict, 38111 +github.tar, no source size with dict, old streaming cdict, 38442 github, level -5 with dict, old streaming advanced cdict, 46708 github, level -3 with dict, old streaming advanced cdict, 45476 github, level -1 with dict, old streaming advanced cdict, 42060 @@ -1463,18 +1463,18 @@ github, level 13 with dict, old stre github, level 16 with dict, old streaming advanced cdict, 40804 github, level 19 with dict, old streaming advanced cdict, 37916 github, no source size with dict, old streaming advanced cdict, 40608 -github.tar, level -5 with dict, old streaming advanced cdict, 50791 -github.tar, level -3 with dict, old streaming advanced cdict, 44926 -github.tar, level -1 with dict, old streaming advanced cdict, 41482 -github.tar, level 0 with dict, old streaming advanced cdict, 38013 -github.tar, level 1 with dict, old streaming advanced cdict, 38168 -github.tar, level 3 with dict, old streaming advanced cdict, 38013 -github.tar, level 4 with dict, old streaming advanced cdict, 38063 -github.tar, level 5 with dict, old streaming advanced cdict, 39018 -github.tar, level 6 with dict, old streaming advanced cdict, 38635 -github.tar, level 7 with dict, old streaming advanced cdict, 37264 +github.tar, level -5 with dict, old streaming advanced cdict, 51019 +github.tar, level -3 with dict, old streaming advanced cdict, 45149 +github.tar, level -1 with dict, old streaming advanced cdict, 41694 +github.tar, level 0 with dict, old streaming advanced cdict, 38327 +github.tar, level 1 with dict, old streaming advanced cdict, 38513 +github.tar, level 3 with dict, old streaming advanced cdict, 38327 +github.tar, level 4 with dict, old streaming advanced cdict, 38382 +github.tar, level 5 with dict, old streaming advanced cdict, 39347 +github.tar, level 6 with dict, old streaming advanced cdict, 38889 +github.tar, level 7 with dict, old streaming advanced cdict, 37534 github.tar, level 9 with dict, old streaming advanced cdict, 36241 github.tar, level 13 with dict, old streaming advanced cdict, 35807 github.tar, level 16 with dict, old streaming advanced cdict, 38578 github.tar, level 19 with dict, old streaming advanced cdict, 32678 -github.tar, no source size with dict, old streaming advanced cdict, 38076 +github.tar, no source size with dict, old streaming advanced cdict, 38399 From 90095f056d4ccb8e0ed0942b2e30a664f0489932 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 11:36:56 -0700 Subject: [PATCH 143/405] apply limit conditions for all splitting strategies instead of just for blind split. This is in anticipation of adversarial input, that would intentionally target the sampling pattern of the split detector. Note that, even without this protection, splitting can never expand beyond ZSTD_COMPRESSBOUND(), because this upper limit uses a 1KB block size worst case scenario, and splitting never creates blocks thath small. The protection is more to ensure that data is not expanded by more than 3-bytes per 128 KB full block, which is a much stricter limit. --- lib/compress/zstd_compress.c | 38 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3ab7414d4..437bd1fbe 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4499,6 +4499,11 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src */ if (srcSize < 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); + /* do not split incompressible data though: + * ensure a 3 bytes per full block overhead limit. + * Note: as a consequence, the first full block skips the splitting detector. + */ + if (savings < 3) return 128 KB; /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) @@ -4508,9 +4513,8 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src /* blind split strategy * heuristic value, tested as being "generally better". * no cpu cost, but can over-split homegeneous data. - * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ - return (savings > 3) ? 92 KB : 128 KB; + return 92 KB; } /*! ZSTD_compress_frameChunk() : @@ -4587,21 +4591,21 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ - /* @savings is employed by the blind-split strategy, - * to authorize splitting into less-than-full blocks, - * and thus avoid oversplitting blocks in case of incompressible data: - * when @savings is not large enough, blind split is disactivated, and full block is used instead. - * If data is incompressible, it's allowed to expand it by 3-bytes per full block. - * For large data, a full block is 128 KB. - * blind-split will instead use 92 KB as block size. - * So it expands incompressible data by 3-bytes per 92 KB block. - * That's an over-expansion of ((128*3) - (92*3)) / 128 = 0.84 bytes per block. - * Therefore, when data doesn't shrink, we subtract a 1 byte malus from @savings. - * This is a conservative estimate, especially as we don't count the 3-bytes header when there are savings, - * but it doesn't matter, the goal is not accuracy, - * the goal is to ensure the 3-bytes expansion limit per 128 KB input can never be breached */ - if (cSize < blockSize) savings += (blockSize - cSize); - else savings--; + /* @savings is employed to ensure that splitting doesn't worsen expansion of incompressible data. + * Without splitting, the maximum expansion is 3 bytes per full block. + * An adversarial input could attempt to fudge the split detector, + * and make it split incompressible data, resulting in more block headers. + * Note that, since ZSTD_COMPRESSBOUND() assumes a worst case scenario of 1KB per block, + * and the splitter never creates blocks that small (current lower limit is 8 KB), + * there is already no risk to expand beyond ZSTD_COMPRESSBOUND() limit. + * But if the goal is to not expand by more than 3-bytes per 128 KB full block, + * then yes, it becomes possible to make the block splitter oversplit incompressible data. + * Using @savings, we enforce an even more conservative condition, + * requiring the presence of enough savings (at least 3 bytes) to authorize splitting, + * otherwise only full blocks are used. + * But being conservative is fine, + * since splitting barely compressible blocks is not fruitful anyway */ + savings += (S64)blockSize - (S64)cSize; ip += blockSize; assert(remaining >= blockSize); From 70c77d20d63454b58e220c235e215147a357220c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 11:43:16 -0700 Subject: [PATCH 144/405] update regression results first block is no longer splitted since adding the @savings over-split protection --- tests/regression/results.csv | 72 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 2ac686962..ea5ed58d5 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -43,19 +43,19 @@ silesia, level 4, compress silesia, level 5, compress cctx, 4666524 silesia, level 6, compress cctx, 4602031 silesia, level 7, compress cctx, 4567954 -silesia, level 9, compress cctx, 4535624 -silesia, level 13, compress cctx, 4484013 -silesia, level 16, compress cctx, 4356207 -silesia, level 19, compress cctx, 4266751 +silesia, level 9, compress cctx, 4540520 +silesia, level 13, compress cctx, 4488969 +silesia, level 16, compress cctx, 4356799 +silesia, level 19, compress cctx, 4265851 silesia, long distance mode, compress cctx, 4838417 silesia, multithreaded, compress cctx, 4838417 silesia, multithreaded long distance mode, compress cctx, 4838417 silesia, small window log, compress cctx, 7082907 -silesia, small hash log, compress cctx, 6524931 -silesia, small chain log, compress cctx, 4912322 +silesia, small hash log, compress cctx, 6525510 +silesia, small chain log, compress cctx, 4912248 silesia, explicit params, compress cctx, 4792640 silesia, uncompressed literals, compress cctx, 4838417 -silesia, uncompressed literals optimal, compress cctx, 4266751 +silesia, uncompressed literals optimal, compress cctx, 4265851 silesia, huffman literals, compress cctx, 6174127 silesia, multithreaded with advanced params, compress cctx, 4838417 github, level -5, compress cctx, 204407 @@ -107,19 +107,19 @@ silesia, level 4, zstdcli, silesia, level 5, zstdcli, 4666931 silesia, level 6, zstdcli, 4602509 silesia, level 7, zstdcli, 4568265 -silesia, level 9, zstdcli, 4535309 -silesia, level 13, zstdcli, 4483601 -silesia, level 16, zstdcli, 4357591 -silesia, level 19, zstdcli, 4266865 +silesia, level 9, zstdcli, 4540123 +silesia, level 13, zstdcli, 4488478 +silesia, level 16, zstdcli, 4358150 +silesia, level 19, zstdcli, 4265929 silesia, long distance mode, zstdcli, 4830467 silesia, multithreaded, zstdcli, 4838997 silesia, multithreaded long distance mode, zstdcli, 4830467 silesia, small window log, zstdcli, 7094528 -silesia, small hash log, zstdcli, 6526639 -silesia, small chain log, zstdcli, 4911746 +silesia, small hash log, zstdcli, 6527214 +silesia, small chain log, zstdcli, 4911647 silesia, explicit params, zstdcli, 4794378 silesia, uncompressed literals, zstdcli, 5117843 -silesia, uncompressed literals optimal, zstdcli, 4317311 +silesia, uncompressed literals optimal, zstdcli, 4316761 silesia, huffman literals, zstdcli, 5320793 silesia, multithreaded with advanced params, zstdcli, 5117843 silesia.tar, level -5, zstdcli, 6860173 @@ -242,24 +242,24 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass, 4567954 silesia, level 7 row 2, advanced one pass, 4562774 silesia, level 7, advanced one pass, 4567954 -silesia, level 9, advanced one pass, 4535624 -silesia, level 11 row 1, advanced one pass, 4495623 -silesia, level 11 row 2, advanced one pass, 4493258 -silesia, level 12 row 1, advanced one pass, 4495623 -silesia, level 12 row 2, advanced one pass, 4493258 -silesia, level 13, advanced one pass, 4484013 -silesia, level 16, advanced one pass, 4356207 -silesia, level 19, advanced one pass, 4266751 +silesia, level 9, advanced one pass, 4540520 +silesia, level 11 row 1, advanced one pass, 4500472 +silesia, level 11 row 2, advanced one pass, 4498174 +silesia, level 12 row 1, advanced one pass, 4500472 +silesia, level 12 row 2, advanced one pass, 4498174 +silesia, level 13, advanced one pass, 4488969 +silesia, level 16, advanced one pass, 4356799 +silesia, level 19, advanced one pass, 4265851 silesia, no source size, advanced one pass, 4838417 silesia, long distance mode, advanced one pass, 4830097 silesia, multithreaded, advanced one pass, 4838949 silesia, multithreaded long distance mode, advanced one pass, 4830419 silesia, small window log, advanced one pass, 7094480 -silesia, small hash log, advanced one pass, 6524931 -silesia, small chain log, advanced one pass, 4912322 +silesia, small hash log, advanced one pass, 6525510 +silesia, small chain log, advanced one pass, 4912248 silesia, explicit params, advanced one pass, 4794219 silesia, uncompressed literals, advanced one pass, 5117482 -silesia, uncompressed literals optimal, advanced one pass, 4317186 +silesia, uncompressed literals optimal, advanced one pass, 4316644 silesia, huffman literals, advanced one pass, 5321686 silesia, multithreaded with advanced params, advanced one pass, 5117795 silesia.tar, level -5, advanced one pass, 6860782 @@ -560,24 +560,24 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass small out, 4567954 silesia, level 7 row 2, advanced one pass small out, 4562774 silesia, level 7, advanced one pass small out, 4567954 -silesia, level 9, advanced one pass small out, 4535624 -silesia, level 11 row 1, advanced one pass small out, 4495623 -silesia, level 11 row 2, advanced one pass small out, 4493258 -silesia, level 12 row 1, advanced one pass small out, 4495623 -silesia, level 12 row 2, advanced one pass small out, 4493258 -silesia, level 13, advanced one pass small out, 4484013 -silesia, level 16, advanced one pass small out, 4356207 -silesia, level 19, advanced one pass small out, 4266751 +silesia, level 9, advanced one pass small out, 4540520 +silesia, level 11 row 1, advanced one pass small out, 4500472 +silesia, level 11 row 2, advanced one pass small out, 4498174 +silesia, level 12 row 1, advanced one pass small out, 4500472 +silesia, level 12 row 2, advanced one pass small out, 4498174 +silesia, level 13, advanced one pass small out, 4488969 +silesia, level 16, advanced one pass small out, 4356799 +silesia, level 19, advanced one pass small out, 4265851 silesia, no source size, advanced one pass small out, 4838417 silesia, long distance mode, advanced one pass small out, 4830097 silesia, multithreaded, advanced one pass small out, 4838949 silesia, multithreaded long distance mode, advanced one pass small out, 4830419 silesia, small window log, advanced one pass small out, 7094480 -silesia, small hash log, advanced one pass small out, 6524931 -silesia, small chain log, advanced one pass small out, 4912322 +silesia, small hash log, advanced one pass small out, 6525510 +silesia, small chain log, advanced one pass small out, 4912248 silesia, explicit params, advanced one pass small out, 4794219 silesia, uncompressed literals, advanced one pass small out, 5117482 -silesia, uncompressed literals optimal, advanced one pass small out, 4317186 +silesia, uncompressed literals optimal, advanced one pass small out, 4316644 silesia, huffman literals, advanced one pass small out, 5321686 silesia, multithreaded with advanced params, advanced one pass small out, 5117795 silesia.tar, level -5, advanced one pass small out, 6860782 From 566763fdc9b54220e8e419446331dc15fb1c183b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 11:57:23 -0700 Subject: [PATCH 145/405] new variant, sampling by 11 --- lib/compress/zstd_compress.c | 4 +++- lib/compress/zstd_preSplit.c | 8 ++++++-- lib/compress/zstd_preSplit.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 437bd1fbe..f917ca12c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4507,8 +4507,10 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) - return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl3, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_lazy2) + return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); + if (strat >= ZSTD_greedy) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * heuristic value, tested as being "generally better". diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index c658f6fe5..504664d67 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -68,6 +68,7 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, s ZSTD_GEN_ADDEVENTS_SAMPLE(1) ZSTD_GEN_ADDEVENTS_SAMPLE(5) +ZSTD_GEN_ADDEVENTS_SAMPLE(11) typedef void (*addEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); @@ -173,9 +174,12 @@ size_t ZSTD_splitBlock(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, void* workspace, size_t wkspSize) { - if (splitStrat == split_lvl2) + if (splitStrat == split_lvl3) return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(1), workspace, wkspSize); + if (splitStrat == split_lvl2) + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(5), workspace, wkspSize); + assert(splitStrat == split_lvl1); - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(5), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(11), workspace, wkspSize); } diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 2c87d34a6..19ad337b0 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef enum { split_lvl1, split_lvl2 } ZSTD_SplitBlock_strategy_e; +typedef enum { split_lvl1, split_lvl2, split_lvl3 } ZSTD_SplitBlock_strategy_e; #define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 From 94d7b0742500ecb02546c562c68f6e095068ce35 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 16:43:44 -0700 Subject: [PATCH 146/405] organize specialization at recordFingerprint level --- lib/compress/zstd_preSplit.c | 50 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 504664d67..e8d6c5ff2 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -46,7 +46,8 @@ static void initStats(FPStats* fpstats) ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) +FORCE_INLINE_TEMPLATE void +addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) { const char* p = (const char*)src; size_t limit = srcSize - HASHLENGTH + 1; @@ -58,27 +59,28 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, s fp->nbEvents += limit/samplingRate; } -#define ADDEVENTS_RATE(_rate) ZSTD_addEvents_##_rate - -#define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ - static void ADDEVENTS_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ - { \ - addEvents_generic(fp, src, srcSize, _rate); \ - } - -ZSTD_GEN_ADDEVENTS_SAMPLE(1) -ZSTD_GEN_ADDEVENTS_SAMPLE(5) -ZSTD_GEN_ADDEVENTS_SAMPLE(11) - - -typedef void (*addEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); - -static void recordFingerprint(Fingerprint* fp, const void* src, size_t s, addEvents_f addEvents) +FORCE_INLINE_TEMPLATE void +recordFingerprint_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) { ZSTD_memset(fp, 0, sizeof(*fp)); - addEvents(fp, src, s); + addEvents_generic(fp, src, srcSize, samplingRate); } +typedef void (*RecordEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); + +#define FP_RECORD_RATE(_rate) ZSTD_recordFingerprint_##_rate + +#define ZSTD_GEN_RECORD_FINGERPRINT_RATE(_rate) \ + static void FP_RECORD_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ + { \ + recordFingerprint_generic(fp, src, srcSize, _rate); \ + } + +ZSTD_GEN_RECORD_FINGERPRINT_RATE(1) +ZSTD_GEN_RECORD_FINGERPRINT_RATE(5) +ZSTD_GEN_RECORD_FINGERPRINT_RATE(11) + + static U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); } static U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) @@ -140,7 +142,7 @@ static void removeEvents(Fingerprint* acc, const Fingerprint* slice) #define CHUNKSIZE (8 << 10) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, - size_t blockSizeMax, addEvents_f f, + size_t blockSizeMax, RecordEvents_f record_f, void* workspace, size_t wkspSize) { FPStats* const fpstats = (FPStats*)workspace; @@ -155,9 +157,9 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); - recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE, f); + record_f(&fpstats->pastEvents, p, CHUNKSIZE); for (pos = CHUNKSIZE; pos <= blockSizeMax - CHUNKSIZE; pos += CHUNKSIZE) { - recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE, f); + record_f(&fpstats->newEvents, p + pos, CHUNKSIZE); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; } else { @@ -175,11 +177,11 @@ size_t ZSTD_splitBlock(const void* src, size_t srcSize, void* workspace, size_t wkspSize) { if (splitStrat == split_lvl3) - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(1), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, FP_RECORD_RATE(1), workspace, wkspSize); if (splitStrat == split_lvl2) - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(5), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, FP_RECORD_RATE(5), workspace, wkspSize); assert(splitStrat == split_lvl1); - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(11), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, FP_RECORD_RATE(11), workspace, wkspSize); } From ca6e55cbf5bf3739520dd6ee07ae2785629f1b1e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 19:59:03 -0700 Subject: [PATCH 147/405] reduce splitBlock arguments --- lib/compress/zstd_compress.c | 6 +++--- lib/compress/zstd_preSplit.c | 25 ++++++++++++------------- lib/compress/zstd_preSplit.h | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index f917ca12c..e78de2ba8 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4507,11 +4507,11 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) - return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl3, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, blockSizeMax, split_lvl3, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_lazy2) - return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_greedy) - return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * heuristic value, tested as being "generally better". * no cpu cost, but can over-split homegeneous data. diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index e8d6c5ff2..c4c693955 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -141,16 +141,15 @@ static void removeEvents(Fingerprint* acc, const Fingerprint* slice) #define CHUNKSIZE (8 << 10) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ -static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, - size_t blockSizeMax, RecordEvents_f record_f, +static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, + RecordEvents_f record_f, void* workspace, size_t wkspSize) { FPStats* const fpstats = (FPStats*)workspace; - const char* p = (const char*)src; + const char* p = (const char*)blockStart; int penalty = THRESHOLD_PENALTY; size_t pos = 0; - if (srcSize <= blockSizeMax) return srcSize; - assert(blockSizeMax == (128 << 10)); + assert(blockSize == (128 << 10)); assert(workspace != NULL); assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0); ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats)); @@ -158,7 +157,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, initStats(fpstats); record_f(&fpstats->pastEvents, p, CHUNKSIZE); - for (pos = CHUNKSIZE; pos <= blockSizeMax - CHUNKSIZE; pos += CHUNKSIZE) { + for (pos = CHUNKSIZE; pos <= blockSize - CHUNKSIZE; pos += CHUNKSIZE) { record_f(&fpstats->newEvents, p + pos, CHUNKSIZE); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; @@ -167,21 +166,21 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, if (penalty > 0) penalty--; } } - assert(pos == blockSizeMax); - return blockSizeMax; + assert(pos == blockSize); + return blockSize; (void)flushEvents; (void)removeEvents; } -size_t ZSTD_splitBlock(const void* src, size_t srcSize, - size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, +size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, + ZSTD_SplitBlock_strategy_e splitStrat, void* workspace, size_t wkspSize) { if (splitStrat == split_lvl3) - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, FP_RECORD_RATE(1), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(blockStart, blockSize, FP_RECORD_RATE(1), workspace, wkspSize); if (splitStrat == split_lvl2) - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, FP_RECORD_RATE(5), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(blockStart, blockSize, FP_RECORD_RATE(5), workspace, wkspSize); assert(splitStrat == split_lvl1); - return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, FP_RECORD_RATE(11), workspace, wkspSize); + return ZSTD_splitBlock_byChunks(blockStart, blockSize, FP_RECORD_RATE(11), workspace, wkspSize); } diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 19ad337b0..cf829ecee 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -29,8 +29,8 @@ typedef enum { split_lvl1, split_lvl2, split_lvl3 } ZSTD_SplitBlock_strategy_e; * therefore @blockSizeMax must be == 128 KB. * This could be extended to smaller sizes in the future. */ -size_t ZSTD_splitBlock(const void* src, size_t srcSize, - size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, +size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, + ZSTD_SplitBlock_strategy_e splitStrat, void* workspace, size_t wkspSize); #if defined (__cplusplus) From 326c45bb8ed8f9f9e7dce1721db5d5e1ec1cb818 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 20:20:32 -0700 Subject: [PATCH 148/405] complete sample11 with reduced fingerprint size --- lib/compress/zstd_preSplit.c | 64 +++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index c4c693955..63ff0ded8 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -21,14 +21,15 @@ #define THRESHOLD_PENALTY 3 #define HASHLENGTH 2 -#define HASHLOG 10 -#define HASHTABLESIZE (1 << HASHLOG) +#define HASHLOG_MAX 10 +#define HASHTABLESIZE (1 << HASHLOG_MAX) #define HASHMASK (HASHTABLESIZE - 1) #define KNUTH 0x9e3779b9 -static unsigned hash2(const void *p) +FORCE_INLINE_TEMPLATE unsigned hash2(const void *p, unsigned hashLog) { - return (U32)(MEM_read16(p)) * KNUTH >> (32 - HASHLOG); + assert(hashLog <= HASHLOG_MAX); + return (U32)(MEM_read16(p)) * KNUTH >> (32 - hashLog); } @@ -47,47 +48,49 @@ static void initStats(FPStats* fpstats) } FORCE_INLINE_TEMPLATE void -addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) +addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog) { const char* p = (const char*)src; size_t limit = srcSize - HASHLENGTH + 1; size_t n; assert(srcSize >= HASHLENGTH); for (n = 0; n < limit; n+=samplingRate) { - fp->events[hash2(p+n)]++; + fp->events[hash2(p+n, hashLog)]++; } fp->nbEvents += limit/samplingRate; } FORCE_INLINE_TEMPLATE void -recordFingerprint_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) +recordFingerprint_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog) { - ZSTD_memset(fp, 0, sizeof(*fp)); - addEvents_generic(fp, src, srcSize, samplingRate); + ZSTD_memset(fp, 0, sizeof(unsigned) * (1 << hashLog)); + fp->nbEvents = 0; + addEvents_generic(fp, src, srcSize, samplingRate, hashLog); } typedef void (*RecordEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); -#define FP_RECORD_RATE(_rate) ZSTD_recordFingerprint_##_rate +#define FP_RECORD(_rate) ZSTD_recordFingerprint_##_rate -#define ZSTD_GEN_RECORD_FINGERPRINT_RATE(_rate) \ - static void FP_RECORD_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ +#define ZSTD_GEN_RECORD_FINGERPRINT(_rate, _hSize) \ + static void FP_RECORD(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ { \ - recordFingerprint_generic(fp, src, srcSize, _rate); \ + recordFingerprint_generic(fp, src, srcSize, _rate, _hSize); \ } -ZSTD_GEN_RECORD_FINGERPRINT_RATE(1) -ZSTD_GEN_RECORD_FINGERPRINT_RATE(5) -ZSTD_GEN_RECORD_FINGERPRINT_RATE(11) +ZSTD_GEN_RECORD_FINGERPRINT(1, 10) +ZSTD_GEN_RECORD_FINGERPRINT(5, 10) +ZSTD_GEN_RECORD_FINGERPRINT(11, 9) static U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); } -static U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) +static U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2, unsigned hashLog) { U64 distance = 0; size_t n; - for (n = 0; n < HASHTABLESIZE; n++) { + assert(hashLog <= HASHLOG_MAX); + for (n = 0; n < ((size_t)1 << hashLog); n++) { distance += abs64((S64)fp1->events[n] * (S64)fp2->nbEvents - (S64)fp2->events[n] * (S64)fp1->nbEvents); } @@ -99,12 +102,13 @@ static U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) */ static int compareFingerprints(const Fingerprint* ref, const Fingerprint* newfp, - int penalty) + int penalty, + unsigned hashLog) { assert(ref->nbEvents > 0); assert(newfp->nbEvents > 0); { U64 p50 = (U64)ref->nbEvents * (U64)newfp->nbEvents; - U64 deviation = fpDistance(ref, newfp); + U64 deviation = fpDistance(ref, newfp, hashLog); U64 threshold = p50 * (U64)(THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } @@ -140,11 +144,15 @@ static void removeEvents(Fingerprint* acc, const Fingerprint* slice) } #define CHUNKSIZE (8 << 10) -/* Note: technically, we use CHUNKSIZE, so that's 8 KB */ static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, - RecordEvents_f record_f, + ZSTD_SplitBlock_strategy_e splitStrat, void* workspace, size_t wkspSize) { + static const RecordEvents_f records_fs[] = { + FP_RECORD(11), FP_RECORD(5), FP_RECORD(1) + }; + static const unsigned hashParams[] = { 9, 10, 10 }; + const RecordEvents_f record_f = (assert(splitStrat<=split_lvl3), records_fs[splitStrat]); FPStats* const fpstats = (FPStats*)workspace; const char* p = (const char*)blockStart; int penalty = THRESHOLD_PENALTY; @@ -159,7 +167,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, record_f(&fpstats->pastEvents, p, CHUNKSIZE); for (pos = CHUNKSIZE; pos <= blockSize - CHUNKSIZE; pos += CHUNKSIZE) { record_f(&fpstats->newEvents, p + pos, CHUNKSIZE); - if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { + if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty, hashParams[splitStrat])) { return pos; } else { mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); @@ -175,12 +183,6 @@ size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, ZSTD_SplitBlock_strategy_e splitStrat, void* workspace, size_t wkspSize) { - if (splitStrat == split_lvl3) - return ZSTD_splitBlock_byChunks(blockStart, blockSize, FP_RECORD_RATE(1), workspace, wkspSize); - - if (splitStrat == split_lvl2) - return ZSTD_splitBlock_byChunks(blockStart, blockSize, FP_RECORD_RATE(5), workspace, wkspSize); - - assert(splitStrat == split_lvl1); - return ZSTD_splitBlock_byChunks(blockStart, blockSize, FP_RECORD_RATE(11), workspace, wkspSize); + assert(splitStrat <= split_lvl3); + return ZSTD_splitBlock_byChunks(blockStart, blockSize, splitStrat, workspace, wkspSize); } From ea082692aaff79abebecd97e77b3bf79ab58f43f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 13:27:01 -0700 Subject: [PATCH 149/405] added block splitter variant for greedy & lazy (levels 5 to 7) --- tests/regression/results.csv | 492 +++++++++++++++++------------------ 1 file changed, 246 insertions(+), 246 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index ea5ed58d5..b46c4ca5c 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -6,9 +6,9 @@ silesia.tar, level 0, compress silesia.tar, level 1, compress simple, 5316794 silesia.tar, level 3, compress simple, 4843429 silesia.tar, level 4, compress simple, 4780657 -silesia.tar, level 5, compress simple, 4669650 -silesia.tar, level 6, compress simple, 4604925 -silesia.tar, level 7, compress simple, 4570873 +silesia.tar, level 5, compress simple, 4662847 +silesia.tar, level 6, compress simple, 4597877 +silesia.tar, level 7, compress simple, 4563998 silesia.tar, level 9, compress simple, 4537558 silesia.tar, level 13, compress simple, 4484732 silesia.tar, level 16, compress simple, 4355572 @@ -23,9 +23,9 @@ github.tar, level 0, compress github.tar, level 1, compress simple, 39444 github.tar, level 3, compress simple, 39073 github.tar, level 4, compress simple, 39068 -github.tar, level 5, compress simple, 39808 -github.tar, level 6, compress simple, 39455 -github.tar, level 7, compress simple, 38168 +github.tar, level 5, compress simple, 39651 +github.tar, level 6, compress simple, 39282 +github.tar, level 7, compress simple, 38005 github.tar, level 9, compress simple, 36723 github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 @@ -40,9 +40,9 @@ silesia, level 0, compress silesia, level 1, compress cctx, 5306931 silesia, level 3, compress cctx, 4838417 silesia, level 4, compress cctx, 4775359 -silesia, level 5, compress cctx, 4666524 -silesia, level 6, compress cctx, 4602031 -silesia, level 7, compress cctx, 4567954 +silesia, level 5, compress cctx, 4663718 +silesia, level 6, compress cctx, 4600034 +silesia, level 7, compress cctx, 4566069 silesia, level 9, compress cctx, 4540520 silesia, level 13, compress cctx, 4488969 silesia, level 16, compress cctx, 4356799 @@ -53,7 +53,7 @@ silesia, multithreaded long distance mode, compress silesia, small window log, compress cctx, 7082907 silesia, small hash log, compress cctx, 6525510 silesia, small chain log, compress cctx, 4912248 -silesia, explicit params, compress cctx, 4792640 +silesia, explicit params, compress cctx, 4789676 silesia, uncompressed literals, compress cctx, 4838417 silesia, uncompressed literals optimal, compress cctx, 4265851 silesia, huffman literals, compress cctx, 6174127 @@ -104,11 +104,11 @@ silesia, level 0, zstdcli, silesia, level 1, zstdcli, 5306179 silesia, level 3, zstdcli, 4838997 silesia, level 4, zstdcli, 4775769 -silesia, level 5, zstdcli, 4666931 -silesia, level 6, zstdcli, 4602509 -silesia, level 7, zstdcli, 4568265 -silesia, level 9, zstdcli, 4540123 -silesia, level 13, zstdcli, 4488478 +silesia, level 5, zstdcli, 4663332 +silesia, level 6, zstdcli, 4599601 +silesia, level 7, zstdcli, 4565601 +silesia, level 9, zstdcli, 4540082 +silesia, level 13, zstdcli, 4488438 silesia, level 16, zstdcli, 4358150 silesia, level 19, zstdcli, 4265929 silesia, long distance mode, zstdcli, 4830467 @@ -117,7 +117,7 @@ silesia, multithreaded long distance mode, zstdcli, silesia, small window log, zstdcli, 7094528 silesia, small hash log, zstdcli, 6527214 silesia, small chain log, zstdcli, 4911647 -silesia, explicit params, zstdcli, 4794378 +silesia, explicit params, zstdcli, 4790803 silesia, uncompressed literals, zstdcli, 5117843 silesia, uncompressed literals optimal, zstdcli, 4316761 silesia, huffman literals, zstdcli, 5320793 @@ -129,23 +129,23 @@ silesia.tar, level 0, zstdcli, silesia.tar, level 1, zstdcli, 5313917 silesia.tar, level 3, zstdcli, 4841906 silesia.tar, level 4, zstdcli, 4780121 -silesia.tar, level 5, zstdcli, 4671144 -silesia.tar, level 6, zstdcli, 4606407 -silesia.tar, level 7, zstdcli, 4572666 -silesia.tar, level 9, zstdcli, 4542599 -silesia.tar, level 13, zstdcli, 4489976 -silesia.tar, level 16, zstdcli, 4356959 -silesia.tar, level 19, zstdcli, 4259787 +silesia.tar, level 5, zstdcli, 4667310 +silesia.tar, level 6, zstdcli, 4602398 +silesia.tar, level 7, zstdcli, 4568891 +silesia.tar, level 9, zstdcli, 4541098 +silesia.tar, level 13, zstdcli, 4488484 +silesia.tar, level 16, zstdcli, 4357018 +silesia.tar, level 19, zstdcli, 4259593 silesia.tar, no source size, zstdcli, 4841902 silesia.tar, long distance mode, zstdcli, 4834266 silesia.tar, multithreaded, zstdcli, 4841906 silesia.tar, multithreaded long distance mode, zstdcli, 4834266 silesia.tar, small window log, zstdcli, 7100110 -silesia.tar, small hash log, zstdcli, 6530007 -silesia.tar, small chain log, zstdcli, 4916091 -silesia.tar, explicit params, zstdcli, 4809323 +silesia.tar, small hash log, zstdcli, 6530127 +silesia.tar, small chain log, zstdcli, 4915865 +silesia.tar, explicit params, zstdcli, 4808370 silesia.tar, uncompressed literals, zstdcli, 5116446 -silesia.tar, uncompressed literals optimal, zstdcli, 4306844 +silesia.tar, uncompressed literals optimal, zstdcli, 4306520 silesia.tar, huffman literals, zstdcli, 5326463 silesia.tar, multithreaded with advanced params, zstdcli, 5116446 github, level -5, zstdcli, 206407 @@ -201,11 +201,11 @@ github.tar, level 3, zstdcli, github.tar, level 3 with dict, zstdcli, 38140 github.tar, level 4, zstdcli, 39067 github.tar, level 4 with dict, zstdcli, 38082 -github.tar, level 5, zstdcli, 39815 -github.tar, level 5 with dict, zstdcli, 39221 -github.tar, level 6, zstdcli, 39455 -github.tar, level 6 with dict, zstdcli, 38787 -github.tar, level 7, zstdcli, 38177 +github.tar, level 5, zstdcli, 39655 +github.tar, level 5 with dict, zstdcli, 39073 +github.tar, level 6, zstdcli, 39286 +github.tar, level 6 with dict, zstdcli, 38647 +github.tar, level 7, zstdcli, 38009 github.tar, level 7 with dict, zstdcli, 37861 github.tar, level 9, zstdcli, 36727 github.tar, level 9 with dict, zstdcli, 36686 @@ -223,7 +223,7 @@ github.tar, multithreaded long distance mode, zstdcli, github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 -github.tar, explicit params, zstdcli, 41588 +github.tar, explicit params, zstdcli, 41385 github.tar, uncompressed literals, zstdcli, 41704 github.tar, uncompressed literals optimal, zstdcli, 35360 github.tar, huffman literals, zstdcli, 39046 @@ -235,13 +235,13 @@ silesia, level 0, advanced silesia, level 1, advanced one pass, 5306931 silesia, level 3, advanced one pass, 4838417 silesia, level 4, advanced one pass, 4775359 -silesia, level 5 row 1, advanced one pass, 4666524 -silesia, level 5 row 2, advanced one pass, 4668976 -silesia, level 5, advanced one pass, 4666524 -silesia, level 6, advanced one pass, 4602031 -silesia, level 7 row 1, advanced one pass, 4567954 -silesia, level 7 row 2, advanced one pass, 4562774 -silesia, level 7, advanced one pass, 4567954 +silesia, level 5 row 1, advanced one pass, 4663718 +silesia, level 5 row 2, advanced one pass, 4666272 +silesia, level 5, advanced one pass, 4663718 +silesia, level 6, advanced one pass, 4600034 +silesia, level 7 row 1, advanced one pass, 4566069 +silesia, level 7 row 2, advanced one pass, 4560893 +silesia, level 7, advanced one pass, 4566069 silesia, level 9, advanced one pass, 4540520 silesia, level 11 row 1, advanced one pass, 4500472 silesia, level 11 row 2, advanced one pass, 4498174 @@ -257,7 +257,7 @@ silesia, multithreaded long distance mode, advanced silesia, small window log, advanced one pass, 7094480 silesia, small hash log, advanced one pass, 6525510 silesia, small chain log, advanced one pass, 4912248 -silesia, explicit params, advanced one pass, 4794219 +silesia, explicit params, advanced one pass, 4791219 silesia, uncompressed literals, advanced one pass, 5117482 silesia, uncompressed literals optimal, advanced one pass, 4316644 silesia, huffman literals, advanced one pass, 5321686 @@ -269,13 +269,13 @@ silesia.tar, level 0, advanced silesia.tar, level 1, advanced one pass, 5316794 silesia.tar, level 3, advanced one pass, 4843429 silesia.tar, level 4, advanced one pass, 4780657 -silesia.tar, level 5 row 1, advanced one pass, 4669650 -silesia.tar, level 5 row 2, advanced one pass, 4673119 -silesia.tar, level 5, advanced one pass, 4669650 -silesia.tar, level 6, advanced one pass, 4604925 -silesia.tar, level 7 row 1, advanced one pass, 4570873 -silesia.tar, level 7 row 2, advanced one pass, 4566314 -silesia.tar, level 7, advanced one pass, 4570873 +silesia.tar, level 5 row 1, advanced one pass, 4662847 +silesia.tar, level 5 row 2, advanced one pass, 4666825 +silesia.tar, level 5, advanced one pass, 4662847 +silesia.tar, level 6, advanced one pass, 4597877 +silesia.tar, level 7 row 1, advanced one pass, 4563998 +silesia.tar, level 7 row 2, advanced one pass, 4559520 +silesia.tar, level 7, advanced one pass, 4563998 silesia.tar, level 9, advanced one pass, 4537558 silesia.tar, level 11 row 1, advanced one pass, 4496590 silesia.tar, level 11 row 2, advanced one pass, 4495225 @@ -291,7 +291,7 @@ silesia.tar, multithreaded long distance mode, advanced silesia.tar, small window log, advanced one pass, 7100064 silesia.tar, small hash log, advanced one pass, 6530222 silesia.tar, small chain log, advanced one pass, 4915689 -silesia.tar, explicit params, advanced one pass, 4797958 +silesia.tar, explicit params, advanced one pass, 4790421 silesia.tar, uncompressed literals, advanced one pass, 5116329 silesia.tar, uncompressed literals optimal, advanced one pass, 4306289 silesia.tar, huffman literals, advanced one pass, 5331382 @@ -451,44 +451,44 @@ github.tar, level 4 with dict dms, advanced github.tar, level 4 with dict dds, advanced one pass, 38135 github.tar, level 4 with dict copy, advanced one pass, 38081 github.tar, level 4 with dict load, advanced one pass, 38088 -github.tar, level 5 row 1, advanced one pass, 39808 -github.tar, level 5 row 1 with dict dms, advanced one pass, 39185 -github.tar, level 5 row 1 with dict dds, advanced one pass, 39213 -github.tar, level 5 row 1 with dict copy, advanced one pass, 39284 -github.tar, level 5 row 1 with dict load, advanced one pass, 39155 -github.tar, level 5 row 2, advanced one pass, 39851 -github.tar, level 5 row 2 with dict dms, advanced one pass, 39498 -github.tar, level 5 row 2 with dict dds, advanced one pass, 39364 -github.tar, level 5 row 2 with dict copy, advanced one pass, 39843 -github.tar, level 5 row 2 with dict load, advanced one pass, 39312 -github.tar, level 5, advanced one pass, 39808 -github.tar, level 5 with dict, advanced one pass, 39284 -github.tar, level 5 with dict dms, advanced one pass, 39185 -github.tar, level 5 with dict dds, advanced one pass, 39213 -github.tar, level 5 with dict copy, advanced one pass, 39284 -github.tar, level 5 with dict load, advanced one pass, 39155 -github.tar, level 6, advanced one pass, 39455 -github.tar, level 6 with dict, advanced one pass, 38808 -github.tar, level 6 with dict dms, advanced one pass, 38792 -github.tar, level 6 with dict dds, advanced one pass, 38790 -github.tar, level 6 with dict copy, advanced one pass, 38808 -github.tar, level 6 with dict load, advanced one pass, 38796 -github.tar, level 7 row 1, advanced one pass, 38168 +github.tar, level 5 row 1, advanced one pass, 39651 +github.tar, level 5 row 1 with dict dms, advanced one pass, 39043 +github.tar, level 5 row 1 with dict dds, advanced one pass, 39069 +github.tar, level 5 row 1 with dict copy, advanced one pass, 39145 +github.tar, level 5 row 1 with dict load, advanced one pass, 39000 +github.tar, level 5 row 2, advanced one pass, 39701 +github.tar, level 5 row 2 with dict dms, advanced one pass, 39365 +github.tar, level 5 row 2 with dict dds, advanced one pass, 39233 +github.tar, level 5 row 2 with dict copy, advanced one pass, 39715 +github.tar, level 5 row 2 with dict load, advanced one pass, 39158 +github.tar, level 5, advanced one pass, 39651 +github.tar, level 5 with dict, advanced one pass, 39145 +github.tar, level 5 with dict dms, advanced one pass, 39043 +github.tar, level 5 with dict dds, advanced one pass, 39069 +github.tar, level 5 with dict copy, advanced one pass, 39145 +github.tar, level 5 with dict load, advanced one pass, 39000 +github.tar, level 6, advanced one pass, 39282 +github.tar, level 6 with dict, advanced one pass, 38656 +github.tar, level 6 with dict dms, advanced one pass, 38640 +github.tar, level 6 with dict dds, advanced one pass, 38643 +github.tar, level 6 with dict copy, advanced one pass, 38656 +github.tar, level 6 with dict load, advanced one pass, 38647 +github.tar, level 7 row 1, advanced one pass, 38005 github.tar, level 7 row 1 with dict dms, advanced one pass, 37832 github.tar, level 7 row 1 with dict dds, advanced one pass, 37857 github.tar, level 7 row 1 with dict copy, advanced one pass, 37839 -github.tar, level 7 row 1 with dict load, advanced one pass, 37445 -github.tar, level 7 row 2, advanced one pass, 38235 +github.tar, level 7 row 1 with dict load, advanced one pass, 37286 +github.tar, level 7 row 2, advanced one pass, 38077 github.tar, level 7 row 2 with dict dms, advanced one pass, 38012 github.tar, level 7 row 2 with dict dds, advanced one pass, 38014 github.tar, level 7 row 2 with dict copy, advanced one pass, 38101 -github.tar, level 7 row 2 with dict load, advanced one pass, 37552 -github.tar, level 7, advanced one pass, 38168 +github.tar, level 7 row 2 with dict load, advanced one pass, 37402 +github.tar, level 7, advanced one pass, 38005 github.tar, level 7 with dict, advanced one pass, 37839 github.tar, level 7 with dict dms, advanced one pass, 37832 github.tar, level 7 with dict dds, advanced one pass, 37857 github.tar, level 7 with dict copy, advanced one pass, 37839 -github.tar, level 7 with dict load, advanced one pass, 37445 +github.tar, level 7 with dict load, advanced one pass, 37286 github.tar, level 9, advanced one pass, 36723 github.tar, level 9 with dict, advanced one pass, 36531 github.tar, level 9 with dict dms, advanced one pass, 36615 @@ -541,7 +541,7 @@ github.tar, multithreaded long distance mode, advanced github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 -github.tar, explicit params, advanced one pass, 41605 +github.tar, explicit params, advanced one pass, 41385 github.tar, uncompressed literals, advanced one pass, 41709 github.tar, uncompressed literals optimal, advanced one pass, 35356 github.tar, huffman literals, advanced one pass, 39099 @@ -553,13 +553,13 @@ silesia, level 0, advanced silesia, level 1, advanced one pass small out, 5306931 silesia, level 3, advanced one pass small out, 4838417 silesia, level 4, advanced one pass small out, 4775359 -silesia, level 5 row 1, advanced one pass small out, 4666524 -silesia, level 5 row 2, advanced one pass small out, 4668976 -silesia, level 5, advanced one pass small out, 4666524 -silesia, level 6, advanced one pass small out, 4602031 -silesia, level 7 row 1, advanced one pass small out, 4567954 -silesia, level 7 row 2, advanced one pass small out, 4562774 -silesia, level 7, advanced one pass small out, 4567954 +silesia, level 5 row 1, advanced one pass small out, 4663718 +silesia, level 5 row 2, advanced one pass small out, 4666272 +silesia, level 5, advanced one pass small out, 4663718 +silesia, level 6, advanced one pass small out, 4600034 +silesia, level 7 row 1, advanced one pass small out, 4566069 +silesia, level 7 row 2, advanced one pass small out, 4560893 +silesia, level 7, advanced one pass small out, 4566069 silesia, level 9, advanced one pass small out, 4540520 silesia, level 11 row 1, advanced one pass small out, 4500472 silesia, level 11 row 2, advanced one pass small out, 4498174 @@ -575,7 +575,7 @@ silesia, multithreaded long distance mode, advanced silesia, small window log, advanced one pass small out, 7094480 silesia, small hash log, advanced one pass small out, 6525510 silesia, small chain log, advanced one pass small out, 4912248 -silesia, explicit params, advanced one pass small out, 4794219 +silesia, explicit params, advanced one pass small out, 4791219 silesia, uncompressed literals, advanced one pass small out, 5117482 silesia, uncompressed literals optimal, advanced one pass small out, 4316644 silesia, huffman literals, advanced one pass small out, 5321686 @@ -587,13 +587,13 @@ silesia.tar, level 0, advanced silesia.tar, level 1, advanced one pass small out, 5316794 silesia.tar, level 3, advanced one pass small out, 4843429 silesia.tar, level 4, advanced one pass small out, 4780657 -silesia.tar, level 5 row 1, advanced one pass small out, 4669650 -silesia.tar, level 5 row 2, advanced one pass small out, 4673119 -silesia.tar, level 5, advanced one pass small out, 4669650 -silesia.tar, level 6, advanced one pass small out, 4604925 -silesia.tar, level 7 row 1, advanced one pass small out, 4570873 -silesia.tar, level 7 row 2, advanced one pass small out, 4566314 -silesia.tar, level 7, advanced one pass small out, 4570873 +silesia.tar, level 5 row 1, advanced one pass small out, 4662847 +silesia.tar, level 5 row 2, advanced one pass small out, 4666825 +silesia.tar, level 5, advanced one pass small out, 4662847 +silesia.tar, level 6, advanced one pass small out, 4597877 +silesia.tar, level 7 row 1, advanced one pass small out, 4563998 +silesia.tar, level 7 row 2, advanced one pass small out, 4559520 +silesia.tar, level 7, advanced one pass small out, 4563998 silesia.tar, level 9, advanced one pass small out, 4537558 silesia.tar, level 11 row 1, advanced one pass small out, 4496590 silesia.tar, level 11 row 2, advanced one pass small out, 4495225 @@ -609,7 +609,7 @@ silesia.tar, multithreaded long distance mode, advanced silesia.tar, small window log, advanced one pass small out, 7100064 silesia.tar, small hash log, advanced one pass small out, 6530222 silesia.tar, small chain log, advanced one pass small out, 4915689 -silesia.tar, explicit params, advanced one pass small out, 4797958 +silesia.tar, explicit params, advanced one pass small out, 4790421 silesia.tar, uncompressed literals, advanced one pass small out, 5116329 silesia.tar, uncompressed literals optimal, advanced one pass small out, 4306289 silesia.tar, huffman literals, advanced one pass small out, 5331382 @@ -769,44 +769,44 @@ github.tar, level 4 with dict dms, advanced github.tar, level 4 with dict dds, advanced one pass small out, 38135 github.tar, level 4 with dict copy, advanced one pass small out, 38081 github.tar, level 4 with dict load, advanced one pass small out, 38088 -github.tar, level 5 row 1, advanced one pass small out, 39808 -github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39185 -github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39213 -github.tar, level 5 row 1 with dict copy, advanced one pass small out, 39284 -github.tar, level 5 row 1 with dict load, advanced one pass small out, 39155 -github.tar, level 5 row 2, advanced one pass small out, 39851 -github.tar, level 5 row 2 with dict dms, advanced one pass small out, 39498 -github.tar, level 5 row 2 with dict dds, advanced one pass small out, 39364 -github.tar, level 5 row 2 with dict copy, advanced one pass small out, 39843 -github.tar, level 5 row 2 with dict load, advanced one pass small out, 39312 -github.tar, level 5, advanced one pass small out, 39808 -github.tar, level 5 with dict, advanced one pass small out, 39284 -github.tar, level 5 with dict dms, advanced one pass small out, 39185 -github.tar, level 5 with dict dds, advanced one pass small out, 39213 -github.tar, level 5 with dict copy, advanced one pass small out, 39284 -github.tar, level 5 with dict load, advanced one pass small out, 39155 -github.tar, level 6, advanced one pass small out, 39455 -github.tar, level 6 with dict, advanced one pass small out, 38808 -github.tar, level 6 with dict dms, advanced one pass small out, 38792 -github.tar, level 6 with dict dds, advanced one pass small out, 38790 -github.tar, level 6 with dict copy, advanced one pass small out, 38808 -github.tar, level 6 with dict load, advanced one pass small out, 38796 -github.tar, level 7 row 1, advanced one pass small out, 38168 +github.tar, level 5 row 1, advanced one pass small out, 39651 +github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39043 +github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39069 +github.tar, level 5 row 1 with dict copy, advanced one pass small out, 39145 +github.tar, level 5 row 1 with dict load, advanced one pass small out, 39000 +github.tar, level 5 row 2, advanced one pass small out, 39701 +github.tar, level 5 row 2 with dict dms, advanced one pass small out, 39365 +github.tar, level 5 row 2 with dict dds, advanced one pass small out, 39233 +github.tar, level 5 row 2 with dict copy, advanced one pass small out, 39715 +github.tar, level 5 row 2 with dict load, advanced one pass small out, 39158 +github.tar, level 5, advanced one pass small out, 39651 +github.tar, level 5 with dict, advanced one pass small out, 39145 +github.tar, level 5 with dict dms, advanced one pass small out, 39043 +github.tar, level 5 with dict dds, advanced one pass small out, 39069 +github.tar, level 5 with dict copy, advanced one pass small out, 39145 +github.tar, level 5 with dict load, advanced one pass small out, 39000 +github.tar, level 6, advanced one pass small out, 39282 +github.tar, level 6 with dict, advanced one pass small out, 38656 +github.tar, level 6 with dict dms, advanced one pass small out, 38640 +github.tar, level 6 with dict dds, advanced one pass small out, 38643 +github.tar, level 6 with dict copy, advanced one pass small out, 38656 +github.tar, level 6 with dict load, advanced one pass small out, 38647 +github.tar, level 7 row 1, advanced one pass small out, 38005 github.tar, level 7 row 1 with dict dms, advanced one pass small out, 37832 github.tar, level 7 row 1 with dict dds, advanced one pass small out, 37857 github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37839 -github.tar, level 7 row 1 with dict load, advanced one pass small out, 37445 -github.tar, level 7 row 2, advanced one pass small out, 38235 +github.tar, level 7 row 1 with dict load, advanced one pass small out, 37286 +github.tar, level 7 row 2, advanced one pass small out, 38077 github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38012 github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38014 github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38101 -github.tar, level 7 row 2 with dict load, advanced one pass small out, 37552 -github.tar, level 7, advanced one pass small out, 38168 +github.tar, level 7 row 2 with dict load, advanced one pass small out, 37402 +github.tar, level 7, advanced one pass small out, 38005 github.tar, level 7 with dict, advanced one pass small out, 37839 github.tar, level 7 with dict dms, advanced one pass small out, 37832 github.tar, level 7 with dict dds, advanced one pass small out, 37857 github.tar, level 7 with dict copy, advanced one pass small out, 37839 -github.tar, level 7 with dict load, advanced one pass small out, 37445 +github.tar, level 7 with dict load, advanced one pass small out, 37286 github.tar, level 9, advanced one pass small out, 36723 github.tar, level 9 with dict, advanced one pass small out, 36531 github.tar, level 9 with dict dms, advanced one pass small out, 36615 @@ -859,7 +859,7 @@ github.tar, multithreaded long distance mode, advanced github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 -github.tar, explicit params, advanced one pass small out, 41605 +github.tar, explicit params, advanced one pass small out, 41385 github.tar, uncompressed literals, advanced one pass small out, 41709 github.tar, uncompressed literals optimal, advanced one pass small out, 35356 github.tar, huffman literals, advanced one pass small out, 39099 @@ -871,31 +871,31 @@ silesia, level 0, advanced silesia, level 1, advanced streaming, 5305682 silesia, level 3, advanced streaming, 4839173 silesia, level 4, advanced streaming, 4776074 -silesia, level 5 row 1, advanced streaming, 4667049 -silesia, level 5 row 2, advanced streaming, 4669474 -silesia, level 5, advanced streaming, 4667049 -silesia, level 6, advanced streaming, 4602956 -silesia, level 7 row 1, advanced streaming, 4568785 -silesia, level 7 row 2, advanced streaming, 4563722 -silesia, level 7, advanced streaming, 4568785 -silesia, level 9, advanced streaming, 4545850 -silesia, level 11 row 1, advanced streaming, 4505658 -silesia, level 11 row 2, advanced streaming, 4503429 -silesia, level 12 row 1, advanced streaming, 4505658 -silesia, level 12 row 2, advanced streaming, 4503429 -silesia, level 13, advanced streaming, 4493990 -silesia, level 16, advanced streaming, 4359652 -silesia, level 19, advanced streaming, 4266582 +silesia, level 5 row 1, advanced streaming, 4664679 +silesia, level 5 row 2, advanced streaming, 4667307 +silesia, level 5, advanced streaming, 4664679 +silesia, level 6, advanced streaming, 4601116 +silesia, level 7 row 1, advanced streaming, 4567082 +silesia, level 7 row 2, advanced streaming, 4561992 +silesia, level 7, advanced streaming, 4567082 +silesia, level 9, advanced streaming, 4542474 +silesia, level 11 row 1, advanced streaming, 4502322 +silesia, level 11 row 2, advanced streaming, 4500050 +silesia, level 12 row 1, advanced streaming, 4502322 +silesia, level 12 row 2, advanced streaming, 4500050 +silesia, level 13, advanced streaming, 4490650 +silesia, level 16, advanced streaming, 4358094 +silesia, level 19, advanced streaming, 4265908 silesia, no source size, advanced streaming, 4839137 silesia, long distance mode, advanced streaming, 4831125 silesia, multithreaded, advanced streaming, 4838949 silesia, multithreaded long distance mode, advanced streaming, 4830419 silesia, small window log, advanced streaming, 7110591 -silesia, small hash log, advanced streaming, 6526141 -silesia, small chain log, advanced streaming, 4912197 -silesia, explicit params, advanced streaming, 4795053 +silesia, small hash log, advanced streaming, 6525259 +silesia, small chain log, advanced streaming, 4911577 +silesia, explicit params, advanced streaming, 4792505 silesia, uncompressed literals, advanced streaming, 5117625 -silesia, uncompressed literals optimal, advanced streaming, 4316880 +silesia, uncompressed literals optimal, advanced streaming, 4316533 silesia, huffman literals, advanced streaming, 5321812 silesia, multithreaded with advanced params, advanced streaming, 5117795 silesia.tar, level -5, advanced streaming, 6857458 @@ -905,31 +905,31 @@ silesia.tar, level 0, advanced silesia.tar, level 1, advanced streaming, 5311452 silesia.tar, level 3, advanced streaming, 4849720 silesia.tar, level 4, advanced streaming, 4787534 -silesia.tar, level 5 row 1, advanced streaming, 4669420 -silesia.tar, level 5 row 2, advanced streaming, 4673610 -silesia.tar, level 5, advanced streaming, 4669420 -silesia.tar, level 6, advanced streaming, 4604125 -silesia.tar, level 7 row 1, advanced streaming, 4570206 -silesia.tar, level 7 row 2, advanced streaming, 4565792 -silesia.tar, level 7, advanced streaming, 4570206 -silesia.tar, level 9, advanced streaming, 4555445 -silesia.tar, level 11 row 1, advanced streaming, 4514959 -silesia.tar, level 11 row 2, advanced streaming, 4513810 -silesia.tar, level 12 row 1, advanced streaming, 4514514 -silesia.tar, level 12 row 2, advanced streaming, 4514003 -silesia.tar, level 13, advanced streaming, 4502956 -silesia.tar, level 16, advanced streaming, 4360385 -silesia.tar, level 19, advanced streaming, 4260939 +silesia.tar, level 5 row 1, advanced streaming, 4664523 +silesia.tar, level 5 row 2, advanced streaming, 4668292 +silesia.tar, level 5, advanced streaming, 4664523 +silesia.tar, level 6, advanced streaming, 4599420 +silesia.tar, level 7 row 1, advanced streaming, 4565332 +silesia.tar, level 7 row 2, advanced streaming, 4561064 +silesia.tar, level 7, advanced streaming, 4565332 +silesia.tar, level 9, advanced streaming, 4539391 +silesia.tar, level 11 row 1, advanced streaming, 4498530 +silesia.tar, level 11 row 2, advanced streaming, 4497297 +silesia.tar, level 12 row 1, advanced streaming, 4498097 +silesia.tar, level 12 row 2, advanced streaming, 4497497 +silesia.tar, level 13, advanced streaming, 4486652 +silesia.tar, level 16, advanced streaming, 4358029 +silesia.tar, level 19, advanced streaming, 4258228 silesia.tar, no source size, advanced streaming, 4849716 silesia.tar, long distance mode, advanced streaming, 4829339 silesia.tar, multithreaded, advanced streaming, 4841902 silesia.tar, multithreaded long distance mode, advanced streaming, 4834262 silesia.tar, small window log, advanced streaming, 7117024 -silesia.tar, small hash log, advanced streaming, 6529209 -silesia.tar, small chain log, advanced streaming, 4917021 -silesia.tar, explicit params, advanced streaming, 4797673 +silesia.tar, small hash log, advanced streaming, 6529503 +silesia.tar, small chain log, advanced streaming, 4915956 +silesia.tar, explicit params, advanced streaming, 4791739 silesia.tar, uncompressed literals, advanced streaming, 5124811 -silesia.tar, uncompressed literals optimal, advanced streaming, 4308451 +silesia.tar, uncompressed literals optimal, advanced streaming, 4306968 silesia.tar, huffman literals, advanced streaming, 5326278 silesia.tar, multithreaded with advanced params, advanced streaming, 5116442 github, level -5, advanced streaming, 204407 @@ -1087,44 +1087,44 @@ github.tar, level 4 with dict dms, advanced github.tar, level 4 with dict dds, advanced streaming, 38317 github.tar, level 4 with dict copy, advanced streaming, 38270 github.tar, level 4 with dict load, advanced streaming, 38259 -github.tar, level 5 row 1, advanced streaming, 39986 -github.tar, level 5 row 1 with dict dms, advanced streaming, 39370 -github.tar, level 5 row 1 with dict dds, advanced streaming, 39396 -github.tar, level 5 row 1 with dict copy, advanced streaming, 39465 -github.tar, level 5 row 1 with dict load, advanced streaming, 39332 -github.tar, level 5 row 2, advanced streaming, 40038 -github.tar, level 5 row 2 with dict dms, advanced streaming, 39690 -github.tar, level 5 row 2 with dict dds, advanced streaming, 39555 -github.tar, level 5 row 2 with dict copy, advanced streaming, 40036 -github.tar, level 5 row 2 with dict load, advanced streaming, 39498 -github.tar, level 5, advanced streaming, 39986 -github.tar, level 5 with dict, advanced streaming, 39465 -github.tar, level 5 with dict dms, advanced streaming, 39370 -github.tar, level 5 with dict dds, advanced streaming, 39396 -github.tar, level 5 with dict copy, advanced streaming, 39465 -github.tar, level 5 with dict load, advanced streaming, 39332 -github.tar, level 6, advanced streaming, 39565 -github.tar, level 6 with dict, advanced streaming, 38894 -github.tar, level 6 with dict dms, advanced streaming, 38901 -github.tar, level 6 with dict dds, advanced streaming, 38903 -github.tar, level 6 with dict copy, advanced streaming, 38894 -github.tar, level 6 with dict load, advanced streaming, 38906 -github.tar, level 7 row 1, advanced streaming, 38295 +github.tar, level 5 row 1, advanced streaming, 39651 +github.tar, level 5 row 1 with dict dms, advanced streaming, 39043 +github.tar, level 5 row 1 with dict dds, advanced streaming, 39069 +github.tar, level 5 row 1 with dict copy, advanced streaming, 39145 +github.tar, level 5 row 1 with dict load, advanced streaming, 39000 +github.tar, level 5 row 2, advanced streaming, 39701 +github.tar, level 5 row 2 with dict dms, advanced streaming, 39365 +github.tar, level 5 row 2 with dict dds, advanced streaming, 39233 +github.tar, level 5 row 2 with dict copy, advanced streaming, 39715 +github.tar, level 5 row 2 with dict load, advanced streaming, 39158 +github.tar, level 5, advanced streaming, 39651 +github.tar, level 5 with dict, advanced streaming, 39145 +github.tar, level 5 with dict dms, advanced streaming, 39043 +github.tar, level 5 with dict dds, advanced streaming, 39069 +github.tar, level 5 with dict copy, advanced streaming, 39145 +github.tar, level 5 with dict load, advanced streaming, 39000 +github.tar, level 6, advanced streaming, 39282 +github.tar, level 6 with dict, advanced streaming, 38656 +github.tar, level 6 with dict dms, advanced streaming, 38640 +github.tar, level 6 with dict dds, advanced streaming, 38643 +github.tar, level 6 with dict copy, advanced streaming, 38656 +github.tar, level 6 with dict load, advanced streaming, 38647 +github.tar, level 7 row 1, advanced streaming, 38005 github.tar, level 7 row 1 with dict dms, advanced streaming, 37832 github.tar, level 7 row 1 with dict dds, advanced streaming, 37857 github.tar, level 7 row 1 with dict copy, advanced streaming, 37839 -github.tar, level 7 row 1 with dict load, advanced streaming, 37565 -github.tar, level 7 row 2, advanced streaming, 38369 +github.tar, level 7 row 1 with dict load, advanced streaming, 37286 +github.tar, level 7 row 2, advanced streaming, 38077 github.tar, level 7 row 2 with dict dms, advanced streaming, 38012 github.tar, level 7 row 2 with dict dds, advanced streaming, 38014 github.tar, level 7 row 2 with dict copy, advanced streaming, 38101 -github.tar, level 7 row 2 with dict load, advanced streaming, 37688 -github.tar, level 7, advanced streaming, 38295 +github.tar, level 7 row 2 with dict load, advanced streaming, 37402 +github.tar, level 7, advanced streaming, 38005 github.tar, level 7 with dict, advanced streaming, 37839 github.tar, level 7 with dict dms, advanced streaming, 37832 github.tar, level 7 with dict dds, advanced streaming, 37857 github.tar, level 7 with dict copy, advanced streaming, 37839 -github.tar, level 7 with dict load, advanced streaming, 37565 +github.tar, level 7 with dict load, advanced streaming, 37286 github.tar, level 9, advanced streaming, 36723 github.tar, level 9 with dict, advanced streaming, 36531 github.tar, level 9 with dict dms, advanced streaming, 36615 @@ -1177,7 +1177,7 @@ github.tar, multithreaded long distance mode, advanced github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 -github.tar, explicit params, advanced streaming, 41768 +github.tar, explicit params, advanced streaming, 41385 github.tar, uncompressed literals, advanced streaming, 41784 github.tar, uncompressed literals optimal, advanced streaming, 35356 github.tar, huffman literals, advanced streaming, 39226 @@ -1189,16 +1189,16 @@ silesia, level 0, old stre silesia, level 1, old streaming, 5305682 silesia, level 3, old streaming, 4839173 silesia, level 4, old streaming, 4776074 -silesia, level 5, old streaming, 4667049 -silesia, level 6, old streaming, 4602956 -silesia, level 7, old streaming, 4568785 -silesia, level 9, old streaming, 4545850 -silesia, level 13, old streaming, 4493990 -silesia, level 16, old streaming, 4359652 -silesia, level 19, old streaming, 4266582 +silesia, level 5, old streaming, 4664679 +silesia, level 6, old streaming, 4601116 +silesia, level 7, old streaming, 4567082 +silesia, level 9, old streaming, 4542474 +silesia, level 13, old streaming, 4490650 +silesia, level 16, old streaming, 4358094 +silesia, level 19, old streaming, 4265908 silesia, no source size, old streaming, 4839137 silesia, uncompressed literals, old streaming, 4839173 -silesia, uncompressed literals optimal, old streaming, 4266582 +silesia, uncompressed literals optimal, old streaming, 4265908 silesia, huffman literals, old streaming, 6174139 silesia.tar, level -5, old streaming, 6857458 silesia.tar, level -3, old streaming, 6508562 @@ -1207,16 +1207,16 @@ silesia.tar, level 0, old stre silesia.tar, level 1, old streaming, 5311452 silesia.tar, level 3, old streaming, 4849720 silesia.tar, level 4, old streaming, 4787534 -silesia.tar, level 5, old streaming, 4669420 -silesia.tar, level 6, old streaming, 4604125 -silesia.tar, level 7, old streaming, 4570206 -silesia.tar, level 9, old streaming, 4555445 -silesia.tar, level 13, old streaming, 4502956 -silesia.tar, level 16, old streaming, 4360385 -silesia.tar, level 19, old streaming, 4260939 +silesia.tar, level 5, old streaming, 4664523 +silesia.tar, level 6, old streaming, 4599420 +silesia.tar, level 7, old streaming, 4565332 +silesia.tar, level 9, old streaming, 4539391 +silesia.tar, level 13, old streaming, 4486652 +silesia.tar, level 16, old streaming, 4358029 +silesia.tar, level 19, old streaming, 4258228 silesia.tar, no source size, old streaming, 4849716 silesia.tar, uncompressed literals, old streaming, 4849720 -silesia.tar, uncompressed literals optimal, old streaming, 4260939 +silesia.tar, uncompressed literals optimal, old streaming, 4258228 silesia.tar, huffman literals, old streaming, 6178057 github, level -5, old streaming, 204407 github, level -5 with dict, old streaming, 45832 @@ -1265,11 +1265,11 @@ github.tar, level 3, old stre github.tar, level 3 with dict, old streaming, 38309 github.tar, level 4, old streaming, 39247 github.tar, level 4 with dict, old streaming, 38270 -github.tar, level 5, old streaming, 39986 -github.tar, level 5 with dict, old streaming, 39465 -github.tar, level 6, old streaming, 39565 -github.tar, level 6 with dict, old streaming, 38894 -github.tar, level 7, old streaming, 38295 +github.tar, level 5, old streaming, 39651 +github.tar, level 5 with dict, old streaming, 39145 +github.tar, level 6, old streaming, 39282 +github.tar, level 6 with dict, old streaming, 38656 +github.tar, level 7, old streaming, 38005 github.tar, level 7 with dict, old streaming, 37839 github.tar, level 9, old streaming, 36723 github.tar, level 9 with dict, old streaming, 36531 @@ -1291,23 +1291,23 @@ silesia, level 0, old stre silesia, level 1, old streaming advanced, 5305682 silesia, level 3, old streaming advanced, 4839173 silesia, level 4, old streaming advanced, 4776074 -silesia, level 5, old streaming advanced, 4667049 -silesia, level 6, old streaming advanced, 4602956 -silesia, level 7, old streaming advanced, 4568785 -silesia, level 9, old streaming advanced, 4545850 -silesia, level 13, old streaming advanced, 4493990 -silesia, level 16, old streaming advanced, 4359652 -silesia, level 19, old streaming advanced, 4266582 +silesia, level 5, old streaming advanced, 4664679 +silesia, level 6, old streaming advanced, 4601116 +silesia, level 7, old streaming advanced, 4567082 +silesia, level 9, old streaming advanced, 4542474 +silesia, level 13, old streaming advanced, 4490650 +silesia, level 16, old streaming advanced, 4358094 +silesia, level 19, old streaming advanced, 4265908 silesia, no source size, old streaming advanced, 4839137 silesia, long distance mode, old streaming advanced, 4839173 silesia, multithreaded, old streaming advanced, 4839173 silesia, multithreaded long distance mode, old streaming advanced, 4839173 silesia, small window log, old streaming advanced, 7110591 -silesia, small hash log, old streaming advanced, 6526141 -silesia, small chain log, old streaming advanced, 4912197 -silesia, explicit params, old streaming advanced, 4795053 +silesia, small hash log, old streaming advanced, 6525259 +silesia, small chain log, old streaming advanced, 4911577 +silesia, explicit params, old streaming advanced, 4792505 silesia, uncompressed literals, old streaming advanced, 4839173 -silesia, uncompressed literals optimal, old streaming advanced, 4266582 +silesia, uncompressed literals optimal, old streaming advanced, 4265908 silesia, huffman literals, old streaming advanced, 6174139 silesia, multithreaded with advanced params, old streaming advanced, 4839173 silesia.tar, level -5, old streaming advanced, 6857458 @@ -1317,23 +1317,23 @@ silesia.tar, level 0, old stre silesia.tar, level 1, old streaming advanced, 5311452 silesia.tar, level 3, old streaming advanced, 4849720 silesia.tar, level 4, old streaming advanced, 4787534 -silesia.tar, level 5, old streaming advanced, 4669420 -silesia.tar, level 6, old streaming advanced, 4604125 -silesia.tar, level 7, old streaming advanced, 4570206 -silesia.tar, level 9, old streaming advanced, 4555445 -silesia.tar, level 13, old streaming advanced, 4502956 -silesia.tar, level 16, old streaming advanced, 4360385 -silesia.tar, level 19, old streaming advanced, 4260939 +silesia.tar, level 5, old streaming advanced, 4664523 +silesia.tar, level 6, old streaming advanced, 4599420 +silesia.tar, level 7, old streaming advanced, 4565332 +silesia.tar, level 9, old streaming advanced, 4539391 +silesia.tar, level 13, old streaming advanced, 4486652 +silesia.tar, level 16, old streaming advanced, 4358029 +silesia.tar, level 19, old streaming advanced, 4258228 silesia.tar, no source size, old streaming advanced, 4849716 silesia.tar, long distance mode, old streaming advanced, 4849720 silesia.tar, multithreaded, old streaming advanced, 4849720 silesia.tar, multithreaded long distance mode, old streaming advanced, 4849720 silesia.tar, small window log, old streaming advanced, 7117027 -silesia.tar, small hash log, old streaming advanced, 6529209 -silesia.tar, small chain log, old streaming advanced, 4917021 -silesia.tar, explicit params, old streaming advanced, 4797673 +silesia.tar, small hash log, old streaming advanced, 6529503 +silesia.tar, small chain log, old streaming advanced, 4915956 +silesia.tar, explicit params, old streaming advanced, 4791739 silesia.tar, uncompressed literals, old streaming advanced, 4849720 -silesia.tar, uncompressed literals optimal, old streaming advanced, 4260939 +silesia.tar, uncompressed literals optimal, old streaming advanced, 4258228 silesia.tar, huffman literals, old streaming advanced, 6178057 silesia.tar, multithreaded with advanced params, old streaming advanced, 4849720 github, level -5, old streaming advanced, 213265 @@ -1391,12 +1391,12 @@ github.tar, level 3, old stre github.tar, level 3 with dict, old streaming advanced, 38327 github.tar, level 4, old streaming advanced, 39247 github.tar, level 4 with dict, old streaming advanced, 38382 -github.tar, level 5, old streaming advanced, 39986 -github.tar, level 5 with dict, old streaming advanced, 39347 -github.tar, level 6, old streaming advanced, 39565 -github.tar, level 6 with dict, old streaming advanced, 38889 -github.tar, level 7, old streaming advanced, 38295 -github.tar, level 7 with dict, old streaming advanced, 37534 +github.tar, level 5, old streaming advanced, 39651 +github.tar, level 5 with dict, old streaming advanced, 39018 +github.tar, level 6, old streaming advanced, 39282 +github.tar, level 6 with dict, old streaming advanced, 38635 +github.tar, level 7, old streaming advanced, 38005 +github.tar, level 7 with dict, old streaming advanced, 37264 github.tar, level 9, old streaming advanced, 36723 github.tar, level 9 with dict, old streaming advanced, 36241 github.tar, level 13, old streaming advanced, 35501 @@ -1413,7 +1413,7 @@ github.tar, multithreaded long distance mode, old stre github.tar, small window log, old streaming advanced, 199556 github.tar, small hash log, old streaming advanced, 129870 github.tar, small chain log, old streaming advanced, 41669 -github.tar, explicit params, old streaming advanced, 41768 +github.tar, explicit params, old streaming advanced, 41385 github.tar, uncompressed literals, old streaming advanced, 39249 github.tar, uncompressed literals optimal, old streaming advanced, 32262 github.tar, huffman literals, old streaming advanced, 42777 @@ -1440,9 +1440,9 @@ github.tar, level 0 with dict, old stre github.tar, level 1 with dict, old streaming cdict, 38716 github.tar, level 3 with dict, old streaming cdict, 38281 github.tar, level 4 with dict, old streaming cdict, 38259 -github.tar, level 5 with dict, old streaming cdict, 39332 -github.tar, level 6 with dict, old streaming cdict, 38906 -github.tar, level 7 with dict, old streaming cdict, 37565 +github.tar, level 5 with dict, old streaming cdict, 39000 +github.tar, level 6 with dict, old streaming cdict, 38647 +github.tar, level 7 with dict, old streaming cdict, 37286 github.tar, level 9 with dict, old streaming cdict, 36322 github.tar, level 13 with dict, old streaming cdict, 36010 github.tar, level 16 with dict, old streaming cdict, 39081 @@ -1470,9 +1470,9 @@ github.tar, level 0 with dict, old stre github.tar, level 1 with dict, old streaming advanced cdict, 38513 github.tar, level 3 with dict, old streaming advanced cdict, 38327 github.tar, level 4 with dict, old streaming advanced cdict, 38382 -github.tar, level 5 with dict, old streaming advanced cdict, 39347 -github.tar, level 6 with dict, old streaming advanced cdict, 38889 -github.tar, level 7 with dict, old streaming advanced cdict, 37534 +github.tar, level 5 with dict, old streaming advanced cdict, 39018 +github.tar, level 6 with dict, old streaming advanced cdict, 38635 +github.tar, level 7 with dict, old streaming advanced cdict, 37264 github.tar, level 9 with dict, old streaming advanced cdict, 36241 github.tar, level 13 with dict, old streaming advanced cdict, 35807 github.tar, level 16 with dict, old streaming advanced cdict, 38578 From 2366a87ddc7ed9ad54944404c57e506ea8bd79bc Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 13:38:12 -0700 Subject: [PATCH 150/405] fix minor visual conversion warning --- lib/compress/zstd_preSplit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 63ff0ded8..77f4534dc 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -63,7 +63,7 @@ addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t sampl FORCE_INLINE_TEMPLATE void recordFingerprint_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog) { - ZSTD_memset(fp, 0, sizeof(unsigned) * (1 << hashLog)); + ZSTD_memset(fp, 0, sizeof(unsigned) * ((size_t)1 << hashLog)); fp->nbEvents = 0; addEvents_generic(fp, src, srcSize, samplingRate, hashLog); } From da2c0dffd8c3e6306fcf2e8e5bd5f8ef97d7a999 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 14:37:00 -0700 Subject: [PATCH 151/405] add faster block splitting heuristic, suitable for dfast strategy --- lib/compress/zstd_compress.c | 8 +++++--- lib/compress/zstd_preSplit.c | 22 ++++++++++++++-------- lib/compress/zstd_preSplit.h | 7 +++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e78de2ba8..ee939f227 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4507,11 +4507,13 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) - return ZSTD_splitBlock(src, blockSizeMax, split_lvl3, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, blockSizeMax, 3, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_lazy2) - return ZSTD_splitBlock(src, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, blockSizeMax, 2, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_greedy) - return ZSTD_splitBlock(src, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); + return ZSTD_splitBlock(src, blockSizeMax, 1, cctx->tmpWorkspace, cctx->tmpWkspSize); + if (strat >= ZSTD_dfast) + return ZSTD_splitBlock(src, blockSizeMax, 0, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * heuristic value, tested as being "generally better". * no cpu cost, but can over-split homegeneous data. diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 77f4534dc..3f6edb612 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -26,8 +26,13 @@ #define HASHMASK (HASHTABLESIZE - 1) #define KNUTH 0x9e3779b9 +/* for hashLog > 8, hash 2 bytes. + * for hashLog == 8, just take the byte, no hashing. + * The speed of this method relies on compile-time constant propagation */ FORCE_INLINE_TEMPLATE unsigned hash2(const void *p, unsigned hashLog) { + assert(hashLog >= 8); + if (hashLog == 8) return (U32)((const BYTE*)p)[0]; assert(hashLog <= HASHLOG_MAX); return (U32)(MEM_read16(p)) * KNUTH >> (32 - hashLog); } @@ -81,6 +86,7 @@ typedef void (*RecordEvents_f)(Fingerprint* fp, const void* src, size_t srcSize) ZSTD_GEN_RECORD_FINGERPRINT(1, 10) ZSTD_GEN_RECORD_FINGERPRINT(5, 10) ZSTD_GEN_RECORD_FINGERPRINT(11, 9) +ZSTD_GEN_RECORD_FINGERPRINT(43, 8) static U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); } @@ -145,14 +151,14 @@ static void removeEvents(Fingerprint* acc, const Fingerprint* slice) #define CHUNKSIZE (8 << 10) static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, - ZSTD_SplitBlock_strategy_e splitStrat, + int level, void* workspace, size_t wkspSize) { static const RecordEvents_f records_fs[] = { - FP_RECORD(11), FP_RECORD(5), FP_RECORD(1) + FP_RECORD(43), FP_RECORD(11), FP_RECORD(5), FP_RECORD(1) }; - static const unsigned hashParams[] = { 9, 10, 10 }; - const RecordEvents_f record_f = (assert(splitStrat<=split_lvl3), records_fs[splitStrat]); + static const unsigned hashParams[] = { 8, 9, 10, 10 }; + const RecordEvents_f record_f = (assert(0<=level && level<=3), records_fs[level]); FPStats* const fpstats = (FPStats*)workspace; const char* p = (const char*)blockStart; int penalty = THRESHOLD_PENALTY; @@ -167,7 +173,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, record_f(&fpstats->pastEvents, p, CHUNKSIZE); for (pos = CHUNKSIZE; pos <= blockSize - CHUNKSIZE; pos += CHUNKSIZE) { record_f(&fpstats->newEvents, p + pos, CHUNKSIZE); - if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty, hashParams[splitStrat])) { + if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty, hashParams[level])) { return pos; } else { mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); @@ -180,9 +186,9 @@ static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, } size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, - ZSTD_SplitBlock_strategy_e splitStrat, + int level, void* workspace, size_t wkspSize) { - assert(splitStrat <= split_lvl3); - return ZSTD_splitBlock_byChunks(blockStart, blockSize, splitStrat, workspace, wkspSize); + assert(0<=level && level<=3); + return ZSTD_splitBlock_byChunks(blockStart, blockSize, level, workspace, wkspSize); } diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index cf829ecee..07d7d4ef5 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -17,11 +17,10 @@ extern "C" { #endif -typedef enum { split_lvl1, split_lvl2, split_lvl3 } ZSTD_SplitBlock_strategy_e; - #define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 -/* note: +/* @level must be a value between 0 and 3. + * higher levels spend more energy to find block boundaries * @workspace must be aligned on 8-bytes boundaries * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE * note2: @@ -30,7 +29,7 @@ typedef enum { split_lvl1, split_lvl2, split_lvl3 } ZSTD_SplitBlock_strategy_e; * This could be extended to smaller sizes in the future. */ size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, - ZSTD_SplitBlock_strategy_e splitStrat, + int level, void* workspace, size_t wkspSize); #if defined (__cplusplus) From c63b5d2294cf6d185a5b284725e5db09646a3296 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 14:47:55 -0700 Subject: [PATCH 152/405] update regression results --- tests/regression/results.csv | 466 +++++++++++++++++------------------ 1 file changed, 233 insertions(+), 233 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index b46c4ca5c..0b1a79b85 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -2,10 +2,10 @@ Data, Config, Method, silesia.tar, level -5, compress simple, 6860782 silesia.tar, level -3, compress simple, 6507448 silesia.tar, level -1, compress simple, 6175582 -silesia.tar, level 0, compress simple, 4843429 +silesia.tar, level 0, compress simple, 4829268 silesia.tar, level 1, compress simple, 5316794 -silesia.tar, level 3, compress simple, 4843429 -silesia.tar, level 4, compress simple, 4780657 +silesia.tar, level 3, compress simple, 4829268 +silesia.tar, level 4, compress simple, 4767074 silesia.tar, level 5, compress simple, 4662847 silesia.tar, level 6, compress simple, 4597877 silesia.tar, level 7, compress simple, 4563998 @@ -13,16 +13,16 @@ silesia.tar, level 9, compress silesia.tar, level 13, compress simple, 4484732 silesia.tar, level 16, compress simple, 4355572 silesia.tar, level 19, compress simple, 4257629 -silesia.tar, uncompressed literals, compress simple, 4843429 +silesia.tar, uncompressed literals, compress simple, 4829268 silesia.tar, uncompressed literals optimal, compress simple, 4257629 silesia.tar, huffman literals, compress simple, 6175582 github.tar, level -5, compress simple, 52320 github.tar, level -3, compress simple, 45823 github.tar, level -1, compress simple, 42740 -github.tar, level 0, compress simple, 39073 +github.tar, level 0, compress simple, 38884 github.tar, level 1, compress simple, 39444 -github.tar, level 3, compress simple, 39073 -github.tar, level 4, compress simple, 39068 +github.tar, level 3, compress simple, 38884 +github.tar, level 4, compress simple, 38880 github.tar, level 5, compress simple, 39651 github.tar, level 6, compress simple, 39282 github.tar, level 7, compress simple, 38005 @@ -30,16 +30,16 @@ github.tar, level 9, compress github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 github.tar, level 19, compress simple, 32262 -github.tar, uncompressed literals, compress simple, 39073 +github.tar, uncompressed literals, compress simple, 38884 github.tar, uncompressed literals optimal, compress simple, 32262 github.tar, huffman literals, compress simple, 42740 silesia, level -5, compress cctx, 6857776 silesia, level -3, compress cctx, 6504756 silesia, level -1, compress cctx, 6174127 -silesia, level 0, compress cctx, 4838417 +silesia, level 0, compress cctx, 4832054 silesia, level 1, compress cctx, 5306931 -silesia, level 3, compress cctx, 4838417 -silesia, level 4, compress cctx, 4775359 +silesia, level 3, compress cctx, 4832054 +silesia, level 4, compress cctx, 4768799 silesia, level 5, compress cctx, 4663718 silesia, level 6, compress cctx, 4600034 silesia, level 7, compress cctx, 4566069 @@ -47,17 +47,17 @@ silesia, level 9, compress silesia, level 13, compress cctx, 4488969 silesia, level 16, compress cctx, 4356799 silesia, level 19, compress cctx, 4265851 -silesia, long distance mode, compress cctx, 4838417 -silesia, multithreaded, compress cctx, 4838417 -silesia, multithreaded long distance mode, compress cctx, 4838417 +silesia, long distance mode, compress cctx, 4832054 +silesia, multithreaded, compress cctx, 4832054 +silesia, multithreaded long distance mode, compress cctx, 4832054 silesia, small window log, compress cctx, 7082907 silesia, small hash log, compress cctx, 6525510 silesia, small chain log, compress cctx, 4912248 silesia, explicit params, compress cctx, 4789676 -silesia, uncompressed literals, compress cctx, 4838417 +silesia, uncompressed literals, compress cctx, 4832054 silesia, uncompressed literals optimal, compress cctx, 4265851 silesia, huffman literals, compress cctx, 6174127 -silesia, multithreaded with advanced params, compress cctx, 4838417 +silesia, multithreaded with advanced params, compress cctx, 4832054 github, level -5, compress cctx, 204407 github, level -5 with dict, compress cctx, 47581 github, level -3, compress cctx, 193253 @@ -100,10 +100,10 @@ github, multithreaded with advanced params, compress silesia, level -5, zstdcli, 6856073 silesia, level -3, zstdcli, 6505580 silesia, level -1, zstdcli, 6172649 -silesia, level 0, zstdcli, 4838997 +silesia, level 0, zstdcli, 4833113 silesia, level 1, zstdcli, 5306179 -silesia, level 3, zstdcli, 4838997 -silesia, level 4, zstdcli, 4775769 +silesia, level 3, zstdcli, 4833113 +silesia, level 4, zstdcli, 4770061 silesia, level 5, zstdcli, 4663332 silesia, level 6, zstdcli, 4599601 silesia, level 7, zstdcli, 4565601 @@ -111,24 +111,24 @@ silesia, level 9, zstdcli, silesia, level 13, zstdcli, 4488438 silesia, level 16, zstdcli, 4358150 silesia, level 19, zstdcli, 4265929 -silesia, long distance mode, zstdcli, 4830467 -silesia, multithreaded, zstdcli, 4838997 -silesia, multithreaded long distance mode, zstdcli, 4830467 +silesia, long distance mode, zstdcli, 4824875 +silesia, multithreaded, zstdcli, 4833113 +silesia, multithreaded long distance mode, zstdcli, 4824875 silesia, small window log, zstdcli, 7094528 silesia, small hash log, zstdcli, 6527214 silesia, small chain log, zstdcli, 4911647 silesia, explicit params, zstdcli, 4790803 -silesia, uncompressed literals, zstdcli, 5117843 +silesia, uncompressed literals, zstdcli, 5118235 silesia, uncompressed literals optimal, zstdcli, 4316761 silesia, huffman literals, zstdcli, 5320793 -silesia, multithreaded with advanced params, zstdcli, 5117843 +silesia, multithreaded with advanced params, zstdcli, 5118235 silesia.tar, level -5, zstdcli, 6860173 silesia.tar, level -3, zstdcli, 6507196 silesia.tar, level -1, zstdcli, 6177719 -silesia.tar, level 0, zstdcli, 4841906 +silesia.tar, level 0, zstdcli, 4836004 silesia.tar, level 1, zstdcli, 5313917 -silesia.tar, level 3, zstdcli, 4841906 -silesia.tar, level 4, zstdcli, 4780121 +silesia.tar, level 3, zstdcli, 4836004 +silesia.tar, level 4, zstdcli, 4774061 silesia.tar, level 5, zstdcli, 4667310 silesia.tar, level 6, zstdcli, 4602398 silesia.tar, level 7, zstdcli, 4568891 @@ -136,18 +136,18 @@ silesia.tar, level 9, zstdcli, silesia.tar, level 13, zstdcli, 4488484 silesia.tar, level 16, zstdcli, 4357018 silesia.tar, level 19, zstdcli, 4259593 -silesia.tar, no source size, zstdcli, 4841902 -silesia.tar, long distance mode, zstdcli, 4834266 -silesia.tar, multithreaded, zstdcli, 4841906 -silesia.tar, multithreaded long distance mode, zstdcli, 4834266 +silesia.tar, no source size, zstdcli, 4836000 +silesia.tar, long distance mode, zstdcli, 4828171 +silesia.tar, multithreaded, zstdcli, 4836004 +silesia.tar, multithreaded long distance mode, zstdcli, 4828171 silesia.tar, small window log, zstdcli, 7100110 silesia.tar, small hash log, zstdcli, 6530127 silesia.tar, small chain log, zstdcli, 4915865 silesia.tar, explicit params, zstdcli, 4808370 -silesia.tar, uncompressed literals, zstdcli, 5116446 +silesia.tar, uncompressed literals, zstdcli, 5116583 silesia.tar, uncompressed literals optimal, zstdcli, 4306520 silesia.tar, huffman literals, zstdcli, 5326463 -silesia.tar, multithreaded with advanced params, zstdcli, 5116446 +silesia.tar, multithreaded with advanced params, zstdcli, 5116583 github, level -5, zstdcli, 206407 github, level -5 with dict, zstdcli, 47832 github, level -3, zstdcli, 195253 @@ -193,14 +193,14 @@ github.tar, level -3, zstdcli, github.tar, level -3 with dict, zstdcli, 44883 github.tar, level -1, zstdcli, 42688 github.tar, level -1 with dict, zstdcli, 41510 -github.tar, level 0, zstdcli, 39071 -github.tar, level 0 with dict, zstdcli, 38140 +github.tar, level 0, zstdcli, 38888 +github.tar, level 0 with dict, zstdcli, 37999 github.tar, level 1, zstdcli, 39404 github.tar, level 1 with dict, zstdcli, 38320 -github.tar, level 3, zstdcli, 39071 -github.tar, level 3 with dict, zstdcli, 38140 -github.tar, level 4, zstdcli, 39067 -github.tar, level 4 with dict, zstdcli, 38082 +github.tar, level 3, zstdcli, 38888 +github.tar, level 3 with dict, zstdcli, 37999 +github.tar, level 4, zstdcli, 38884 +github.tar, level 4 with dict, zstdcli, 37952 github.tar, level 5, zstdcli, 39655 github.tar, level 5 with dict, zstdcli, 39073 github.tar, level 6, zstdcli, 39286 @@ -215,26 +215,26 @@ github.tar, level 16, zstdcli, github.tar, level 16 with dict, zstdcli, 33379 github.tar, level 19, zstdcli, 32266 github.tar, level 19 with dict, zstdcli, 32705 -github.tar, no source size, zstdcli, 39068 -github.tar, no source size with dict, zstdcli, 38274 -github.tar, long distance mode, zstdcli, 40381 -github.tar, multithreaded, zstdcli, 39071 -github.tar, multithreaded long distance mode, zstdcli, 40381 +github.tar, no source size, zstdcli, 38885 +github.tar, no source size with dict, zstdcli, 38115 +github.tar, long distance mode, zstdcli, 40227 +github.tar, multithreaded, zstdcli, 38888 +github.tar, multithreaded long distance mode, zstdcli, 40227 github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 github.tar, explicit params, zstdcli, 41385 -github.tar, uncompressed literals, zstdcli, 41704 +github.tar, uncompressed literals, zstdcli, 41566 github.tar, uncompressed literals optimal, zstdcli, 35360 github.tar, huffman literals, zstdcli, 39046 -github.tar, multithreaded with advanced params, zstdcli, 41704 +github.tar, multithreaded with advanced params, zstdcli, 41566 silesia, level -5, advanced one pass, 6857776 silesia, level -3, advanced one pass, 6504756 silesia, level -1, advanced one pass, 6174127 -silesia, level 0, advanced one pass, 4838417 +silesia, level 0, advanced one pass, 4832054 silesia, level 1, advanced one pass, 5306931 -silesia, level 3, advanced one pass, 4838417 -silesia, level 4, advanced one pass, 4775359 +silesia, level 3, advanced one pass, 4832054 +silesia, level 4, advanced one pass, 4768799 silesia, level 5 row 1, advanced one pass, 4663718 silesia, level 5 row 2, advanced one pass, 4666272 silesia, level 5, advanced one pass, 4663718 @@ -250,25 +250,25 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced one pass, 4488969 silesia, level 16, advanced one pass, 4356799 silesia, level 19, advanced one pass, 4265851 -silesia, no source size, advanced one pass, 4838417 -silesia, long distance mode, advanced one pass, 4830097 -silesia, multithreaded, advanced one pass, 4838949 -silesia, multithreaded long distance mode, advanced one pass, 4830419 +silesia, no source size, advanced one pass, 4832054 +silesia, long distance mode, advanced one pass, 4823833 +silesia, multithreaded, advanced one pass, 4833065 +silesia, multithreaded long distance mode, advanced one pass, 4824827 silesia, small window log, advanced one pass, 7094480 silesia, small hash log, advanced one pass, 6525510 silesia, small chain log, advanced one pass, 4912248 silesia, explicit params, advanced one pass, 4791219 -silesia, uncompressed literals, advanced one pass, 5117482 +silesia, uncompressed literals, advanced one pass, 5117526 silesia, uncompressed literals optimal, advanced one pass, 4316644 silesia, huffman literals, advanced one pass, 5321686 -silesia, multithreaded with advanced params, advanced one pass, 5117795 +silesia, multithreaded with advanced params, advanced one pass, 5118187 silesia.tar, level -5, advanced one pass, 6860782 silesia.tar, level -3, advanced one pass, 6507448 silesia.tar, level -1, advanced one pass, 6175582 -silesia.tar, level 0, advanced one pass, 4843429 +silesia.tar, level 0, advanced one pass, 4829268 silesia.tar, level 1, advanced one pass, 5316794 -silesia.tar, level 3, advanced one pass, 4843429 -silesia.tar, level 4, advanced one pass, 4780657 +silesia.tar, level 3, advanced one pass, 4829268 +silesia.tar, level 4, advanced one pass, 4767074 silesia.tar, level 5 row 1, advanced one pass, 4662847 silesia.tar, level 5 row 2, advanced one pass, 4666825 silesia.tar, level 5, advanced one pass, 4662847 @@ -284,18 +284,18 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced one pass, 4484732 silesia.tar, level 16, advanced one pass, 4355572 silesia.tar, level 19, advanced one pass, 4257629 -silesia.tar, no source size, advanced one pass, 4843429 -silesia.tar, long distance mode, advanced one pass, 4830453 -silesia.tar, multithreaded, advanced one pass, 4841902 -silesia.tar, multithreaded long distance mode, advanced one pass, 4834262 +silesia.tar, no source size, advanced one pass, 4829268 +silesia.tar, long distance mode, advanced one pass, 4816169 +silesia.tar, multithreaded, advanced one pass, 4836000 +silesia.tar, multithreaded long distance mode, advanced one pass, 4828167 silesia.tar, small window log, advanced one pass, 7100064 silesia.tar, small hash log, advanced one pass, 6530222 silesia.tar, small chain log, advanced one pass, 4915689 silesia.tar, explicit params, advanced one pass, 4790421 -silesia.tar, uncompressed literals, advanced one pass, 5116329 +silesia.tar, uncompressed literals, advanced one pass, 5114702 silesia.tar, uncompressed literals optimal, advanced one pass, 4306289 silesia.tar, huffman literals, advanced one pass, 5331382 -silesia.tar, multithreaded with advanced params, advanced one pass, 5116442 +silesia.tar, multithreaded with advanced params, advanced one pass, 5116579 github, level -5, advanced one pass, 204407 github, level -5 with dict, advanced one pass, 45832 github, level -3, advanced one pass, 193253 @@ -427,30 +427,30 @@ github.tar, level -3, advanced github.tar, level -3 with dict, advanced one pass, 44882 github.tar, level -1, advanced one pass, 42740 github.tar, level -1 with dict, advanced one pass, 41506 -github.tar, level 0, advanced one pass, 39073 -github.tar, level 0 with dict, advanced one pass, 38146 -github.tar, level 0 with dict dms, advanced one pass, 38262 -github.tar, level 0 with dict dds, advanced one pass, 38262 -github.tar, level 0 with dict copy, advanced one pass, 38146 -github.tar, level 0 with dict load, advanced one pass, 38107 +github.tar, level 0, advanced one pass, 38884 +github.tar, level 0 with dict, advanced one pass, 37995 +github.tar, level 0 with dict dms, advanced one pass, 38114 +github.tar, level 0 with dict dds, advanced one pass, 38114 +github.tar, level 0 with dict copy, advanced one pass, 37995 +github.tar, level 0 with dict load, advanced one pass, 37956 github.tar, level 1, advanced one pass, 39444 github.tar, level 1 with dict, advanced one pass, 38338 github.tar, level 1 with dict dms, advanced one pass, 38641 github.tar, level 1 with dict dds, advanced one pass, 38641 github.tar, level 1 with dict copy, advanced one pass, 38338 github.tar, level 1 with dict load, advanced one pass, 38592 -github.tar, level 3, advanced one pass, 39073 -github.tar, level 3 with dict, advanced one pass, 38146 -github.tar, level 3 with dict dms, advanced one pass, 38262 -github.tar, level 3 with dict dds, advanced one pass, 38262 -github.tar, level 3 with dict copy, advanced one pass, 38146 -github.tar, level 3 with dict load, advanced one pass, 38107 -github.tar, level 4, advanced one pass, 39068 -github.tar, level 4 with dict, advanced one pass, 38081 -github.tar, level 4 with dict dms, advanced one pass, 38135 -github.tar, level 4 with dict dds, advanced one pass, 38135 -github.tar, level 4 with dict copy, advanced one pass, 38081 -github.tar, level 4 with dict load, advanced one pass, 38088 +github.tar, level 3, advanced one pass, 38884 +github.tar, level 3 with dict, advanced one pass, 37995 +github.tar, level 3 with dict dms, advanced one pass, 38114 +github.tar, level 3 with dict dds, advanced one pass, 38114 +github.tar, level 3 with dict copy, advanced one pass, 37995 +github.tar, level 3 with dict load, advanced one pass, 37956 +github.tar, level 4, advanced one pass, 38880 +github.tar, level 4 with dict, advanced one pass, 37948 +github.tar, level 4 with dict dms, advanced one pass, 37995 +github.tar, level 4 with dict dds, advanced one pass, 37995 +github.tar, level 4 with dict copy, advanced one pass, 37948 +github.tar, level 4 with dict load, advanced one pass, 37927 github.tar, level 5 row 1, advanced one pass, 39651 github.tar, level 5 row 1 with dict dms, advanced one pass, 39043 github.tar, level 5 row 1 with dict dds, advanced one pass, 39069 @@ -533,26 +533,26 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass, 32565 github.tar, level 19 with dict copy, advanced one pass, 32701 github.tar, level 19 with dict load, advanced one pass, 32428 -github.tar, no source size, advanced one pass, 39073 -github.tar, no source size with dict, advanced one pass, 38146 -github.tar, long distance mode, advanced one pass, 40402 -github.tar, multithreaded, advanced one pass, 39067 -github.tar, multithreaded long distance mode, advanced one pass, 40377 +github.tar, no source size, advanced one pass, 38884 +github.tar, no source size with dict, advanced one pass, 37995 +github.tar, long distance mode, advanced one pass, 40242 +github.tar, multithreaded, advanced one pass, 38884 +github.tar, multithreaded long distance mode, advanced one pass, 40223 github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 github.tar, explicit params, advanced one pass, 41385 -github.tar, uncompressed literals, advanced one pass, 41709 +github.tar, uncompressed literals, advanced one pass, 41562 github.tar, uncompressed literals optimal, advanced one pass, 35356 github.tar, huffman literals, advanced one pass, 39099 -github.tar, multithreaded with advanced params, advanced one pass, 41700 +github.tar, multithreaded with advanced params, advanced one pass, 41562 silesia, level -5, advanced one pass small out, 6857776 silesia, level -3, advanced one pass small out, 6504756 silesia, level -1, advanced one pass small out, 6174127 -silesia, level 0, advanced one pass small out, 4838417 +silesia, level 0, advanced one pass small out, 4832054 silesia, level 1, advanced one pass small out, 5306931 -silesia, level 3, advanced one pass small out, 4838417 -silesia, level 4, advanced one pass small out, 4775359 +silesia, level 3, advanced one pass small out, 4832054 +silesia, level 4, advanced one pass small out, 4768799 silesia, level 5 row 1, advanced one pass small out, 4663718 silesia, level 5 row 2, advanced one pass small out, 4666272 silesia, level 5, advanced one pass small out, 4663718 @@ -568,25 +568,25 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced one pass small out, 4488969 silesia, level 16, advanced one pass small out, 4356799 silesia, level 19, advanced one pass small out, 4265851 -silesia, no source size, advanced one pass small out, 4838417 -silesia, long distance mode, advanced one pass small out, 4830097 -silesia, multithreaded, advanced one pass small out, 4838949 -silesia, multithreaded long distance mode, advanced one pass small out, 4830419 +silesia, no source size, advanced one pass small out, 4832054 +silesia, long distance mode, advanced one pass small out, 4823833 +silesia, multithreaded, advanced one pass small out, 4833065 +silesia, multithreaded long distance mode, advanced one pass small out, 4824827 silesia, small window log, advanced one pass small out, 7094480 silesia, small hash log, advanced one pass small out, 6525510 silesia, small chain log, advanced one pass small out, 4912248 silesia, explicit params, advanced one pass small out, 4791219 -silesia, uncompressed literals, advanced one pass small out, 5117482 +silesia, uncompressed literals, advanced one pass small out, 5117526 silesia, uncompressed literals optimal, advanced one pass small out, 4316644 silesia, huffman literals, advanced one pass small out, 5321686 -silesia, multithreaded with advanced params, advanced one pass small out, 5117795 +silesia, multithreaded with advanced params, advanced one pass small out, 5118187 silesia.tar, level -5, advanced one pass small out, 6860782 silesia.tar, level -3, advanced one pass small out, 6507448 silesia.tar, level -1, advanced one pass small out, 6175582 -silesia.tar, level 0, advanced one pass small out, 4843429 +silesia.tar, level 0, advanced one pass small out, 4829268 silesia.tar, level 1, advanced one pass small out, 5316794 -silesia.tar, level 3, advanced one pass small out, 4843429 -silesia.tar, level 4, advanced one pass small out, 4780657 +silesia.tar, level 3, advanced one pass small out, 4829268 +silesia.tar, level 4, advanced one pass small out, 4767074 silesia.tar, level 5 row 1, advanced one pass small out, 4662847 silesia.tar, level 5 row 2, advanced one pass small out, 4666825 silesia.tar, level 5, advanced one pass small out, 4662847 @@ -602,18 +602,18 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced one pass small out, 4484732 silesia.tar, level 16, advanced one pass small out, 4355572 silesia.tar, level 19, advanced one pass small out, 4257629 -silesia.tar, no source size, advanced one pass small out, 4843429 -silesia.tar, long distance mode, advanced one pass small out, 4830453 -silesia.tar, multithreaded, advanced one pass small out, 4841902 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4834262 +silesia.tar, no source size, advanced one pass small out, 4829268 +silesia.tar, long distance mode, advanced one pass small out, 4816169 +silesia.tar, multithreaded, advanced one pass small out, 4836000 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4828167 silesia.tar, small window log, advanced one pass small out, 7100064 silesia.tar, small hash log, advanced one pass small out, 6530222 silesia.tar, small chain log, advanced one pass small out, 4915689 silesia.tar, explicit params, advanced one pass small out, 4790421 -silesia.tar, uncompressed literals, advanced one pass small out, 5116329 +silesia.tar, uncompressed literals, advanced one pass small out, 5114702 silesia.tar, uncompressed literals optimal, advanced one pass small out, 4306289 silesia.tar, huffman literals, advanced one pass small out, 5331382 -silesia.tar, multithreaded with advanced params, advanced one pass small out, 5116442 +silesia.tar, multithreaded with advanced params, advanced one pass small out, 5116579 github, level -5, advanced one pass small out, 204407 github, level -5 with dict, advanced one pass small out, 45832 github, level -3, advanced one pass small out, 193253 @@ -745,30 +745,30 @@ github.tar, level -3, advanced github.tar, level -3 with dict, advanced one pass small out, 44882 github.tar, level -1, advanced one pass small out, 42740 github.tar, level -1 with dict, advanced one pass small out, 41506 -github.tar, level 0, advanced one pass small out, 39073 -github.tar, level 0 with dict, advanced one pass small out, 38146 -github.tar, level 0 with dict dms, advanced one pass small out, 38262 -github.tar, level 0 with dict dds, advanced one pass small out, 38262 -github.tar, level 0 with dict copy, advanced one pass small out, 38146 -github.tar, level 0 with dict load, advanced one pass small out, 38107 +github.tar, level 0, advanced one pass small out, 38884 +github.tar, level 0 with dict, advanced one pass small out, 37995 +github.tar, level 0 with dict dms, advanced one pass small out, 38114 +github.tar, level 0 with dict dds, advanced one pass small out, 38114 +github.tar, level 0 with dict copy, advanced one pass small out, 37995 +github.tar, level 0 with dict load, advanced one pass small out, 37956 github.tar, level 1, advanced one pass small out, 39444 github.tar, level 1 with dict, advanced one pass small out, 38338 github.tar, level 1 with dict dms, advanced one pass small out, 38641 github.tar, level 1 with dict dds, advanced one pass small out, 38641 github.tar, level 1 with dict copy, advanced one pass small out, 38338 github.tar, level 1 with dict load, advanced one pass small out, 38592 -github.tar, level 3, advanced one pass small out, 39073 -github.tar, level 3 with dict, advanced one pass small out, 38146 -github.tar, level 3 with dict dms, advanced one pass small out, 38262 -github.tar, level 3 with dict dds, advanced one pass small out, 38262 -github.tar, level 3 with dict copy, advanced one pass small out, 38146 -github.tar, level 3 with dict load, advanced one pass small out, 38107 -github.tar, level 4, advanced one pass small out, 39068 -github.tar, level 4 with dict, advanced one pass small out, 38081 -github.tar, level 4 with dict dms, advanced one pass small out, 38135 -github.tar, level 4 with dict dds, advanced one pass small out, 38135 -github.tar, level 4 with dict copy, advanced one pass small out, 38081 -github.tar, level 4 with dict load, advanced one pass small out, 38088 +github.tar, level 3, advanced one pass small out, 38884 +github.tar, level 3 with dict, advanced one pass small out, 37995 +github.tar, level 3 with dict dms, advanced one pass small out, 38114 +github.tar, level 3 with dict dds, advanced one pass small out, 38114 +github.tar, level 3 with dict copy, advanced one pass small out, 37995 +github.tar, level 3 with dict load, advanced one pass small out, 37956 +github.tar, level 4, advanced one pass small out, 38880 +github.tar, level 4 with dict, advanced one pass small out, 37948 +github.tar, level 4 with dict dms, advanced one pass small out, 37995 +github.tar, level 4 with dict dds, advanced one pass small out, 37995 +github.tar, level 4 with dict copy, advanced one pass small out, 37948 +github.tar, level 4 with dict load, advanced one pass small out, 37927 github.tar, level 5 row 1, advanced one pass small out, 39651 github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39043 github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39069 @@ -851,26 +851,26 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass small out, 32565 github.tar, level 19 with dict copy, advanced one pass small out, 32701 github.tar, level 19 with dict load, advanced one pass small out, 32428 -github.tar, no source size, advanced one pass small out, 39073 -github.tar, no source size with dict, advanced one pass small out, 38146 -github.tar, long distance mode, advanced one pass small out, 40402 -github.tar, multithreaded, advanced one pass small out, 39067 -github.tar, multithreaded long distance mode, advanced one pass small out, 40377 +github.tar, no source size, advanced one pass small out, 38884 +github.tar, no source size with dict, advanced one pass small out, 37995 +github.tar, long distance mode, advanced one pass small out, 40242 +github.tar, multithreaded, advanced one pass small out, 38884 +github.tar, multithreaded long distance mode, advanced one pass small out, 40223 github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 github.tar, explicit params, advanced one pass small out, 41385 -github.tar, uncompressed literals, advanced one pass small out, 41709 +github.tar, uncompressed literals, advanced one pass small out, 41562 github.tar, uncompressed literals optimal, advanced one pass small out, 35356 github.tar, huffman literals, advanced one pass small out, 39099 -github.tar, multithreaded with advanced params, advanced one pass small out, 41700 +github.tar, multithreaded with advanced params, advanced one pass small out, 41562 silesia, level -5, advanced streaming, 6856699 silesia, level -3, advanced streaming, 6505694 silesia, level -1, advanced streaming, 6174139 -silesia, level 0, advanced streaming, 4839173 +silesia, level 0, advanced streaming, 4835804 silesia, level 1, advanced streaming, 5305682 -silesia, level 3, advanced streaming, 4839173 -silesia, level 4, advanced streaming, 4776074 +silesia, level 3, advanced streaming, 4835804 +silesia, level 4, advanced streaming, 4773049 silesia, level 5 row 1, advanced streaming, 4664679 silesia, level 5 row 2, advanced streaming, 4667307 silesia, level 5, advanced streaming, 4664679 @@ -886,25 +886,25 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced streaming, 4490650 silesia, level 16, advanced streaming, 4358094 silesia, level 19, advanced streaming, 4265908 -silesia, no source size, advanced streaming, 4839137 -silesia, long distance mode, advanced streaming, 4831125 -silesia, multithreaded, advanced streaming, 4838949 -silesia, multithreaded long distance mode, advanced streaming, 4830419 +silesia, no source size, advanced streaming, 4835768 +silesia, long distance mode, advanced streaming, 4827592 +silesia, multithreaded, advanced streaming, 4833065 +silesia, multithreaded long distance mode, advanced streaming, 4824827 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6525259 silesia, small chain log, advanced streaming, 4911577 silesia, explicit params, advanced streaming, 4792505 -silesia, uncompressed literals, advanced streaming, 5117625 +silesia, uncompressed literals, advanced streaming, 5116404 silesia, uncompressed literals optimal, advanced streaming, 4316533 silesia, huffman literals, advanced streaming, 5321812 -silesia, multithreaded with advanced params, advanced streaming, 5117795 +silesia, multithreaded with advanced params, advanced streaming, 5118187 silesia.tar, level -5, advanced streaming, 6857458 silesia.tar, level -3, advanced streaming, 6508562 silesia.tar, level -1, advanced streaming, 6178057 -silesia.tar, level 0, advanced streaming, 4849720 +silesia.tar, level 0, advanced streaming, 4846783 silesia.tar, level 1, advanced streaming, 5311452 -silesia.tar, level 3, advanced streaming, 4849720 -silesia.tar, level 4, advanced streaming, 4787534 +silesia.tar, level 3, advanced streaming, 4846783 +silesia.tar, level 4, advanced streaming, 4785332 silesia.tar, level 5 row 1, advanced streaming, 4664523 silesia.tar, level 5 row 2, advanced streaming, 4668292 silesia.tar, level 5, advanced streaming, 4664523 @@ -920,18 +920,18 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced streaming, 4486652 silesia.tar, level 16, advanced streaming, 4358029 silesia.tar, level 19, advanced streaming, 4258228 -silesia.tar, no source size, advanced streaming, 4849716 -silesia.tar, long distance mode, advanced streaming, 4829339 -silesia.tar, multithreaded, advanced streaming, 4841902 -silesia.tar, multithreaded long distance mode, advanced streaming, 4834262 +silesia.tar, no source size, advanced streaming, 4846779 +silesia.tar, long distance mode, advanced streaming, 4826177 +silesia.tar, multithreaded, advanced streaming, 4836000 +silesia.tar, multithreaded long distance mode, advanced streaming, 4828167 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529503 silesia.tar, small chain log, advanced streaming, 4915956 silesia.tar, explicit params, advanced streaming, 4791739 -silesia.tar, uncompressed literals, advanced streaming, 5124811 +silesia.tar, uncompressed literals, advanced streaming, 5123274 silesia.tar, uncompressed literals optimal, advanced streaming, 4306968 silesia.tar, huffman literals, advanced streaming, 5326278 -silesia.tar, multithreaded with advanced params, advanced streaming, 5116442 +silesia.tar, multithreaded with advanced params, advanced streaming, 5116579 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 github, level -3, advanced streaming, 193253 @@ -1063,30 +1063,30 @@ github.tar, level -3, advanced github.tar, level -3 with dict, advanced streaming, 44973 github.tar, level -1, advanced streaming, 42777 github.tar, level -1 with dict, advanced streaming, 41603 -github.tar, level 0, advanced streaming, 39249 -github.tar, level 0 with dict, advanced streaming, 38309 -github.tar, level 0 with dict dms, advanced streaming, 38445 -github.tar, level 0 with dict dds, advanced streaming, 38445 -github.tar, level 0 with dict copy, advanced streaming, 38309 -github.tar, level 0 with dict load, advanced streaming, 38281 +github.tar, level 0, advanced streaming, 38884 +github.tar, level 0 with dict, advanced streaming, 37995 +github.tar, level 0 with dict dms, advanced streaming, 38114 +github.tar, level 0 with dict dds, advanced streaming, 38114 +github.tar, level 0 with dict copy, advanced streaming, 37995 +github.tar, level 0 with dict load, advanced streaming, 37956 github.tar, level 1, advanced streaming, 39550 github.tar, level 1 with dict, advanced streaming, 38502 github.tar, level 1 with dict dms, advanced streaming, 38770 github.tar, level 1 with dict dds, advanced streaming, 38770 github.tar, level 1 with dict copy, advanced streaming, 38502 github.tar, level 1 with dict load, advanced streaming, 38716 -github.tar, level 3, advanced streaming, 39249 -github.tar, level 3 with dict, advanced streaming, 38309 -github.tar, level 3 with dict dms, advanced streaming, 38445 -github.tar, level 3 with dict dds, advanced streaming, 38445 -github.tar, level 3 with dict copy, advanced streaming, 38309 -github.tar, level 3 with dict load, advanced streaming, 38281 -github.tar, level 4, advanced streaming, 39247 -github.tar, level 4 with dict, advanced streaming, 38270 -github.tar, level 4 with dict dms, advanced streaming, 38317 -github.tar, level 4 with dict dds, advanced streaming, 38317 -github.tar, level 4 with dict copy, advanced streaming, 38270 -github.tar, level 4 with dict load, advanced streaming, 38259 +github.tar, level 3, advanced streaming, 38884 +github.tar, level 3 with dict, advanced streaming, 37995 +github.tar, level 3 with dict dms, advanced streaming, 38114 +github.tar, level 3 with dict dds, advanced streaming, 38114 +github.tar, level 3 with dict copy, advanced streaming, 37995 +github.tar, level 3 with dict load, advanced streaming, 37956 +github.tar, level 4, advanced streaming, 38880 +github.tar, level 4 with dict, advanced streaming, 37948 +github.tar, level 4 with dict dms, advanced streaming, 37995 +github.tar, level 4 with dict dds, advanced streaming, 37995 +github.tar, level 4 with dict copy, advanced streaming, 37948 +github.tar, level 4 with dict load, advanced streaming, 37927 github.tar, level 5 row 1, advanced streaming, 39651 github.tar, level 5 row 1 with dict dms, advanced streaming, 39043 github.tar, level 5 row 1 with dict dds, advanced streaming, 39069 @@ -1169,26 +1169,26 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced streaming, 32565 github.tar, level 19 with dict copy, advanced streaming, 32701 github.tar, level 19 with dict load, advanced streaming, 32428 -github.tar, no source size, advanced streaming, 39246 -github.tar, no source size with dict, advanced streaming, 38442 -github.tar, long distance mode, advanced streaming, 40569 -github.tar, multithreaded, advanced streaming, 39067 -github.tar, multithreaded long distance mode, advanced streaming, 40377 +github.tar, no source size, advanced streaming, 38881 +github.tar, no source size with dict, advanced streaming, 38111 +github.tar, long distance mode, advanced streaming, 40242 +github.tar, multithreaded, advanced streaming, 38884 +github.tar, multithreaded long distance mode, advanced streaming, 40223 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 github.tar, explicit params, advanced streaming, 41385 -github.tar, uncompressed literals, advanced streaming, 41784 +github.tar, uncompressed literals, advanced streaming, 41562 github.tar, uncompressed literals optimal, advanced streaming, 35356 github.tar, huffman literals, advanced streaming, 39226 -github.tar, multithreaded with advanced params, advanced streaming, 41700 +github.tar, multithreaded with advanced params, advanced streaming, 41562 silesia, level -5, old streaming, 6856699 silesia, level -3, old streaming, 6505694 silesia, level -1, old streaming, 6174139 -silesia, level 0, old streaming, 4839173 +silesia, level 0, old streaming, 4835804 silesia, level 1, old streaming, 5305682 -silesia, level 3, old streaming, 4839173 -silesia, level 4, old streaming, 4776074 +silesia, level 3, old streaming, 4835804 +silesia, level 4, old streaming, 4773049 silesia, level 5, old streaming, 4664679 silesia, level 6, old streaming, 4601116 silesia, level 7, old streaming, 4567082 @@ -1196,17 +1196,17 @@ silesia, level 9, old stre silesia, level 13, old streaming, 4490650 silesia, level 16, old streaming, 4358094 silesia, level 19, old streaming, 4265908 -silesia, no source size, old streaming, 4839137 -silesia, uncompressed literals, old streaming, 4839173 +silesia, no source size, old streaming, 4835768 +silesia, uncompressed literals, old streaming, 4835804 silesia, uncompressed literals optimal, old streaming, 4265908 silesia, huffman literals, old streaming, 6174139 silesia.tar, level -5, old streaming, 6857458 silesia.tar, level -3, old streaming, 6508562 silesia.tar, level -1, old streaming, 6178057 -silesia.tar, level 0, old streaming, 4849720 +silesia.tar, level 0, old streaming, 4846783 silesia.tar, level 1, old streaming, 5311452 -silesia.tar, level 3, old streaming, 4849720 -silesia.tar, level 4, old streaming, 4787534 +silesia.tar, level 3, old streaming, 4846783 +silesia.tar, level 4, old streaming, 4785332 silesia.tar, level 5, old streaming, 4664523 silesia.tar, level 6, old streaming, 4599420 silesia.tar, level 7, old streaming, 4565332 @@ -1214,8 +1214,8 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming, 4486652 silesia.tar, level 16, old streaming, 4358029 silesia.tar, level 19, old streaming, 4258228 -silesia.tar, no source size, old streaming, 4849716 -silesia.tar, uncompressed literals, old streaming, 4849720 +silesia.tar, no source size, old streaming, 4846779 +silesia.tar, uncompressed literals, old streaming, 4846783 silesia.tar, uncompressed literals optimal, old streaming, 4258228 silesia.tar, huffman literals, old streaming, 6178057 github, level -5, old streaming, 204407 @@ -1257,14 +1257,14 @@ github.tar, level -3, old stre github.tar, level -3 with dict, old streaming, 44973 github.tar, level -1, old streaming, 42777 github.tar, level -1 with dict, old streaming, 41603 -github.tar, level 0, old streaming, 39249 -github.tar, level 0 with dict, old streaming, 38309 +github.tar, level 0, old streaming, 38884 +github.tar, level 0 with dict, old streaming, 37995 github.tar, level 1, old streaming, 39550 github.tar, level 1 with dict, old streaming, 38502 -github.tar, level 3, old streaming, 39249 -github.tar, level 3 with dict, old streaming, 38309 -github.tar, level 4, old streaming, 39247 -github.tar, level 4 with dict, old streaming, 38270 +github.tar, level 3, old streaming, 38884 +github.tar, level 3 with dict, old streaming, 37995 +github.tar, level 4, old streaming, 38880 +github.tar, level 4 with dict, old streaming, 37948 github.tar, level 5, old streaming, 39651 github.tar, level 5 with dict, old streaming, 39145 github.tar, level 6, old streaming, 39282 @@ -1279,18 +1279,18 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming, 33375 github.tar, level 19, old streaming, 32262 github.tar, level 19 with dict, old streaming, 32701 -github.tar, no source size, old streaming, 39246 -github.tar, no source size with dict, old streaming, 38442 -github.tar, uncompressed literals, old streaming, 39249 +github.tar, no source size, old streaming, 38881 +github.tar, no source size with dict, old streaming, 38111 +github.tar, uncompressed literals, old streaming, 38884 github.tar, uncompressed literals optimal, old streaming, 32262 github.tar, huffman literals, old streaming, 42777 silesia, level -5, old streaming advanced, 6856699 silesia, level -3, old streaming advanced, 6505694 silesia, level -1, old streaming advanced, 6174139 -silesia, level 0, old streaming advanced, 4839173 +silesia, level 0, old streaming advanced, 4835804 silesia, level 1, old streaming advanced, 5305682 -silesia, level 3, old streaming advanced, 4839173 -silesia, level 4, old streaming advanced, 4776074 +silesia, level 3, old streaming advanced, 4835804 +silesia, level 4, old streaming advanced, 4773049 silesia, level 5, old streaming advanced, 4664679 silesia, level 6, old streaming advanced, 4601116 silesia, level 7, old streaming advanced, 4567082 @@ -1298,25 +1298,25 @@ silesia, level 9, old stre silesia, level 13, old streaming advanced, 4490650 silesia, level 16, old streaming advanced, 4358094 silesia, level 19, old streaming advanced, 4265908 -silesia, no source size, old streaming advanced, 4839137 -silesia, long distance mode, old streaming advanced, 4839173 -silesia, multithreaded, old streaming advanced, 4839173 -silesia, multithreaded long distance mode, old streaming advanced, 4839173 +silesia, no source size, old streaming advanced, 4835768 +silesia, long distance mode, old streaming advanced, 4835804 +silesia, multithreaded, old streaming advanced, 4835804 +silesia, multithreaded long distance mode, old streaming advanced, 4835804 silesia, small window log, old streaming advanced, 7110591 silesia, small hash log, old streaming advanced, 6525259 silesia, small chain log, old streaming advanced, 4911577 silesia, explicit params, old streaming advanced, 4792505 -silesia, uncompressed literals, old streaming advanced, 4839173 +silesia, uncompressed literals, old streaming advanced, 4835804 silesia, uncompressed literals optimal, old streaming advanced, 4265908 silesia, huffman literals, old streaming advanced, 6174139 -silesia, multithreaded with advanced params, old streaming advanced, 4839173 +silesia, multithreaded with advanced params, old streaming advanced, 4835804 silesia.tar, level -5, old streaming advanced, 6857458 silesia.tar, level -3, old streaming advanced, 6508562 silesia.tar, level -1, old streaming advanced, 6178057 -silesia.tar, level 0, old streaming advanced, 4849720 +silesia.tar, level 0, old streaming advanced, 4846783 silesia.tar, level 1, old streaming advanced, 5311452 -silesia.tar, level 3, old streaming advanced, 4849720 -silesia.tar, level 4, old streaming advanced, 4787534 +silesia.tar, level 3, old streaming advanced, 4846783 +silesia.tar, level 4, old streaming advanced, 4785332 silesia.tar, level 5, old streaming advanced, 4664523 silesia.tar, level 6, old streaming advanced, 4599420 silesia.tar, level 7, old streaming advanced, 4565332 @@ -1324,18 +1324,18 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming advanced, 4486652 silesia.tar, level 16, old streaming advanced, 4358029 silesia.tar, level 19, old streaming advanced, 4258228 -silesia.tar, no source size, old streaming advanced, 4849716 -silesia.tar, long distance mode, old streaming advanced, 4849720 -silesia.tar, multithreaded, old streaming advanced, 4849720 -silesia.tar, multithreaded long distance mode, old streaming advanced, 4849720 +silesia.tar, no source size, old streaming advanced, 4846779 +silesia.tar, long distance mode, old streaming advanced, 4846783 +silesia.tar, multithreaded, old streaming advanced, 4846783 +silesia.tar, multithreaded long distance mode, old streaming advanced, 4846783 silesia.tar, small window log, old streaming advanced, 7117027 silesia.tar, small hash log, old streaming advanced, 6529503 silesia.tar, small chain log, old streaming advanced, 4915956 silesia.tar, explicit params, old streaming advanced, 4791739 -silesia.tar, uncompressed literals, old streaming advanced, 4849720 +silesia.tar, uncompressed literals, old streaming advanced, 4846783 silesia.tar, uncompressed literals optimal, old streaming advanced, 4258228 silesia.tar, huffman literals, old streaming advanced, 6178057 -silesia.tar, multithreaded with advanced params, old streaming advanced, 4849720 +silesia.tar, multithreaded with advanced params, old streaming advanced, 4846783 github, level -5, old streaming advanced, 213265 github, level -5 with dict, old streaming advanced, 46708 github, level -3, old streaming advanced, 196126 @@ -1383,14 +1383,14 @@ github.tar, level -3, old stre github.tar, level -3 with dict, old streaming advanced, 45211 github.tar, level -1, old streaming advanced, 42777 github.tar, level -1 with dict, old streaming advanced, 41865 -github.tar, level 0, old streaming advanced, 39249 -github.tar, level 0 with dict, old streaming advanced, 38327 +github.tar, level 0, old streaming advanced, 38884 +github.tar, level 0 with dict, old streaming advanced, 38013 github.tar, level 1, old streaming advanced, 39550 github.tar, level 1 with dict, old streaming advanced, 38714 -github.tar, level 3, old streaming advanced, 39249 -github.tar, level 3 with dict, old streaming advanced, 38327 -github.tar, level 4, old streaming advanced, 39247 -github.tar, level 4 with dict, old streaming advanced, 38382 +github.tar, level 3, old streaming advanced, 38884 +github.tar, level 3 with dict, old streaming advanced, 38013 +github.tar, level 4, old streaming advanced, 38880 +github.tar, level 4 with dict, old streaming advanced, 38063 github.tar, level 5, old streaming advanced, 39651 github.tar, level 5 with dict, old streaming advanced, 39018 github.tar, level 6, old streaming advanced, 39282 @@ -1405,19 +1405,19 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming advanced, 38578 github.tar, level 19, old streaming advanced, 32262 github.tar, level 19 with dict, old streaming advanced, 32678 -github.tar, no source size, old streaming advanced, 39246 -github.tar, no source size with dict, old streaming advanced, 38399 -github.tar, long distance mode, old streaming advanced, 39249 -github.tar, multithreaded, old streaming advanced, 39249 -github.tar, multithreaded long distance mode, old streaming advanced, 39249 +github.tar, no source size, old streaming advanced, 38881 +github.tar, no source size with dict, old streaming advanced, 38076 +github.tar, long distance mode, old streaming advanced, 38884 +github.tar, multithreaded, old streaming advanced, 38884 +github.tar, multithreaded long distance mode, old streaming advanced, 38884 github.tar, small window log, old streaming advanced, 199556 github.tar, small hash log, old streaming advanced, 129870 github.tar, small chain log, old streaming advanced, 41669 github.tar, explicit params, old streaming advanced, 41385 -github.tar, uncompressed literals, old streaming advanced, 39249 +github.tar, uncompressed literals, old streaming advanced, 38884 github.tar, uncompressed literals optimal, old streaming advanced, 32262 github.tar, huffman literals, old streaming advanced, 42777 -github.tar, multithreaded with advanced params, old streaming advanced, 39249 +github.tar, multithreaded with advanced params, old streaming advanced, 38884 github, level -5 with dict, old streaming cdict, 45832 github, level -3 with dict, old streaming cdict, 44671 github, level -1 with dict, old streaming cdict, 41825 @@ -1436,10 +1436,10 @@ github, no source size with dict, old stre github.tar, level -5 with dict, old streaming cdict, 51512 github.tar, level -3 with dict, old streaming cdict, 45379 github.tar, level -1 with dict, old streaming cdict, 42084 -github.tar, level 0 with dict, old streaming cdict, 38281 +github.tar, level 0 with dict, old streaming cdict, 37956 github.tar, level 1 with dict, old streaming cdict, 38716 -github.tar, level 3 with dict, old streaming cdict, 38281 -github.tar, level 4 with dict, old streaming cdict, 38259 +github.tar, level 3 with dict, old streaming cdict, 37956 +github.tar, level 4 with dict, old streaming cdict, 37927 github.tar, level 5 with dict, old streaming cdict, 39000 github.tar, level 6 with dict, old streaming cdict, 38647 github.tar, level 7 with dict, old streaming cdict, 37286 @@ -1447,7 +1447,7 @@ github.tar, level 9 with dict, old stre github.tar, level 13 with dict, old streaming cdict, 36010 github.tar, level 16 with dict, old streaming cdict, 39081 github.tar, level 19 with dict, old streaming cdict, 32428 -github.tar, no source size with dict, old streaming cdict, 38442 +github.tar, no source size with dict, old streaming cdict, 38111 github, level -5 with dict, old streaming advanced cdict, 46708 github, level -3 with dict, old streaming advanced cdict, 45476 github, level -1 with dict, old streaming advanced cdict, 42060 @@ -1466,10 +1466,10 @@ github, no source size with dict, old stre github.tar, level -5 with dict, old streaming advanced cdict, 51019 github.tar, level -3 with dict, old streaming advanced cdict, 45149 github.tar, level -1 with dict, old streaming advanced cdict, 41694 -github.tar, level 0 with dict, old streaming advanced cdict, 38327 +github.tar, level 0 with dict, old streaming advanced cdict, 38013 github.tar, level 1 with dict, old streaming advanced cdict, 38513 -github.tar, level 3 with dict, old streaming advanced cdict, 38327 -github.tar, level 4 with dict, old streaming advanced cdict, 38382 +github.tar, level 3 with dict, old streaming advanced cdict, 38013 +github.tar, level 4 with dict, old streaming advanced cdict, 38063 github.tar, level 5 with dict, old streaming advanced cdict, 39018 github.tar, level 6 with dict, old streaming advanced cdict, 38635 github.tar, level 7 with dict, old streaming advanced cdict, 37264 @@ -1477,4 +1477,4 @@ github.tar, level 9 with dict, old stre github.tar, level 13 with dict, old streaming advanced cdict, 35807 github.tar, level 16 with dict, old streaming advanced cdict, 38578 github.tar, level 19 with dict, old streaming advanced cdict, 32678 -github.tar, no source size with dict, old streaming advanced cdict, 38399 +github.tar, no source size with dict, old streaming advanced cdict, 38076 From e557abc8a0380b095b14623ca7c4105a38fdb981 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 15:57:29 -0700 Subject: [PATCH 153/405] new block splitting variant _fromBorders less precise but still suitable for `fast` strategy. --- lib/compress/hist.c | 10 +++++++ lib/compress/hist.h | 7 +++++ lib/compress/zstd_compress.c | 22 ++++----------- lib/compress/zstd_preSplit.c | 53 ++++++++++++++++++++++++++++++++---- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/lib/compress/hist.c b/lib/compress/hist.c index e2fb431f0..4ccf9a90a 100644 --- a/lib/compress/hist.c +++ b/lib/compress/hist.c @@ -26,6 +26,16 @@ unsigned HIST_isError(size_t code) { return ERR_isError(code); } /*-************************************************************** * Histogram functions ****************************************************************/ +void HIST_add(unsigned* count, const void* src, size_t srcSize) +{ + const BYTE* ip = (const BYTE*)src; + const BYTE* const end = ip + srcSize; + + while (ip= ZSTD_btopt) - return ZSTD_splitBlock(src, blockSizeMax, 3, cctx->tmpWorkspace, cctx->tmpWkspSize); - if (strat >= ZSTD_lazy2) - return ZSTD_splitBlock(src, blockSizeMax, 2, cctx->tmpWorkspace, cctx->tmpWkspSize); - if (strat >= ZSTD_greedy) - return ZSTD_splitBlock(src, blockSizeMax, 1, cctx->tmpWorkspace, cctx->tmpWkspSize); - if (strat >= ZSTD_dfast) - return ZSTD_splitBlock(src, blockSizeMax, 0, cctx->tmpWorkspace, cctx->tmpWkspSize); - /* blind split strategy - * heuristic value, tested as being "generally better". - * no cpu cost, but can over-split homegeneous data. - */ - return 92 KB; + * select a variant among multiple gradual speed/accuracy tradeoffs */ + return ZSTD_splitBlock(src, blockSizeMax, splitLevels[strat], cctx->tmpWorkspace, cctx->tmpWkspSize); } /*! ZSTD_compress_frameChunk() : diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 3f6edb612..d25773950 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -12,6 +12,7 @@ #include "../common/mem.h" /* S64 */ #include "../common/zstd_deps.h" /* ZSTD_memset */ #include "../common/zstd_internal.h" /* ZSTD_STATIC_ASSERT */ +#include "hist.h" /* HIST_add */ #include "zstd_preSplit.h" @@ -77,10 +78,10 @@ typedef void (*RecordEvents_f)(Fingerprint* fp, const void* src, size_t srcSize) #define FP_RECORD(_rate) ZSTD_recordFingerprint_##_rate -#define ZSTD_GEN_RECORD_FINGERPRINT(_rate, _hSize) \ +#define ZSTD_GEN_RECORD_FINGERPRINT(_rate, _hSize) \ static void FP_RECORD(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ - { \ - recordFingerprint_generic(fp, src, srcSize, _rate, _hSize); \ + { \ + recordFingerprint_generic(fp, src, srcSize, _rate, _hSize); \ } ZSTD_GEN_RECORD_FINGERPRINT(1, 10) @@ -185,10 +186,52 @@ static size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize, (void)flushEvents; (void)removeEvents; } +/* ZSTD_splitBlock_fromBorders(): very fast strategy : + * compare fingerprint from beginning and end of the block, + * derive from their difference if it's preferable to split in the middle, + * repeat the process a second time, for finer grained decision. + * 3 times did not brought improvements, so I stopped at 2. + * Benefits are good enough for a cheap heuristic. + * More accurate splitting saves more, but speed impact is also more perceptible. + * For better accuracy, use more elaborate variant *_byChunks. + */ +static size_t ZSTD_splitBlock_fromBorders(const void* blockStart, size_t blockSize, + void* workspace, size_t wkspSize) +{ +#define SEGMENT_SIZE 512 + FPStats* const fpstats = (FPStats*)workspace; + Fingerprint* middleEvents = (Fingerprint*)(void*)((char*)workspace + 512 * sizeof(unsigned)); + assert(blockSize == (128 << 10)); + assert(workspace != NULL); + assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0); + ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats)); + assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; + + initStats(fpstats); + HIST_add(fpstats->pastEvents.events, blockStart, SEGMENT_SIZE); + HIST_add(fpstats->newEvents.events, (const char*)blockStart + blockSize - SEGMENT_SIZE, SEGMENT_SIZE); + fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents = SEGMENT_SIZE; + if (!compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, 0, 8)) + return blockSize; + + HIST_add(middleEvents->events, (const char*)blockStart + blockSize/2 - SEGMENT_SIZE/2, SEGMENT_SIZE); + middleEvents->nbEvents = SEGMENT_SIZE; + { U64 const distFromBegin = fpDistance(&fpstats->pastEvents, middleEvents, 8); + U64 const distFromEnd = fpDistance(&fpstats->newEvents, middleEvents, 8); + U64 const minDistance = SEGMENT_SIZE * SEGMENT_SIZE / 3; + if (abs64((S64)distFromBegin - (S64)distFromEnd) < minDistance) + return 64 KB; + return (distFromBegin > distFromEnd) ? 32 KB : 96 KB; + } +} + size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, int level, void* workspace, size_t wkspSize) { - assert(0<=level && level<=3); - return ZSTD_splitBlock_byChunks(blockStart, blockSize, level, workspace, wkspSize); + assert(0<=level && level<=4); + if (level == 0) + return ZSTD_splitBlock_fromBorders(blockStart, blockSize, workspace, wkspSize); + /* level >= 1*/ + return ZSTD_splitBlock_byChunks(blockStart, blockSize, level-1, workspace, wkspSize); } From 5b4ce643f03a2cc2c6f4e10dca3332c058f165d5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 25 Oct 2024 16:25:02 -0700 Subject: [PATCH 154/405] update ZSTD_splitBlock() documentation --- lib/compress/zstd_preSplit.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 07d7d4ef5..d606a52b5 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -19,14 +19,16 @@ extern "C" { #define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 -/* @level must be a value between 0 and 3. - * higher levels spend more energy to find block boundaries - * @workspace must be aligned on 8-bytes boundaries +/* ZSTD_splitBlock(): + * @level must be a value between 0 and 4. + * higher levels spend more energy to detect block boundaries. + * @workspace must be aligned for size_t. * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE - * note2: - * for the time being, this function only accepts full 128 KB blocks, - * therefore @blockSizeMax must be == 128 KB. - * This could be extended to smaller sizes in the future. + * note: + * For the time being, this function only accepts full 128 KB blocks. + * Therefore, @blockSize must be == 128 KB. + * While this could be extended to smaller sizes in the future, + * it is not yet clear if this would be useful. TBD. */ size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, int level, From 4e1a87976f5286b60748aece532e05f4515721c0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 25 Oct 2024 16:33:00 -0700 Subject: [PATCH 155/405] update regression results --- tests/regression/results.csv | 298 +++++++++++++++++------------------ 1 file changed, 149 insertions(+), 149 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 0b1a79b85..94d113578 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -1,9 +1,9 @@ Data, Config, Method, Total compressed size -silesia.tar, level -5, compress simple, 6860782 -silesia.tar, level -3, compress simple, 6507448 -silesia.tar, level -1, compress simple, 6175582 +silesia.tar, level -5, compress simple, 6858730 +silesia.tar, level -3, compress simple, 6502944 +silesia.tar, level -1, compress simple, 6175652 silesia.tar, level 0, compress simple, 4829268 -silesia.tar, level 1, compress simple, 5316794 +silesia.tar, level 1, compress simple, 5307443 silesia.tar, level 3, compress simple, 4829268 silesia.tar, level 4, compress simple, 4767074 silesia.tar, level 5, compress simple, 4662847 @@ -15,12 +15,12 @@ silesia.tar, level 16, compress silesia.tar, level 19, compress simple, 4257629 silesia.tar, uncompressed literals, compress simple, 4829268 silesia.tar, uncompressed literals optimal, compress simple, 4257629 -silesia.tar, huffman literals, compress simple, 6175582 -github.tar, level -5, compress simple, 52320 -github.tar, level -3, compress simple, 45823 -github.tar, level -1, compress simple, 42740 +silesia.tar, huffman literals, compress simple, 6175652 +github.tar, level -5, compress simple, 52173 +github.tar, level -3, compress simple, 45783 +github.tar, level -1, compress simple, 42606 github.tar, level 0, compress simple, 38884 -github.tar, level 1, compress simple, 39444 +github.tar, level 1, compress simple, 39200 github.tar, level 3, compress simple, 38884 github.tar, level 4, compress simple, 38880 github.tar, level 5, compress simple, 39651 @@ -32,12 +32,12 @@ github.tar, level 16, compress github.tar, level 19, compress simple, 32262 github.tar, uncompressed literals, compress simple, 38884 github.tar, uncompressed literals optimal, compress simple, 32262 -github.tar, huffman literals, compress simple, 42740 -silesia, level -5, compress cctx, 6857776 -silesia, level -3, compress cctx, 6504756 -silesia, level -1, compress cctx, 6174127 +github.tar, huffman literals, compress simple, 42606 +silesia, level -5, compress cctx, 6854688 +silesia, level -3, compress cctx, 6502839 +silesia, level -1, compress cctx, 6173625 silesia, level 0, compress cctx, 4832054 -silesia, level 1, compress cctx, 5306931 +silesia, level 1, compress cctx, 5304296 silesia, level 3, compress cctx, 4832054 silesia, level 4, compress cctx, 4768799 silesia, level 5, compress cctx, 4663718 @@ -56,7 +56,7 @@ silesia, small chain log, compress silesia, explicit params, compress cctx, 4789676 silesia, uncompressed literals, compress cctx, 4832054 silesia, uncompressed literals optimal, compress cctx, 4265851 -silesia, huffman literals, compress cctx, 6174127 +silesia, huffman literals, compress cctx, 6173625 silesia, multithreaded with advanced params, compress cctx, 4832054 github, level -5, compress cctx, 204407 github, level -5 with dict, compress cctx, 47581 @@ -97,11 +97,11 @@ github, uncompressed literals, compress github, uncompressed literals optimal, compress cctx, 132879 github, huffman literals, compress cctx, 175468 github, multithreaded with advanced params, compress cctx, 141069 -silesia, level -5, zstdcli, 6856073 -silesia, level -3, zstdcli, 6505580 -silesia, level -1, zstdcli, 6172649 +silesia, level -5, zstdcli, 6854509 +silesia, level -3, zstdcli, 6502336 +silesia, level -1, zstdcli, 6171366 silesia, level 0, zstdcli, 4833113 -silesia, level 1, zstdcli, 5306179 +silesia, level 1, zstdcli, 5302161 silesia, level 3, zstdcli, 4833113 silesia, level 4, zstdcli, 4770061 silesia, level 5, zstdcli, 4663332 @@ -120,13 +120,13 @@ silesia, small chain log, zstdcli, silesia, explicit params, zstdcli, 4790803 silesia, uncompressed literals, zstdcli, 5118235 silesia, uncompressed literals optimal, zstdcli, 4316761 -silesia, huffman literals, zstdcli, 5320793 +silesia, huffman literals, zstdcli, 5316827 silesia, multithreaded with advanced params, zstdcli, 5118235 -silesia.tar, level -5, zstdcli, 6860173 -silesia.tar, level -3, zstdcli, 6507196 -silesia.tar, level -1, zstdcli, 6177719 +silesia.tar, level -5, zstdcli, 6859945 +silesia.tar, level -3, zstdcli, 6504296 +silesia.tar, level -1, zstdcli, 6176520 silesia.tar, level 0, zstdcli, 4836004 -silesia.tar, level 1, zstdcli, 5313917 +silesia.tar, level 1, zstdcli, 5309074 silesia.tar, level 3, zstdcli, 4836004 silesia.tar, level 4, zstdcli, 4774061 silesia.tar, level 5, zstdcli, 4667310 @@ -146,7 +146,7 @@ silesia.tar, small chain log, zstdcli, silesia.tar, explicit params, zstdcli, 4808370 silesia.tar, uncompressed literals, zstdcli, 5116583 silesia.tar, uncompressed literals optimal, zstdcli, 4306520 -silesia.tar, huffman literals, zstdcli, 5326463 +silesia.tar, huffman literals, zstdcli, 5324019 silesia.tar, multithreaded with advanced params, zstdcli, 5116583 github, level -5, zstdcli, 206407 github, level -5 with dict, zstdcli, 47832 @@ -187,16 +187,16 @@ github, uncompressed literals, zstdcli, github, uncompressed literals optimal, zstdcli, 154667 github, huffman literals, zstdcli, 144365 github, multithreaded with advanced params, zstdcli, 167909 -github.tar, level -5, zstdcli, 52308 -github.tar, level -5 with dict, zstdcli, 51318 -github.tar, level -3, zstdcli, 45815 -github.tar, level -3 with dict, zstdcli, 44883 -github.tar, level -1, zstdcli, 42688 -github.tar, level -1 with dict, zstdcli, 41510 +github.tar, level -5, zstdcli, 52231 +github.tar, level -5 with dict, zstdcli, 51249 +github.tar, level -3, zstdcli, 45778 +github.tar, level -3 with dict, zstdcli, 44847 +github.tar, level -1, zstdcli, 42680 +github.tar, level -1 with dict, zstdcli, 41486 github.tar, level 0, zstdcli, 38888 github.tar, level 0 with dict, zstdcli, 37999 -github.tar, level 1, zstdcli, 39404 -github.tar, level 1 with dict, zstdcli, 38320 +github.tar, level 1, zstdcli, 39340 +github.tar, level 1 with dict, zstdcli, 38230 github.tar, level 3, zstdcli, 38888 github.tar, level 3 with dict, zstdcli, 37999 github.tar, level 4, zstdcli, 38884 @@ -226,13 +226,13 @@ github.tar, small chain log, zstdcli, github.tar, explicit params, zstdcli, 41385 github.tar, uncompressed literals, zstdcli, 41566 github.tar, uncompressed literals optimal, zstdcli, 35360 -github.tar, huffman literals, zstdcli, 39046 +github.tar, huffman literals, zstdcli, 38989 github.tar, multithreaded with advanced params, zstdcli, 41566 -silesia, level -5, advanced one pass, 6857776 -silesia, level -3, advanced one pass, 6504756 -silesia, level -1, advanced one pass, 6174127 +silesia, level -5, advanced one pass, 6854688 +silesia, level -3, advanced one pass, 6502839 +silesia, level -1, advanced one pass, 6173625 silesia, level 0, advanced one pass, 4832054 -silesia, level 1, advanced one pass, 5306931 +silesia, level 1, advanced one pass, 5304296 silesia, level 3, advanced one pass, 4832054 silesia, level 4, advanced one pass, 4768799 silesia, level 5 row 1, advanced one pass, 4663718 @@ -260,13 +260,13 @@ silesia, small chain log, advanced silesia, explicit params, advanced one pass, 4791219 silesia, uncompressed literals, advanced one pass, 5117526 silesia, uncompressed literals optimal, advanced one pass, 4316644 -silesia, huffman literals, advanced one pass, 5321686 +silesia, huffman literals, advanced one pass, 5319104 silesia, multithreaded with advanced params, advanced one pass, 5118187 -silesia.tar, level -5, advanced one pass, 6860782 -silesia.tar, level -3, advanced one pass, 6507448 -silesia.tar, level -1, advanced one pass, 6175582 +silesia.tar, level -5, advanced one pass, 6858730 +silesia.tar, level -3, advanced one pass, 6502944 +silesia.tar, level -1, advanced one pass, 6175652 silesia.tar, level 0, advanced one pass, 4829268 -silesia.tar, level 1, advanced one pass, 5316794 +silesia.tar, level 1, advanced one pass, 5307443 silesia.tar, level 3, advanced one pass, 4829268 silesia.tar, level 4, advanced one pass, 4767074 silesia.tar, level 5 row 1, advanced one pass, 4662847 @@ -294,7 +294,7 @@ silesia.tar, small chain log, advanced silesia.tar, explicit params, advanced one pass, 4790421 silesia.tar, uncompressed literals, advanced one pass, 5114702 silesia.tar, uncompressed literals optimal, advanced one pass, 4306289 -silesia.tar, huffman literals, advanced one pass, 5331382 +silesia.tar, huffman literals, advanced one pass, 5323421 silesia.tar, multithreaded with advanced params, advanced one pass, 5116579 github, level -5, advanced one pass, 204407 github, level -5 with dict, advanced one pass, 45832 @@ -421,24 +421,24 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced one pass, 152667 github, huffman literals, advanced one pass, 142365 github, multithreaded with advanced params, advanced one pass, 165909 -github.tar, level -5, advanced one pass, 52320 -github.tar, level -5 with dict, advanced one pass, 51321 -github.tar, level -3, advanced one pass, 45823 -github.tar, level -3 with dict, advanced one pass, 44882 -github.tar, level -1, advanced one pass, 42740 -github.tar, level -1 with dict, advanced one pass, 41506 +github.tar, level -5, advanced one pass, 52173 +github.tar, level -5 with dict, advanced one pass, 51161 +github.tar, level -3, advanced one pass, 45783 +github.tar, level -3 with dict, advanced one pass, 44768 +github.tar, level -1, advanced one pass, 42606 +github.tar, level -1 with dict, advanced one pass, 41397 github.tar, level 0, advanced one pass, 38884 github.tar, level 0 with dict, advanced one pass, 37995 github.tar, level 0 with dict dms, advanced one pass, 38114 github.tar, level 0 with dict dds, advanced one pass, 38114 github.tar, level 0 with dict copy, advanced one pass, 37995 github.tar, level 0 with dict load, advanced one pass, 37956 -github.tar, level 1, advanced one pass, 39444 -github.tar, level 1 with dict, advanced one pass, 38338 -github.tar, level 1 with dict dms, advanced one pass, 38641 -github.tar, level 1 with dict dds, advanced one pass, 38641 -github.tar, level 1 with dict copy, advanced one pass, 38338 -github.tar, level 1 with dict load, advanced one pass, 38592 +github.tar, level 1, advanced one pass, 39200 +github.tar, level 1 with dict, advanced one pass, 38189 +github.tar, level 1 with dict dms, advanced one pass, 38398 +github.tar, level 1 with dict dds, advanced one pass, 38398 +github.tar, level 1 with dict copy, advanced one pass, 38189 +github.tar, level 1 with dict load, advanced one pass, 38393 github.tar, level 3, advanced one pass, 38884 github.tar, level 3 with dict, advanced one pass, 37995 github.tar, level 3 with dict dms, advanced one pass, 38114 @@ -544,13 +544,13 @@ github.tar, small chain log, advanced github.tar, explicit params, advanced one pass, 41385 github.tar, uncompressed literals, advanced one pass, 41562 github.tar, uncompressed literals optimal, advanced one pass, 35356 -github.tar, huffman literals, advanced one pass, 39099 +github.tar, huffman literals, advanced one pass, 38921 github.tar, multithreaded with advanced params, advanced one pass, 41562 -silesia, level -5, advanced one pass small out, 6857776 -silesia, level -3, advanced one pass small out, 6504756 -silesia, level -1, advanced one pass small out, 6174127 +silesia, level -5, advanced one pass small out, 6854688 +silesia, level -3, advanced one pass small out, 6502839 +silesia, level -1, advanced one pass small out, 6173625 silesia, level 0, advanced one pass small out, 4832054 -silesia, level 1, advanced one pass small out, 5306931 +silesia, level 1, advanced one pass small out, 5304296 silesia, level 3, advanced one pass small out, 4832054 silesia, level 4, advanced one pass small out, 4768799 silesia, level 5 row 1, advanced one pass small out, 4663718 @@ -578,13 +578,13 @@ silesia, small chain log, advanced silesia, explicit params, advanced one pass small out, 4791219 silesia, uncompressed literals, advanced one pass small out, 5117526 silesia, uncompressed literals optimal, advanced one pass small out, 4316644 -silesia, huffman literals, advanced one pass small out, 5321686 +silesia, huffman literals, advanced one pass small out, 5319104 silesia, multithreaded with advanced params, advanced one pass small out, 5118187 -silesia.tar, level -5, advanced one pass small out, 6860782 -silesia.tar, level -3, advanced one pass small out, 6507448 -silesia.tar, level -1, advanced one pass small out, 6175582 +silesia.tar, level -5, advanced one pass small out, 6858730 +silesia.tar, level -3, advanced one pass small out, 6502944 +silesia.tar, level -1, advanced one pass small out, 6175652 silesia.tar, level 0, advanced one pass small out, 4829268 -silesia.tar, level 1, advanced one pass small out, 5316794 +silesia.tar, level 1, advanced one pass small out, 5307443 silesia.tar, level 3, advanced one pass small out, 4829268 silesia.tar, level 4, advanced one pass small out, 4767074 silesia.tar, level 5 row 1, advanced one pass small out, 4662847 @@ -612,7 +612,7 @@ silesia.tar, small chain log, advanced silesia.tar, explicit params, advanced one pass small out, 4790421 silesia.tar, uncompressed literals, advanced one pass small out, 5114702 silesia.tar, uncompressed literals optimal, advanced one pass small out, 4306289 -silesia.tar, huffman literals, advanced one pass small out, 5331382 +silesia.tar, huffman literals, advanced one pass small out, 5323421 silesia.tar, multithreaded with advanced params, advanced one pass small out, 5116579 github, level -5, advanced one pass small out, 204407 github, level -5 with dict, advanced one pass small out, 45832 @@ -739,24 +739,24 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced one pass small out, 152667 github, huffman literals, advanced one pass small out, 142365 github, multithreaded with advanced params, advanced one pass small out, 165909 -github.tar, level -5, advanced one pass small out, 52320 -github.tar, level -5 with dict, advanced one pass small out, 51321 -github.tar, level -3, advanced one pass small out, 45823 -github.tar, level -3 with dict, advanced one pass small out, 44882 -github.tar, level -1, advanced one pass small out, 42740 -github.tar, level -1 with dict, advanced one pass small out, 41506 +github.tar, level -5, advanced one pass small out, 52173 +github.tar, level -5 with dict, advanced one pass small out, 51161 +github.tar, level -3, advanced one pass small out, 45783 +github.tar, level -3 with dict, advanced one pass small out, 44768 +github.tar, level -1, advanced one pass small out, 42606 +github.tar, level -1 with dict, advanced one pass small out, 41397 github.tar, level 0, advanced one pass small out, 38884 github.tar, level 0 with dict, advanced one pass small out, 37995 github.tar, level 0 with dict dms, advanced one pass small out, 38114 github.tar, level 0 with dict dds, advanced one pass small out, 38114 github.tar, level 0 with dict copy, advanced one pass small out, 37995 github.tar, level 0 with dict load, advanced one pass small out, 37956 -github.tar, level 1, advanced one pass small out, 39444 -github.tar, level 1 with dict, advanced one pass small out, 38338 -github.tar, level 1 with dict dms, advanced one pass small out, 38641 -github.tar, level 1 with dict dds, advanced one pass small out, 38641 -github.tar, level 1 with dict copy, advanced one pass small out, 38338 -github.tar, level 1 with dict load, advanced one pass small out, 38592 +github.tar, level 1, advanced one pass small out, 39200 +github.tar, level 1 with dict, advanced one pass small out, 38189 +github.tar, level 1 with dict dms, advanced one pass small out, 38398 +github.tar, level 1 with dict dds, advanced one pass small out, 38398 +github.tar, level 1 with dict copy, advanced one pass small out, 38189 +github.tar, level 1 with dict load, advanced one pass small out, 38393 github.tar, level 3, advanced one pass small out, 38884 github.tar, level 3 with dict, advanced one pass small out, 37995 github.tar, level 3 with dict dms, advanced one pass small out, 38114 @@ -862,13 +862,13 @@ github.tar, small chain log, advanced github.tar, explicit params, advanced one pass small out, 41385 github.tar, uncompressed literals, advanced one pass small out, 41562 github.tar, uncompressed literals optimal, advanced one pass small out, 35356 -github.tar, huffman literals, advanced one pass small out, 39099 +github.tar, huffman literals, advanced one pass small out, 38921 github.tar, multithreaded with advanced params, advanced one pass small out, 41562 -silesia, level -5, advanced streaming, 6856699 -silesia, level -3, advanced streaming, 6505694 -silesia, level -1, advanced streaming, 6174139 +silesia, level -5, advanced streaming, 6853462 +silesia, level -3, advanced streaming, 6502349 +silesia, level -1, advanced streaming, 6172125 silesia, level 0, advanced streaming, 4835804 -silesia, level 1, advanced streaming, 5305682 +silesia, level 1, advanced streaming, 5301644 silesia, level 3, advanced streaming, 4835804 silesia, level 4, advanced streaming, 4773049 silesia, level 5 row 1, advanced streaming, 4664679 @@ -896,13 +896,13 @@ silesia, small chain log, advanced silesia, explicit params, advanced streaming, 4792505 silesia, uncompressed literals, advanced streaming, 5116404 silesia, uncompressed literals optimal, advanced streaming, 4316533 -silesia, huffman literals, advanced streaming, 5321812 +silesia, huffman literals, advanced streaming, 5317620 silesia, multithreaded with advanced params, advanced streaming, 5118187 -silesia.tar, level -5, advanced streaming, 6857458 -silesia.tar, level -3, advanced streaming, 6508562 -silesia.tar, level -1, advanced streaming, 6178057 +silesia.tar, level -5, advanced streaming, 6853184 +silesia.tar, level -3, advanced streaming, 6503455 +silesia.tar, level -1, advanced streaming, 6175761 silesia.tar, level 0, advanced streaming, 4846783 -silesia.tar, level 1, advanced streaming, 5311452 +silesia.tar, level 1, advanced streaming, 5306719 silesia.tar, level 3, advanced streaming, 4846783 silesia.tar, level 4, advanced streaming, 4785332 silesia.tar, level 5 row 1, advanced streaming, 4664523 @@ -930,7 +930,7 @@ silesia.tar, small chain log, advanced silesia.tar, explicit params, advanced streaming, 4791739 silesia.tar, uncompressed literals, advanced streaming, 5123274 silesia.tar, uncompressed literals optimal, advanced streaming, 4306968 -silesia.tar, huffman literals, advanced streaming, 5326278 +silesia.tar, huffman literals, advanced streaming, 5323245 silesia.tar, multithreaded with advanced params, advanced streaming, 5116579 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 @@ -1057,24 +1057,24 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced streaming, 152667 github, huffman literals, advanced streaming, 142365 github, multithreaded with advanced params, advanced streaming, 165909 -github.tar, level -5, advanced streaming, 52384 -github.tar, level -5 with dict, advanced streaming, 51420 -github.tar, level -3, advanced streaming, 45907 -github.tar, level -3 with dict, advanced streaming, 44973 -github.tar, level -1, advanced streaming, 42777 -github.tar, level -1 with dict, advanced streaming, 41603 +github.tar, level -5, advanced streaming, 52273 +github.tar, level -5 with dict, advanced streaming, 51297 +github.tar, level -3, advanced streaming, 45783 +github.tar, level -3 with dict, advanced streaming, 44853 +github.tar, level -1, advanced streaming, 42687 +github.tar, level -1 with dict, advanced streaming, 41486 github.tar, level 0, advanced streaming, 38884 github.tar, level 0 with dict, advanced streaming, 37995 github.tar, level 0 with dict dms, advanced streaming, 38114 github.tar, level 0 with dict dds, advanced streaming, 38114 github.tar, level 0 with dict copy, advanced streaming, 37995 github.tar, level 0 with dict load, advanced streaming, 37956 -github.tar, level 1, advanced streaming, 39550 -github.tar, level 1 with dict, advanced streaming, 38502 -github.tar, level 1 with dict dms, advanced streaming, 38770 -github.tar, level 1 with dict dds, advanced streaming, 38770 -github.tar, level 1 with dict copy, advanced streaming, 38502 -github.tar, level 1 with dict load, advanced streaming, 38716 +github.tar, level 1, advanced streaming, 39346 +github.tar, level 1 with dict, advanced streaming, 38251 +github.tar, level 1 with dict dms, advanced streaming, 38557 +github.tar, level 1 with dict dds, advanced streaming, 38557 +github.tar, level 1 with dict copy, advanced streaming, 38251 +github.tar, level 1 with dict load, advanced streaming, 38503 github.tar, level 3, advanced streaming, 38884 github.tar, level 3 with dict, advanced streaming, 37995 github.tar, level 3 with dict dms, advanced streaming, 38114 @@ -1180,13 +1180,13 @@ github.tar, small chain log, advanced github.tar, explicit params, advanced streaming, 41385 github.tar, uncompressed literals, advanced streaming, 41562 github.tar, uncompressed literals optimal, advanced streaming, 35356 -github.tar, huffman literals, advanced streaming, 39226 +github.tar, huffman literals, advanced streaming, 38998 github.tar, multithreaded with advanced params, advanced streaming, 41562 -silesia, level -5, old streaming, 6856699 -silesia, level -3, old streaming, 6505694 -silesia, level -1, old streaming, 6174139 +silesia, level -5, old streaming, 6853462 +silesia, level -3, old streaming, 6502349 +silesia, level -1, old streaming, 6172125 silesia, level 0, old streaming, 4835804 -silesia, level 1, old streaming, 5305682 +silesia, level 1, old streaming, 5301644 silesia, level 3, old streaming, 4835804 silesia, level 4, old streaming, 4773049 silesia, level 5, old streaming, 4664679 @@ -1199,12 +1199,12 @@ silesia, level 19, old stre silesia, no source size, old streaming, 4835768 silesia, uncompressed literals, old streaming, 4835804 silesia, uncompressed literals optimal, old streaming, 4265908 -silesia, huffman literals, old streaming, 6174139 -silesia.tar, level -5, old streaming, 6857458 -silesia.tar, level -3, old streaming, 6508562 -silesia.tar, level -1, old streaming, 6178057 +silesia, huffman literals, old streaming, 6172125 +silesia.tar, level -5, old streaming, 6853184 +silesia.tar, level -3, old streaming, 6503455 +silesia.tar, level -1, old streaming, 6175761 silesia.tar, level 0, old streaming, 4846783 -silesia.tar, level 1, old streaming, 5311452 +silesia.tar, level 1, old streaming, 5306719 silesia.tar, level 3, old streaming, 4846783 silesia.tar, level 4, old streaming, 4785332 silesia.tar, level 5, old streaming, 4664523 @@ -1217,7 +1217,7 @@ silesia.tar, level 19, old stre silesia.tar, no source size, old streaming, 4846779 silesia.tar, uncompressed literals, old streaming, 4846783 silesia.tar, uncompressed literals optimal, old streaming, 4258228 -silesia.tar, huffman literals, old streaming, 6178057 +silesia.tar, huffman literals, old streaming, 6175761 github, level -5, old streaming, 204407 github, level -5 with dict, old streaming, 45832 github, level -3, old streaming, 193253 @@ -1251,16 +1251,16 @@ github, no source size with dict, old stre github, uncompressed literals, old streaming, 136331 github, uncompressed literals optimal, old streaming, 132879 github, huffman literals, old streaming, 175468 -github.tar, level -5, old streaming, 52384 -github.tar, level -5 with dict, old streaming, 51420 -github.tar, level -3, old streaming, 45907 -github.tar, level -3 with dict, old streaming, 44973 -github.tar, level -1, old streaming, 42777 -github.tar, level -1 with dict, old streaming, 41603 +github.tar, level -5, old streaming, 52273 +github.tar, level -5 with dict, old streaming, 51297 +github.tar, level -3, old streaming, 45783 +github.tar, level -3 with dict, old streaming, 44853 +github.tar, level -1, old streaming, 42687 +github.tar, level -1 with dict, old streaming, 41486 github.tar, level 0, old streaming, 38884 github.tar, level 0 with dict, old streaming, 37995 -github.tar, level 1, old streaming, 39550 -github.tar, level 1 with dict, old streaming, 38502 +github.tar, level 1, old streaming, 39346 +github.tar, level 1 with dict, old streaming, 38251 github.tar, level 3, old streaming, 38884 github.tar, level 3 with dict, old streaming, 37995 github.tar, level 4, old streaming, 38880 @@ -1283,12 +1283,12 @@ github.tar, no source size, old stre github.tar, no source size with dict, old streaming, 38111 github.tar, uncompressed literals, old streaming, 38884 github.tar, uncompressed literals optimal, old streaming, 32262 -github.tar, huffman literals, old streaming, 42777 -silesia, level -5, old streaming advanced, 6856699 -silesia, level -3, old streaming advanced, 6505694 -silesia, level -1, old streaming advanced, 6174139 +github.tar, huffman literals, old streaming, 42687 +silesia, level -5, old streaming advanced, 6853462 +silesia, level -3, old streaming advanced, 6502349 +silesia, level -1, old streaming advanced, 6172125 silesia, level 0, old streaming advanced, 4835804 -silesia, level 1, old streaming advanced, 5305682 +silesia, level 1, old streaming advanced, 5301644 silesia, level 3, old streaming advanced, 4835804 silesia, level 4, old streaming advanced, 4773049 silesia, level 5, old streaming advanced, 4664679 @@ -1308,13 +1308,13 @@ silesia, small chain log, old stre silesia, explicit params, old streaming advanced, 4792505 silesia, uncompressed literals, old streaming advanced, 4835804 silesia, uncompressed literals optimal, old streaming advanced, 4265908 -silesia, huffman literals, old streaming advanced, 6174139 +silesia, huffman literals, old streaming advanced, 6172125 silesia, multithreaded with advanced params, old streaming advanced, 4835804 -silesia.tar, level -5, old streaming advanced, 6857458 -silesia.tar, level -3, old streaming advanced, 6508562 -silesia.tar, level -1, old streaming advanced, 6178057 +silesia.tar, level -5, old streaming advanced, 6853184 +silesia.tar, level -3, old streaming advanced, 6503455 +silesia.tar, level -1, old streaming advanced, 6175761 silesia.tar, level 0, old streaming advanced, 4846783 -silesia.tar, level 1, old streaming advanced, 5311452 +silesia.tar, level 1, old streaming advanced, 5306719 silesia.tar, level 3, old streaming advanced, 4846783 silesia.tar, level 4, old streaming advanced, 4785332 silesia.tar, level 5, old streaming advanced, 4664523 @@ -1334,7 +1334,7 @@ silesia.tar, small chain log, old stre silesia.tar, explicit params, old streaming advanced, 4791739 silesia.tar, uncompressed literals, old streaming advanced, 4846783 silesia.tar, uncompressed literals optimal, old streaming advanced, 4258228 -silesia.tar, huffman literals, old streaming advanced, 6178057 +silesia.tar, huffman literals, old streaming advanced, 6175761 silesia.tar, multithreaded with advanced params, old streaming advanced, 4846783 github, level -5, old streaming advanced, 213265 github, level -5 with dict, old streaming advanced, 46708 @@ -1377,16 +1377,16 @@ github, uncompressed literals, old stre github, uncompressed literals optimal, old streaming advanced, 132879 github, huffman literals, old streaming advanced, 181107 github, multithreaded with advanced params, old streaming advanced, 141101 -github.tar, level -5, old streaming advanced, 52384 -github.tar, level -5 with dict, old streaming advanced, 51359 -github.tar, level -3, old streaming advanced, 45907 -github.tar, level -3 with dict, old streaming advanced, 45211 -github.tar, level -1, old streaming advanced, 42777 -github.tar, level -1 with dict, old streaming advanced, 41865 +github.tar, level -5, old streaming advanced, 52273 +github.tar, level -5 with dict, old streaming advanced, 51249 +github.tar, level -3, old streaming advanced, 45783 +github.tar, level -3 with dict, old streaming advanced, 45093 +github.tar, level -1, old streaming advanced, 42687 +github.tar, level -1 with dict, old streaming advanced, 41762 github.tar, level 0, old streaming advanced, 38884 github.tar, level 0 with dict, old streaming advanced, 38013 -github.tar, level 1, old streaming advanced, 39550 -github.tar, level 1 with dict, old streaming advanced, 38714 +github.tar, level 1, old streaming advanced, 39346 +github.tar, level 1 with dict, old streaming advanced, 38507 github.tar, level 3, old streaming advanced, 38884 github.tar, level 3 with dict, old streaming advanced, 38013 github.tar, level 4, old streaming advanced, 38880 @@ -1416,7 +1416,7 @@ github.tar, small chain log, old stre github.tar, explicit params, old streaming advanced, 41385 github.tar, uncompressed literals, old streaming advanced, 38884 github.tar, uncompressed literals optimal, old streaming advanced, 32262 -github.tar, huffman literals, old streaming advanced, 42777 +github.tar, huffman literals, old streaming advanced, 42687 github.tar, multithreaded with advanced params, old streaming advanced, 38884 github, level -5 with dict, old streaming cdict, 45832 github, level -3 with dict, old streaming cdict, 44671 @@ -1433,11 +1433,11 @@ github, level 13 with dict, old stre github, level 16 with dict, old streaming cdict, 37902 github, level 19 with dict, old streaming cdict, 37916 github, no source size with dict, old streaming cdict, 40652 -github.tar, level -5 with dict, old streaming cdict, 51512 -github.tar, level -3 with dict, old streaming cdict, 45379 -github.tar, level -1 with dict, old streaming cdict, 42084 +github.tar, level -5 with dict, old streaming cdict, 51407 +github.tar, level -3 with dict, old streaming cdict, 45254 +github.tar, level -1 with dict, old streaming cdict, 41973 github.tar, level 0 with dict, old streaming cdict, 37956 -github.tar, level 1 with dict, old streaming cdict, 38716 +github.tar, level 1 with dict, old streaming cdict, 38503 github.tar, level 3 with dict, old streaming cdict, 37956 github.tar, level 4 with dict, old streaming cdict, 37927 github.tar, level 5 with dict, old streaming cdict, 39000 @@ -1463,11 +1463,11 @@ github, level 13 with dict, old stre github, level 16 with dict, old streaming advanced cdict, 40804 github, level 19 with dict, old streaming advanced cdict, 37916 github, no source size with dict, old streaming advanced cdict, 40608 -github.tar, level -5 with dict, old streaming advanced cdict, 51019 -github.tar, level -3 with dict, old streaming advanced cdict, 45149 -github.tar, level -1 with dict, old streaming advanced cdict, 41694 +github.tar, level -5 with dict, old streaming advanced cdict, 50907 +github.tar, level -3 with dict, old streaming advanced cdict, 45032 +github.tar, level -1 with dict, old streaming advanced cdict, 41589 github.tar, level 0 with dict, old streaming advanced cdict, 38013 -github.tar, level 1 with dict, old streaming advanced cdict, 38513 +github.tar, level 1 with dict, old streaming advanced cdict, 38294 github.tar, level 3 with dict, old streaming advanced cdict, 38013 github.tar, level 4 with dict, old streaming advanced cdict, 38063 github.tar, level 5 with dict, old streaming advanced cdict, 39018 From 01474bf73b357fe0c7bcf51f5cd41928462e2488 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 25 Oct 2024 15:51:03 -0700 Subject: [PATCH 156/405] add internal compression parameter preBlockSplitter_level not yet exposed to the interface. Also: renames `useBlockSplitter` to `postBlockSplitter` to better qualify the difference between the 2 settings. --- lib/compress/zstd_compress.c | 52 +++++++++++++++++---------- lib/compress/zstd_compress_internal.h | 20 ++++++++--- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 5f8f5aba4..05edcd201 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -323,7 +323,7 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog); assert(cctxParams.ldmParams.hashRateLog < 32); } - cctxParams.useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.useBlockSplitter, &cParams); + cctxParams.postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.postBlockSplitter, &cParams); cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); cctxParams.validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams.validateSequences); cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize); @@ -391,13 +391,13 @@ ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, */ cctxParams->compressionLevel = compressionLevel; cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, ¶ms->cParams); - cctxParams->useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->useBlockSplitter, ¶ms->cParams); + cctxParams->postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->postBlockSplitter, ¶ms->cParams); cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, ¶ms->cParams); cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences); cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize); cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel); DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d", - cctxParams->useRowMatchFinder, cctxParams->useBlockSplitter, cctxParams->ldmParams.enableLdm); + cctxParams->useRowMatchFinder, cctxParams->postBlockSplitter, cctxParams->ldmParams.enableLdm); } size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) @@ -977,8 +977,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_useBlockSplitter: BOUNDCHECK(ZSTD_c_useBlockSplitter, value); - CCtxParams->useBlockSplitter = (ZSTD_paramSwitch_e)value; - return CCtxParams->useBlockSplitter; + CCtxParams->postBlockSplitter = (ZSTD_paramSwitch_e)value; + return CCtxParams->postBlockSplitter; case ZSTD_c_useRowMatchFinder: BOUNDCHECK(ZSTD_c_useRowMatchFinder, value); @@ -1136,7 +1136,7 @@ size_t ZSTD_CCtxParams_getParameter( *value = (int)CCtxParams->validateSequences; break; case ZSTD_c_useBlockSplitter : - *value = (int)CCtxParams->useBlockSplitter; + *value = (int)CCtxParams->postBlockSplitter; break; case ZSTD_c_useRowMatchFinder : *value = (int)CCtxParams->useRowMatchFinder; @@ -2111,7 +2111,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, params = &zc->appliedParams; assert(params->useRowMatchFinder != ZSTD_ps_auto); - assert(params->useBlockSplitter != ZSTD_ps_auto); + assert(params->postBlockSplitter != ZSTD_ps_auto); assert(params->ldmParams.enableLdm != ZSTD_ps_auto); assert(params->maxBlockSize != 0); if (params->ldmParams.enableLdm == ZSTD_ps_enable) { @@ -2517,10 +2517,10 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, /* Copy only compression parameters related to tables. */ params.cParams = srcCCtx->appliedParams.cParams; assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_ps_auto); - assert(srcCCtx->appliedParams.useBlockSplitter != ZSTD_ps_auto); + assert(srcCCtx->appliedParams.postBlockSplitter != ZSTD_ps_auto); assert(srcCCtx->appliedParams.ldmParams.enableLdm != ZSTD_ps_auto); params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder; - params.useBlockSplitter = srcCCtx->appliedParams.useBlockSplitter; + params.postBlockSplitter = srcCCtx->appliedParams.postBlockSplitter; params.ldmParams = srcCCtx->appliedParams.ldmParams; params.fParams = fParams; params.maxBlockSize = srcCCtx->appliedParams.maxBlockSize; @@ -2728,9 +2728,9 @@ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams) * Returns 1 if true, 0 otherwise. */ static int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams) { - DEBUGLOG(5, "ZSTD_blockSplitterEnabled (useBlockSplitter=%d)", cctxParams->useBlockSplitter); - assert(cctxParams->useBlockSplitter != ZSTD_ps_auto); - return (cctxParams->useBlockSplitter == ZSTD_ps_enable); + DEBUGLOG(5, "ZSTD_blockSplitterEnabled (postBlockSplitter=%d)", cctxParams->postBlockSplitter); + assert(cctxParams->postBlockSplitter != ZSTD_ps_auto); + return (cctxParams->postBlockSplitter == ZSTD_ps_enable); } /* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types @@ -4300,7 +4300,7 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc, U32 nbSeq; size_t cSize; DEBUGLOG(4, "ZSTD_compressBlock_splitBlock"); - assert(zc->appliedParams.useBlockSplitter == ZSTD_ps_enable); + assert(zc->appliedParams.postBlockSplitter == ZSTD_ps_enable); { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); @@ -4491,7 +4491,7 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" -static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) +static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, int splitLevel, ZSTD_strategy strat, S64 savings) { /* split level based on compression strategy, from `fast` to `btultra2` */ static const int splitLevels[] = { 0, 0, 1, 2, 2, 3, 3, 4, 4, 4 }; @@ -4506,9 +4506,18 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src * Note: as a consequence, the first full block is not split. */ if (savings < 3) return 128 KB; - /* dynamic splitting has a cpu cost for analysis, - * select a variant among multiple gradual speed/accuracy tradeoffs */ - return ZSTD_splitBlock(src, blockSizeMax, splitLevels[strat], cctx->tmpWorkspace, cctx->tmpWkspSize); + /* apply @splitLevel, or use default value (which depends on @strat). + * note that splitting heuristic is still conditioned by @savings >= 3, + * so the first block will not reach this code path */ + if (splitLevel == 1) return 128 KB; + if (splitLevel == 0) { + assert(ZSTD_fast <= strat && strat <= ZSTD_btultra2); + splitLevel = splitLevels[strat]; + } else { + assert(2 <= splitLevel && splitLevel <= 6); + splitLevel -= 2; + } + return ZSTD_splitBlock(src, blockSizeMax, splitLevel, cctx->tmpWorkspace, cctx->tmpWkspSize); } /*! ZSTD_compress_frameChunk() : @@ -4539,7 +4548,12 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - size_t const blockSize = ZSTD_optimalBlockSize(cctx, ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); + size_t const blockSize = ZSTD_optimalBlockSize(cctx, + ip, remaining, + blockSizeMax, + cctx->appliedParams.preBlockSplitter_level, + cctx->appliedParams.cParams.strategy, + savings); U32 const lastBlock = lastFrameChunk & (blockSize == remaining); assert(blockSize <= remaining); @@ -6286,7 +6300,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, dictSize, mode); } - params.useBlockSplitter = ZSTD_resolveBlockSplitterMode(params.useBlockSplitter, ¶ms.cParams); + params.postBlockSplitter = ZSTD_resolveBlockSplitterMode(params.postBlockSplitter, ¶ms.cParams); params.ldmParams.enableLdm = ZSTD_resolveEnableLdm(params.ldmParams.enableLdm, ¶ms.cParams); params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, ¶ms.cParams); params.validateSequences = ZSTD_resolveExternalSequenceValidation(params.validateSequences); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index e76bbda71..2d3510adc 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -343,8 +343,21 @@ struct ZSTD_CCtx_params_s { ZSTD_sequenceFormat_e blockDelimiters; int validateSequences; - /* Block splitting */ - ZSTD_paramSwitch_e useBlockSplitter; + /* Block splitting + * @postBlockSplitter executes split analysis after sequences are produced, + * it's more accurate but consumes more resources. + * @preBlockSplitter_level splits before knowing sequences, + * it's more approximative but also cheaper. + * Valid @preBlockSplitter_level values range from 0 to 6 (included). + * 0 means auto, 1 means do not split, + * then levels are sorted in increasing cpu budget, from 2 (fastest) to 6 (slowest). + * Highest @preBlockSplitter_level combines well with @postBlockSplitter. + */ + ZSTD_paramSwitch_e postBlockSplitter; + int preBlockSplitter_level; + + /* Adjust the max block size*/ + size_t maxBlockSize; /* Param for deciding whether to use row-based matchfinder */ ZSTD_paramSwitch_e useRowMatchFinder; @@ -368,9 +381,6 @@ struct ZSTD_CCtx_params_s { void* extSeqProdState; ZSTD_sequenceProducer_F extSeqProdFunc; - /* Adjust the max block size*/ - size_t maxBlockSize; - /* Controls repcode search in external sequence parsing */ ZSTD_paramSwitch_e searchForExternalRepcodes; }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */ From 226ae73311d1ffd0c3488d8bc6a59576d910d6d4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 25 Oct 2024 16:08:22 -0700 Subject: [PATCH 157/405] expose new parameter ZSTD_c_blockSplitter_level --- lib/compress/zstd_compress.c | 15 +++++++++++++++ lib/zstd.h | 23 +++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 05edcd201..fbc11349e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -603,6 +603,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = (int)ZSTD_ps_disable; return bounds; + case ZSTD_c_blockSplitter_level: + bounds.lowerBound = 0; + bounds.upperBound = ZSTD_BLOCKSPLITTER_LEVEL_MAX; + return bounds; + case ZSTD_c_useRowMatchFinder: bounds.lowerBound = (int)ZSTD_ps_auto; bounds.upperBound = (int)ZSTD_ps_disable; @@ -669,6 +674,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_minMatch: case ZSTD_c_targetLength: case ZSTD_c_strategy: + case ZSTD_c_blockSplitter_level: return 1; case ZSTD_c_format: @@ -755,6 +761,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_blockDelimiters: case ZSTD_c_validateSequences: case ZSTD_c_useBlockSplitter: + case ZSTD_c_blockSplitter_level: case ZSTD_c_useRowMatchFinder: case ZSTD_c_deterministicRefPrefix: case ZSTD_c_prefetchCDictTables: @@ -980,6 +987,11 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->postBlockSplitter = (ZSTD_paramSwitch_e)value; return CCtxParams->postBlockSplitter; + case ZSTD_c_blockSplitter_level: + BOUNDCHECK(ZSTD_c_blockSplitter_level, value); + CCtxParams->preBlockSplitter_level = value; + return (size_t)CCtxParams->preBlockSplitter_level; + case ZSTD_c_useRowMatchFinder: BOUNDCHECK(ZSTD_c_useRowMatchFinder, value); CCtxParams->useRowMatchFinder = (ZSTD_paramSwitch_e)value; @@ -1138,6 +1150,9 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_useBlockSplitter : *value = (int)CCtxParams->postBlockSplitter; break; + case ZSTD_c_blockSplitter_level : + *value = CCtxParams->preBlockSplitter_level; + break; case ZSTD_c_useRowMatchFinder : *value = (int)CCtxParams->useRowMatchFinder; break; diff --git a/lib/zstd.h b/lib/zstd.h index 3a88c74d1..c1ad26a8d 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -496,6 +496,7 @@ typedef enum { * ZSTD_c_prefetchCDictTables * ZSTD_c_enableSeqProducerFallback * ZSTD_c_maxBlockSize + * ZSTD_c_blockSplitter_level * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly; * also, the enums values themselves are unstable and can still change. @@ -518,7 +519,8 @@ typedef enum { ZSTD_c_experimentalParam16=1013, ZSTD_c_experimentalParam17=1014, ZSTD_c_experimentalParam18=1015, - ZSTD_c_experimentalParam19=1016 + ZSTD_c_experimentalParam19=1016, + ZSTD_c_experimentalParam20=1017 } ZSTD_cParameter; typedef struct { @@ -2236,7 +2238,6 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo * that overrides the default ZSTD_BLOCKSIZE_MAX. It cannot be used to set upper * bounds greater than ZSTD_BLOCKSIZE_MAX or bounds lower than 1KB (will make * compressBound() inaccurate). Only currently meant to be used for testing. - * */ #define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18 @@ -2264,6 +2265,24 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo */ #define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 +/* ZSTD_c_blockSplitter_level + * note: this parameter only influences the first splitter stage, + * which is active before producing the sequences. + * ZSTD_c_useBlockSplitter influence the next splitter stage, + * which is active after sequence production, + * and is more accurate but also slower. + * Both can be combined. + * Allowed values are between 0 and 6. + * 0 means "auto", which will select a value depending on current ZSTD_c_strategy. + * 1 means no splitting. + * Then, values from 2 to 6 are sorted in increasing cpu load order. + * + * Note that currently the first block is never split, + * to ensure expansion guarantees in presence of incompressible data. + */ +#define ZSTD_BLOCKSPLITTER_LEVEL_MAX 6 +#define ZSTD_c_blockSplitter_level ZSTD_c_experimentalParam20 + /*! ZSTD_CCtx_getParameter() : * Get the requested compression parameter value, selected by enum ZSTD_cParameter, * and store it into int* value. From 37706a677c09a1051f8b02361928c475bd094e67 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 25 Oct 2024 20:29:15 -0700 Subject: [PATCH 158/405] added a test test both that the new parameter works as intended, and that the over-split protection works as intended --- lib/compress/zstd_compress.c | 7 ++-- lib/compress/zstd_preSplit.c | 1 + tests/fuzzer.c | 63 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index fbc11349e..ca9e5edff 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2114,7 +2114,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, { ZSTD_cwksp* const ws = &zc->workspace; DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d", - (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->useBlockSplitter); + (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->postBlockSplitter); assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); zc->isFirstBlock = 1; @@ -4520,7 +4520,10 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src * require verified savings to allow pre-splitting. * Note: as a consequence, the first full block is not split. */ - if (savings < 3) return 128 KB; + if (savings < 3) { + DEBUGLOG(6, "don't attempt splitting: savings (%lli) too low", savings); + return 128 KB; + } /* apply @splitLevel, or use default value (which depends on @strat). * note that splitting heuristic is still conditioned by @savings >= 3, * so the first block will not reach this code path */ diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index d25773950..d820c20ac 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -229,6 +229,7 @@ size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize, int level, void* workspace, size_t wkspSize) { + DEBUGLOG(6, "ZSTD_splitBlock (level=%i)", level); assert(0<=level && level<=4); if (level == 0) return ZSTD_splitBlock_fromBorders(blockStart, blockSize, workspace, wkspSize); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index f5a894354..e32c0130d 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -559,6 +559,67 @@ static void test_setCParams(unsigned tnb) DISPLAYLEVEL(3, "OK \n"); } +static void test_blockSplitter_incompressibleExpansionProtection(unsigned testNb, unsigned seed) +{ + DISPLAYLEVEL(3, "test%3i : Check block splitter doesn't oversplit incompressible data (seed %u): ", testNb, seed); + { ZSTD_CCtx* cctx = ZSTD_createCCtx(); + size_t const srcSize = 256 * 1024; /* needs to be at least 2 blocks */ + void* incompressible = malloc(srcSize); + size_t const dstCapacity = ZSTD_compressBound(srcSize); + void* cBuffer = malloc(dstCapacity); + size_t const chunkSize = 8 KB; + size_t const nbChunks = srcSize / chunkSize; + size_t chunkNb, cSizeNoSplit, cSizeWithSplit; + assert(cctx != NULL); + assert(incompressible != NULL); + assert(cBuffer != NULL); + + /* let's fill input with random noise (incompressible) */ + RDG_genBuffer(incompressible, srcSize, 0.0, 0.0, seed); + DISPLAYLEVEL(4, "(hash: %llx) ", XXH64(incompressible, srcSize, 0)); + + /* this pattern targets the fastest _byChunk variant's sampling (level 3). + * manually checked that, without the @savings protection, it would over-split. + */ + for (chunkNb=0; chunkNb Date: Mon, 28 Oct 2024 16:47:38 -0700 Subject: [PATCH 159/405] fixed minor conversion warning --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ca9e5edff..ea7a45fa7 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4521,7 +4521,7 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src * Note: as a consequence, the first full block is not split. */ if (savings < 3) { - DEBUGLOG(6, "don't attempt splitting: savings (%lli) too low", savings); + DEBUGLOG(6, "don't attempt splitting: savings (%i) too low", (int)savings); return 128 KB; } /* apply @splitLevel, or use default value (which depends on @strat). From f593ccda04f89be6fc4f966b9b816d542941771f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 28 Oct 2024 16:57:01 -0700 Subject: [PATCH 160/405] removed trace left over --- tests/fuzzer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index e32c0130d..c1bff7a5a 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -576,7 +576,6 @@ static void test_blockSplitter_incompressibleExpansionProtection(unsigned testNb /* let's fill input with random noise (incompressible) */ RDG_genBuffer(incompressible, srcSize, 0.0, 0.0, seed); - DISPLAYLEVEL(4, "(hash: %llx) ", XXH64(incompressible, srcSize, 0)); /* this pattern targets the fastest _byChunk variant's sampling (level 3). * manually checked that, without the @savings protection, it would over-split. From 4f93206d62f306040a8e35033312e16986d0aeab Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 29 Oct 2024 11:04:11 -0700 Subject: [PATCH 161/405] changed variable name to ZSTD_c_blockSplitterLevel suggested by @terrelln --- lib/compress/zstd_compress.c | 12 ++++++------ lib/zstd.h | 6 +++--- tests/fuzzer.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ea7a45fa7..cf3e08dca 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -603,7 +603,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = (int)ZSTD_ps_disable; return bounds; - case ZSTD_c_blockSplitter_level: + case ZSTD_c_blockSplitterLevel: bounds.lowerBound = 0; bounds.upperBound = ZSTD_BLOCKSPLITTER_LEVEL_MAX; return bounds; @@ -674,7 +674,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_minMatch: case ZSTD_c_targetLength: case ZSTD_c_strategy: - case ZSTD_c_blockSplitter_level: + case ZSTD_c_blockSplitterLevel: return 1; case ZSTD_c_format: @@ -761,7 +761,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_blockDelimiters: case ZSTD_c_validateSequences: case ZSTD_c_useBlockSplitter: - case ZSTD_c_blockSplitter_level: + case ZSTD_c_blockSplitterLevel: case ZSTD_c_useRowMatchFinder: case ZSTD_c_deterministicRefPrefix: case ZSTD_c_prefetchCDictTables: @@ -987,8 +987,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->postBlockSplitter = (ZSTD_paramSwitch_e)value; return CCtxParams->postBlockSplitter; - case ZSTD_c_blockSplitter_level: - BOUNDCHECK(ZSTD_c_blockSplitter_level, value); + case ZSTD_c_blockSplitterLevel: + BOUNDCHECK(ZSTD_c_blockSplitterLevel, value); CCtxParams->preBlockSplitter_level = value; return (size_t)CCtxParams->preBlockSplitter_level; @@ -1150,7 +1150,7 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_useBlockSplitter : *value = (int)CCtxParams->postBlockSplitter; break; - case ZSTD_c_blockSplitter_level : + case ZSTD_c_blockSplitterLevel : *value = CCtxParams->preBlockSplitter_level; break; case ZSTD_c_useRowMatchFinder : diff --git a/lib/zstd.h b/lib/zstd.h index c1ad26a8d..cc5bb9879 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -496,7 +496,7 @@ typedef enum { * ZSTD_c_prefetchCDictTables * ZSTD_c_enableSeqProducerFallback * ZSTD_c_maxBlockSize - * ZSTD_c_blockSplitter_level + * ZSTD_c_blockSplitterLevel * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly; * also, the enums values themselves are unstable and can still change. @@ -2265,7 +2265,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo */ #define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 -/* ZSTD_c_blockSplitter_level +/* ZSTD_c_blockSplitterLevel * note: this parameter only influences the first splitter stage, * which is active before producing the sequences. * ZSTD_c_useBlockSplitter influence the next splitter stage, @@ -2281,7 +2281,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo * to ensure expansion guarantees in presence of incompressible data. */ #define ZSTD_BLOCKSPLITTER_LEVEL_MAX 6 -#define ZSTD_c_blockSplitter_level ZSTD_c_experimentalParam20 +#define ZSTD_c_blockSplitterLevel ZSTD_c_experimentalParam20 /*! ZSTD_CCtx_getParameter() : * Get the requested compression parameter value, selected by enum ZSTD_cParameter, diff --git a/tests/fuzzer.c b/tests/fuzzer.c index c1bff7a5a..08c2662fb 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -595,11 +595,11 @@ static void test_blockSplitter_incompressibleExpansionProtection(unsigned testNb } /* run first without splitting */ - ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockSplitter_level, 1 /* no split */); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockSplitterLevel, 1 /* no split */); cSizeNoSplit = ZSTD_compress2(cctx, cBuffer, dstCapacity, incompressible, srcSize); /* run with sample43 splitter, check it's still the same */ - ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockSplitter_level, 3 /* sample43, fastest _byChunk variant */); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockSplitterLevel, 3 /* sample43, fastest _byChunk variant */); cSizeWithSplit = ZSTD_compress2(cctx, cBuffer, dstCapacity, incompressible, srcSize); if (cSizeWithSplit != cSizeNoSplit) { From bbaba45589f233b91a310806d97ee7b4d9ee8320 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 31 Oct 2024 13:43:40 -0700 Subject: [PATCH 162/405] change experimental parameter name from ZSTD_c_useBlockSplitter to ZSTD_c_splitAfterSequences. --- lib/compress/zstd_compress.c | 12 ++++----- lib/zstd.h | 51 ++++++++++++++++++++---------------- tests/fuzz/zstd_helpers.c | 3 ++- tests/fuzzer.c | 14 +++++----- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index cf3e08dca..3d78b7da3 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -598,7 +598,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = 1; return bounds; - case ZSTD_c_useBlockSplitter: + case ZSTD_c_splitAfterSequences: bounds.lowerBound = (int)ZSTD_ps_auto; bounds.upperBound = (int)ZSTD_ps_disable; return bounds; @@ -701,7 +701,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_stableOutBuffer: case ZSTD_c_blockDelimiters: case ZSTD_c_validateSequences: - case ZSTD_c_useBlockSplitter: + case ZSTD_c_splitAfterSequences: case ZSTD_c_useRowMatchFinder: case ZSTD_c_deterministicRefPrefix: case ZSTD_c_prefetchCDictTables: @@ -760,7 +760,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_stableOutBuffer: case ZSTD_c_blockDelimiters: case ZSTD_c_validateSequences: - case ZSTD_c_useBlockSplitter: + case ZSTD_c_splitAfterSequences: case ZSTD_c_blockSplitterLevel: case ZSTD_c_useRowMatchFinder: case ZSTD_c_deterministicRefPrefix: @@ -982,8 +982,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->validateSequences = value; return (size_t)CCtxParams->validateSequences; - case ZSTD_c_useBlockSplitter: - BOUNDCHECK(ZSTD_c_useBlockSplitter, value); + case ZSTD_c_splitAfterSequences: + BOUNDCHECK(ZSTD_c_splitAfterSequences, value); CCtxParams->postBlockSplitter = (ZSTD_paramSwitch_e)value; return CCtxParams->postBlockSplitter; @@ -1147,7 +1147,7 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_validateSequences : *value = (int)CCtxParams->validateSequences; break; - case ZSTD_c_useBlockSplitter : + case ZSTD_c_splitAfterSequences : *value = (int)CCtxParams->postBlockSplitter; break; case ZSTD_c_blockSplitterLevel : diff --git a/lib/zstd.h b/lib/zstd.h index cc5bb9879..ecf837bc9 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -491,12 +491,12 @@ typedef enum { * ZSTD_c_stableOutBuffer * ZSTD_c_blockDelimiters * ZSTD_c_validateSequences - * ZSTD_c_useBlockSplitter + * ZSTD_c_blockSplitterLevel + * ZSTD_c_splitAfterSequences * ZSTD_c_useRowMatchFinder * ZSTD_c_prefetchCDictTables * ZSTD_c_enableSeqProducerFallback * ZSTD_c_maxBlockSize - * ZSTD_c_blockSplitterLevel * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly; * also, the enums values themselves are unstable and can still change. @@ -2150,8 +2150,32 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo */ #define ZSTD_c_validateSequences ZSTD_c_experimentalParam12 -/* ZSTD_c_useBlockSplitter - * Controlled with ZSTD_paramSwitch_e enum. +/* ZSTD_c_blockSplitterLevel + * note: this parameter only influences the first splitter stage, + * which is active before producing the sequences. + * ZSTD_c_splitAfterSequences controls the next splitter stage, + * which is active after sequence production. + * Note that both can be combined. + * Allowed values are between 0 and ZSTD_BLOCKSPLITTER_LEVEL_MAX included. + * 0 means "auto", which will select a value depending on current ZSTD_c_strategy. + * 1 means no splitting. + * Then, values from 2 to 6 are sorted in increasing cpu load order. + * + * Note that currently the first block is never split, + * to ensure expansion guarantees in presence of incompressible data. + */ +#define ZSTD_BLOCKSPLITTER_LEVEL_MAX 6 +#define ZSTD_c_blockSplitterLevel ZSTD_c_experimentalParam20 + +/* ZSTD_c_splitAfterSequences + * This is a stronger splitter algorithm, + * based on actual sequences previously produced by the selected parser. + * It's also slower, and as a consequence, mostly used for high compression levels. + * While the post-splitter does overlap with the pre-splitter, + * both can nonetheless be combined, + * notably with ZSTD_c_blockSplitterLevel at ZSTD_BLOCKSPLITTER_LEVEL_MAX, + * resulting in higher compression ratio than just one of them. + * * Default is ZSTD_ps_auto. * Set to ZSTD_ps_disable to never use block splitter. * Set to ZSTD_ps_enable to always use block splitter. @@ -2159,7 +2183,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use * block splitting based on the compression parameters. */ -#define ZSTD_c_useBlockSplitter ZSTD_c_experimentalParam13 +#define ZSTD_c_splitAfterSequences ZSTD_c_experimentalParam13 /* ZSTD_c_useRowMatchFinder * Controlled with ZSTD_paramSwitch_e enum. @@ -2265,23 +2289,6 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo */ #define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 -/* ZSTD_c_blockSplitterLevel - * note: this parameter only influences the first splitter stage, - * which is active before producing the sequences. - * ZSTD_c_useBlockSplitter influence the next splitter stage, - * which is active after sequence production, - * and is more accurate but also slower. - * Both can be combined. - * Allowed values are between 0 and 6. - * 0 means "auto", which will select a value depending on current ZSTD_c_strategy. - * 1 means no splitting. - * Then, values from 2 to 6 are sorted in increasing cpu load order. - * - * Note that currently the first block is never split, - * to ensure expansion guarantees in presence of incompressible data. - */ -#define ZSTD_BLOCKSPLITTER_LEVEL_MAX 6 -#define ZSTD_c_blockSplitterLevel ZSTD_c_experimentalParam20 /*! ZSTD_CCtx_getParameter() : * Get the requested compression parameter value, selected by enum ZSTD_cParameter, diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c index f4cb10823..c89e448d0 100644 --- a/tests/fuzz/zstd_helpers.c +++ b/tests/fuzz/zstd_helpers.c @@ -140,7 +140,8 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer setRand(cctx, ZSTD_c_forceMaxWindow, 0, 1, producer); setRand(cctx, ZSTD_c_literalCompressionMode, 0, 2, producer); setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, producer); - setRand(cctx, ZSTD_c_useBlockSplitter, 0, 2, producer); + setRand(cctx, ZSTD_c_blockSplitterLevel, 0, ZSTD_BLOCKSPLITTER_LEVEL_MAX, producer); + setRand(cctx, ZSTD_c_splitAfterSequences, 0, 2, producer); setRand(cctx, ZSTD_c_deterministicRefPrefix, 0, 1, producer); setRand(cctx, ZSTD_c_prefetchCDictTables, 0, 2, producer); setRand(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX_MIN, ZSTD_BLOCKSIZE_MAX, producer); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 08c2662fb..4a6ebd69c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1420,7 +1420,7 @@ static int basicUnitTests(U32 const seed, double compressibility) CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19)); CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7)); - CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_useBlockSplitter, ZSTD_ps_enable)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_splitAfterSequences, ZSTD_ps_enable)); cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, data, srcSize); CHECK_Z(cSize); @@ -1737,8 +1737,8 @@ static int basicUnitTests(U32 const seed, double compressibility) { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); int value; ZSTD_compressionParameters cparams = ZSTD_getCParams(1, 0, 0); - cparams.strategy = -1; - /* Set invalid cParams == no change. */ + cparams.strategy = (ZSTD_strategy)-1; /* set invalid value, on purpose */ + /* Set invalid cParams == error out, and no change. */ CHECK(ZSTD_isError(ZSTD_CCtx_setCParams(cctx, cparams))); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); @@ -1801,12 +1801,12 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_freeCCtx(cctx); } - DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_setCarams() : ", testNb++); + DISPLAYLEVEL(3, "test%3d : ZSTD_CCtx_setParams() : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); int value; ZSTD_parameters params = ZSTD_getParams(1, 0, 0); - params.cParams.strategy = -1; - /* Set invalid params == no change. */ + params.cParams.strategy = (ZSTD_strategy)-1; /* set invalid value, on purpose */ + /* Set invalid params == error out, and no change. */ CHECK(ZSTD_isError(ZSTD_CCtx_setParams(cctx, params))); CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value)); @@ -2252,7 +2252,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : compress with block splitting : ", testNb++) { ZSTD_CCtx* cctx = ZSTD_createCCtx(); - CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_useBlockSplitter, ZSTD_ps_enable) ); + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_splitAfterSequences, ZSTD_ps_enable) ); cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); CHECK_Z(cSize); ZSTD_freeCCtx(cctx); From d9553fd2180535a11dcb4e2f5a3197202befc2c0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 31 Oct 2024 14:04:11 -0700 Subject: [PATCH 163/405] elevated ZSTD_getErrorCode() to stable status answering #4183 --- doc/zstd_manual.html | 149 ++++++++++++++++++++++++------------------- lib/zstd.h | 44 ++++++++----- lib/zstd_errors.h | 8 --- 3 files changed, 109 insertions(+), 92 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 56bfbcd81..7a1cbbd3e 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -10,7 +10,7 @@
  1. Introduction
  2. Version
  3. -
  4. Simple API
  5. +
  6. Simple Core API
  7. Explicit context
  8. Advanced compression API (Requires v1.4.0+)
  9. Advanced decompression API (Requires v1.4.0+)
  10. @@ -74,7 +74,7 @@

    Return runtime library version, like "1.4.5". Requires v1.3.0+.


    -

    Simple API

    
    +

    Simple Core API

    
     
     
    size_t ZSTD_compress( void* dst, size_t dstCapacity,
                     const void* src, size_t srcSize,
    @@ -88,38 +88,42 @@
     
     
    size_t ZSTD_decompress( void* dst, size_t dstCapacity,
                       const void* src, size_t compressedSize);
    -

    `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. - `dstCapacity` is an upper bound of originalSize to regenerate. - If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. - @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), - or an errorCode if it fails (which can be tested using ZSTD_isError()). +

    `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + Multiple compressed frames can be decompressed at once with this method. + The result will be the concatenation of all decompressed frames, back to back. + `dstCapacity` is an upper bound of originalSize to regenerate. + First frame's decompressed size can be extracted using ZSTD_getFrameContentSize(). + If maximum upper bound isn't known, prefer using streaming mode to decompress data. + @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + or an errorCode if it fails (which can be tested using ZSTD_isError()).


    +

    Decompression helper functions


    #define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
     #define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)
     unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
    -

    `src` should point to the start of a ZSTD encoded frame. - `srcSize` must be at least as large as the frame header. - hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. - @return : - decompressed size of `src` frame content, if known - - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) - note 1 : a 0 return value means the frame is valid but "empty". - note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. - When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - In which case, it's necessary to use streaming mode to decompress data. - Optionally, application can rely on some implicit limit, - as ZSTD_decompress() only needs an upper bound of decompressed size. - (For example, data could be necessarily cut into blocks <= 16 KB). - note 3 : decompressed size is always present when compression is completed using single-pass functions, - such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). - note 4 : decompressed size can be very large (64-bits value), - potentially larger than what local system can handle as a single memory segment. - In which case, it's necessary to use streaming mode to decompress data. - note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. - Always ensure return value fits within application's authorized limits. - Each application can set its own limits. - note 6 : This function replaces ZSTD_getDecompressedSize() +

    `src` should point to the start of a ZSTD encoded frame. + `srcSize` must be at least as large as the frame header. + hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. + @return : - decompressed size of `src` frame content, if known + - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) + note 1 : a 0 return value means the frame is valid but "empty". + note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode). + When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + In which case, it's necessary to use streaming mode to decompress data. + Optionally, application can rely on some implicit limit, + as ZSTD_decompress() only needs an upper bound of decompressed size. + (For example, data could be necessarily cut into blocks <= 16 KB). + note 3 : decompressed size is always present when compression is completed using single-pass functions, + such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). + note 4 : decompressed size can be very large (64-bits value), + potentially larger than what local system can handle as a single memory segment. + In which case, it's necessary to use streaming mode to decompress data. + note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. + Always ensure return value fits within application's authorized limits. + Each application can set its own limits. + note 6 : This function replaces ZSTD_getDecompressedSize()


    ZSTD_DEPRECATED("Replaced by ZSTD_getFrameContentSize")
    @@ -140,35 +144,21 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
             or an error code if input is invalid 
     


    -

    Helper functions

    /* ZSTD_compressBound() :
    - * maximum compressed size in worst case single-pass scenario.
    - * When invoking `ZSTD_compress()` or any other one-pass compression function,
    - * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)
    - * as it eliminates one potential failure scenario,
    - * aka not enough room in dst buffer to write the compressed frame.
    - * Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE .
    - *        In which case, ZSTD_compressBound() will return an error code
    - *        which can be tested using ZSTD_isError().
    - *
    - * ZSTD_COMPRESSBOUND() :
    - * same as ZSTD_compressBound(), but as a macro.
    - * It can be used to produce constants, which can be useful for static allocation,
    - * for example to size a static array on stack.
    - * Will produce constant value 0 if srcSize too large.
    - */
    -#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)
    -#define ZSTD_COMPRESSBOUND(srcSize)   (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
    -size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
    +

    Compression helper functions


    +
    size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
    +

    +

    Error helper functions

    #include "zstd_errors.h" /* list of errors */
     /* ZSTD_isError() :
      * Most ZSTD_* functions returning a size_t value can be tested for error,
      * using ZSTD_isError().
      * @return 1 if error, 0 otherwise
      */
    -unsigned    ZSTD_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */
    -const char* ZSTD_getErrorName(size_t code);     /*!< provides readable string from an error code */
    -int         ZSTD_minCLevel(void);               /*!< minimum negative compression level allowed, requires v1.4.0+ */
    -int         ZSTD_maxCLevel(void);               /*!< maximum compression level available */
    -int         ZSTD_defaultCLevel(void);           /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
    +unsigned     ZSTD_isError(size_t code);        /*!< tells if a `size_t` function result is an error code */
    +ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); /* convert a result into an error code, which can be compared to error enum list */
    +const char*  ZSTD_getErrorName(size_t code);   /*!< provides readable string from an error code */
    +int          ZSTD_minCLevel(void);             /*!< minimum negative compression level allowed, requires v1.4.0+ */
    +int          ZSTD_maxCLevel(void);             /*!< maximum compression level available */
    +int          ZSTD_defaultCLevel(void);         /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
     

    Explicit context

    
     
    @@ -718,7 +708,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
     

    Streaming decompression - HowTo

       A ZSTD_DStream object is required to track streaming operations.
       Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
    -  ZSTD_DStream objects can be reused multiple times.
    +  ZSTD_DStream objects can be re-employed multiple times.
     
       Use ZSTD_initDStream() to start a new decompression operation.
      @return : recommended first input size
    @@ -728,16 +718,21 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
       The function will update both `pos` fields.
       If `input.pos < input.size`, some input has not been consumed.
       It's up to the caller to present again remaining data.
    +
       The function tries to flush all data decoded immediately, respecting output buffer size.
       If `output.pos < output.size`, decoder has flushed everything it could.
    -  But if `output.pos == output.size`, there might be some data left within internal buffers.,
    +
    +  However, when `output.pos == output.size`, it's more difficult to know.
    +  If @return > 0, the frame is not complete, meaning
    +  either there is still some data left to flush within internal buffers,
    +  or there is more input to read to complete the frame (or both).
       In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
       Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
      @return : 0 when a frame is completely decoded and fully flushed,
             or an error code, which can be tested using ZSTD_isError(),
             or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
                                     the return value is a suggested next input size (just a hint for better latency)
    -                                that will never request more than the remaining frame size.
    +                                that will never request more than the remaining content of the compressed frame.
      
     
    @@ -763,9 +758,10 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds);
    /* accept NULL pointer */ Function will update both input and output `pos` fields exposing current state via these fields: - `input.pos < input.size`, some input remaining and caller should provide remaining input on the next call. - - `output.pos < output.size`, decoder finished and flushed all remaining buffers. - - `output.pos == output.size`, potentially uncflushed data present in the internal buffers, - call ZSTD_decompressStream() again to flush remaining data to output. + - `output.pos < output.size`, decoder flushed internal output buffer. + - `output.pos == output.size`, unflushed data potentially present in the internal buffers, + check ZSTD_decompressStream() @return value, + if > 0, invoke it again to flush remaining data to output. Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX. @return : 0 when a frame is completely decoded and fully flushed, @@ -1311,19 +1307,37 @@ ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr,


    -

    Generate sequences using ZSTD_compress2(), given a source buffer. +

    ZSTD_DEPRECATED("For debugging only, will be replaced by ZSTD_extractSequences()")
    +ZSTDLIB_STATIC_API size_t
    +ZSTD_generateSequences(ZSTD_CCtx* zc,
    +           ZSTD_Sequence* outSeqs, size_t outSeqsSize,
    +           const void* src, size_t srcSize);
    +

    WARNING: This function is meant for debugging and informational purposes ONLY! + Its implementation is flawed, and it will be deleted in a future version. + It is not guaranteed to succeed, as there are several cases where it will give + up and fail. You should NOT use this function in production code. + + This function is deprecated, and will be removed in a future version. + + Generate sequences using ZSTD_compress2(), given a source buffer. + + @param zc The compression context to be used for ZSTD_compress2(). Set any + compression parameters you need on this context. + @param outSeqs The output sequences buffer of size @p outSeqsSize + @param outSeqsSize The size of the output sequences buffer. + ZSTD_sequenceBound(srcSize) is an upper bound on the number + of sequences that can be generated. + @param src The source buffer to generate sequences from of size @p srcSize. + @param srcSize The size of the source buffer. Each block will end with a dummy sequence with offset == 0, matchLength == 0, and litLength == length of last literals. litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0) simply acts as a block delimiter. - @zc can be used to insert custom compression params. - This function invokes ZSTD_compress2(). - - The output of this function can be fed into ZSTD_compressSequences() with CCtx - setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters - @return : number of sequences generated + @returns The number of sequences generated, necessarily less than + ZSTD_sequenceBound(srcSize), or an error code that can be checked + with ZSTD_isError().


    @@ -1512,13 +1526,14 @@ static #ifdef __GNUC__ __attribute__((__unused__)) #endif -ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };
    /**< this constant defers to stdlib's functions */

    These prototypes make it possible to pass your own allocation/free functions. ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. All allocation/free operations will be completed using these custom variants instead of regular ones.


    +
    ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };  /**< this constant defers to stdlib's functions */
    +

    typedef struct POOL_ctx_s ZSTD_threadPool;
     ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
     ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool);  /* accept NULL pointer */
    diff --git a/lib/zstd.h b/lib/zstd.h
    index ecf837bc9..22aca768c 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -15,7 +15,6 @@ extern "C" {
     #define ZSTD_H_235446
     
     /* ======   Dependencies   ======*/
    -#include    /* INT_MAX */
     #include    /* size_t */
     
     
    @@ -106,7 +105,7 @@ extern "C" {
     /*------   Version   ------*/
     #define ZSTD_VERSION_MAJOR    1
     #define ZSTD_VERSION_MINOR    5
    -#define ZSTD_VERSION_RELEASE  6
    +#define ZSTD_VERSION_RELEASE  7
     #define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
     
     /*! ZSTD_versionNumber() :
    @@ -144,7 +143,7 @@ ZSTDLIB_API const char* ZSTD_versionString(void);
     
     
     /***************************************
    -*  Simple API
    +*  Simple Core API
     ***************************************/
     /*! ZSTD_compress() :
      *  Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
    @@ -168,6 +167,9 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
     ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
                                   const void* src, size_t compressedSize);
     
    +
    +/*======  Decompression helper functions  ======*/
    +
     /*! ZSTD_getFrameContentSize() : requires v1.3.0+
      * `src` should point to the start of a ZSTD encoded frame.
      * `srcSize` must be at least as large as the frame header.
    @@ -214,10 +216,11 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
     ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
     
     
    -/*======  Helper functions  ======*/
    +/*======  Compression helper functions  ======*/
    +
     /* ZSTD_compressBound() :
      * maximum compressed size in worst case single-pass scenario.
    - * When invoking `ZSTD_compress()` or any other one-pass compression function,
    + * When invoking `ZSTD_compress()`, or any other one-pass compression function,
      * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)
      * as it eliminates one potential failure scenario,
      * aka not enough room in dst buffer to write the compressed frame.
    @@ -229,21 +232,26 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
      * same as ZSTD_compressBound(), but as a macro.
      * It can be used to produce constants, which can be useful for static allocation,
      * for example to size a static array on stack.
    - * Will produce constant value 0 if srcSize too large.
    + * Will produce constant value 0 if srcSize is too large.
      */
     #define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)
     #define ZSTD_COMPRESSBOUND(srcSize)   (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
     ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
    +
    +
    +/*======  Error helper functions  ======*/
    +#include "zstd_errors.h" /* list of errors */
     /* ZSTD_isError() :
      * Most ZSTD_* functions returning a size_t value can be tested for error,
      * using ZSTD_isError().
      * @return 1 if error, 0 otherwise
      */
    -ZSTDLIB_API unsigned    ZSTD_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */
    -ZSTDLIB_API const char* ZSTD_getErrorName(size_t code);     /*!< provides readable string from an error code */
    -ZSTDLIB_API int         ZSTD_minCLevel(void);               /*!< minimum negative compression level allowed, requires v1.4.0+ */
    -ZSTDLIB_API int         ZSTD_maxCLevel(void);               /*!< maximum compression level available */
    -ZSTDLIB_API int         ZSTD_defaultCLevel(void);           /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
    +ZSTDLIB_API unsigned     ZSTD_isError(size_t result);      /*!< tells if a `size_t` function result is an error code */
    +ZSTDLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); /* convert a result into an error code, which can be compared to error enum list */
    +ZSTDLIB_API const char*  ZSTD_getErrorName(size_t result); /*!< provides readable string from a function result */
    +ZSTDLIB_API int          ZSTD_minCLevel(void);             /*!< minimum negative compression level allowed, requires v1.4.0+ */
    +ZSTDLIB_API int          ZSTD_maxCLevel(void);             /*!< maximum compression level available */
    +ZSTDLIB_API int          ZSTD_defaultCLevel(void);         /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
     
     
     /***************************************
    @@ -251,17 +259,17 @@ ZSTDLIB_API int         ZSTD_defaultCLevel(void);           /*!< default compres
     ***************************************/
     /*= Compression context
      *  When compressing many times,
    - *  it is recommended to allocate a context just once,
    + *  it is recommended to allocate a compression context just once,
      *  and reuse it for each successive compression operation.
    - *  This will make workload friendlier for system's memory.
    + *  This will make the workload easier for system's memory.
      *  Note : re-using context is just a speed / resource optimization.
      *         It doesn't change the compression ratio, which remains identical.
    - *  Note 2 : In multi-threaded environments,
    - *         use one different context per thread for parallel execution.
    + *  Note 2: For parallel execution in multi-threaded environments,
    + *         use one different context per thread .
      */
     typedef struct ZSTD_CCtx_s ZSTD_CCtx;
     ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
    -ZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* accept NULL pointer */
    +ZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* compatible with NULL pointer */
     
     /*! ZSTD_compressCCtx() :
      *  Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
    @@ -269,7 +277,7 @@ ZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* accept NULL pointer *
      *  this function compresses at the requested compression level,
      *  __ignoring any other advanced parameter__ .
      *  If any advanced parameter was set using the advanced API,
    - *  they will all be reset. Only `compressionLevel` remains.
    + *  they will all be reset. Only @compressionLevel remains.
      */
     ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
                                          void* dst, size_t dstCapacity,
    @@ -1207,6 +1215,8 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
     #if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
     #define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
     
    +#include    /* INT_MAX */
    +
     /* This can be overridden externally to hide static symbols. */
     #ifndef ZSTDLIB_STATIC_API
     #  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
    diff --git a/lib/zstd_errors.h b/lib/zstd_errors.h
    index dc75eeeba..20e488f15 100644
    --- a/lib/zstd_errors.h
    +++ b/lib/zstd_errors.h
    @@ -15,10 +15,6 @@
     extern "C" {
     #endif
     
    -/*===== dependency =====*/
    -#include    /* size_t */
    -
    -
     /* =====   ZSTDERRORLIB_API : control library symbols visibility   ===== */
     #ifndef ZSTDERRORLIB_VISIBLE
        /* Backwards compatibility with old macro name */
    @@ -100,10 +96,6 @@ typedef enum {
       ZSTD_error_maxCode = 120  /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
     } ZSTD_ErrorCode;
     
    -/*! ZSTD_getErrorCode() :
    -    convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
    -    which can be used to compare with enum list published above */
    -ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
     ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);   /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
     
     
    
    From adbb536d00a1a67f2654040fd201760e2abfb20c Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Thu, 31 Oct 2024 14:38:36 -0700
    Subject: [PATCH 164/405] fixed single file library test
    
    copy "zstd_errors.h" alongside "zstd.h" to pass compilation test.
    ---
     build/single_file_libs/build_library_test.sh | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/build/single_file_libs/build_library_test.sh b/build/single_file_libs/build_library_test.sh
    index f4ba109ab..b67cd99a0 100755
    --- a/build/single_file_libs/build_library_test.sh
    +++ b/build/single_file_libs/build_library_test.sh
    @@ -70,6 +70,7 @@ echo "Single file library creation script: PASSED"
     
     # Copy the header to here (for the tests)
     cp "$ZSTD_SRC_ROOT/zstd.h" examples/zstd.h
    +cp "$ZSTD_SRC_ROOT/zstd_errors.h" examples/zstd_errors.h
     
     # Compile the generated output
     cc -Wall -Wextra -Werror -Wshadow -pthread -I. -Os -g0 -o $OUT_FILE zstd.c examples/roundtrip.c
    
    From 2e02cd330dee3fcf9a8609b90ed7b965e0a6f9a1 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Thu, 31 Oct 2024 15:06:48 -0700
    Subject: [PATCH 165/405] inform manual users that it's automatically generated
    
    suggested by @Eugeny1
    ---
     contrib/gen_html/gen_html.cpp |  1 +
     doc/zstd_manual.html          | 49 +++++++++++++++++++++++++----------
     lib/zstd.h                    |  2 +-
     3 files changed, 37 insertions(+), 15 deletions(-)
    
    diff --git a/contrib/gen_html/gen_html.cpp b/contrib/gen_html/gen_html.cpp
    index 1da5879ad..adf0f41b9 100644
    --- a/contrib/gen_html/gen_html.cpp
    +++ b/contrib/gen_html/gen_html.cpp
    @@ -211,6 +211,7 @@ int main(int argc, char *argv[]) {
     
         ostream << "\n\n\n" << version << "\n\n" << endl;
         ostream << "

    " << version << "

    \n"; + ostream << "Note: the content of this file has been automatically generated by parsing \"zstd.h\" \n"; ostream << "
    \n

    Contents

    \n
      \n"; for (size_t i=0; i -zstd 1.5.6 Manual +zstd 1.5.7 Manual -

      zstd 1.5.6 Manual

      +

      zstd 1.5.7 Manual

      +Note: the content of this file has been automatically generated by parsing "zstd.h"

      Contents

        @@ -145,17 +146,35 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);


    Compression helper functions


    -
    size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
    -

    +
    #define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)
    +#define ZSTD_COMPRESSBOUND(srcSize)   (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
    +size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
    +

    maximum compressed size in worst case single-pass scenario. + When invoking `ZSTD_compress()`, or any other one-pass compression function, + it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize) + as it eliminates one potential failure scenario, + aka not enough room in dst buffer to write the compressed frame. + Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE . + In which case, ZSTD_compressBound() will return an error code + which can be tested using ZSTD_isError(). + + ZSTD_COMPRESSBOUND() : + same as ZSTD_compressBound(), but as a macro. + It can be used to produce constants, which can be useful for static allocation, + for example to size a static array on stack. + Will produce constant value 0 if srcSize is too large. + +


    +

    Error helper functions

    #include "zstd_errors.h" /* list of errors */
     /* ZSTD_isError() :
      * Most ZSTD_* functions returning a size_t value can be tested for error,
      * using ZSTD_isError().
      * @return 1 if error, 0 otherwise
      */
    -unsigned     ZSTD_isError(size_t code);        /*!< tells if a `size_t` function result is an error code */
    +unsigned     ZSTD_isError(size_t result);      /*!< tells if a `size_t` function result is an error code */
     ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); /* convert a result into an error code, which can be compared to error enum list */
    -const char*  ZSTD_getErrorName(size_t code);   /*!< provides readable string from an error code */
    +const char*  ZSTD_getErrorName(size_t result); /*!< provides readable string from a function result */
     int          ZSTD_minCLevel(void);             /*!< minimum negative compression level allowed, requires v1.4.0+ */
     int          ZSTD_maxCLevel(void);             /*!< maximum compression level available */
     int          ZSTD_defaultCLevel(void);         /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
    @@ -163,17 +182,17 @@ int          ZSTD_defaultCLevel(void);         /*!< default compression leve
     

    Explicit context

    
     
     

    Compression context

      When compressing many times,
    -  it is recommended to allocate a context just once,
    +  it is recommended to allocate a compression context just once,
       and reuse it for each successive compression operation.
    -  This will make workload friendlier for system's memory.
    +  This will make the workload easier for system's memory.
       Note : re-using context is just a speed / resource optimization.
              It doesn't change the compression ratio, which remains identical.
    -  Note 2 : In multi-threaded environments,
    -         use one different context per thread for parallel execution.
    +  Note 2: For parallel execution in multi-threaded environments,
    +         use one different context per thread .
      
     
    typedef struct ZSTD_CCtx_s ZSTD_CCtx;
     ZSTD_CCtx* ZSTD_createCCtx(void);
    -size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* accept NULL pointer */
    +size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* compatible with NULL pointer */
     

    size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
                              void* dst, size_t dstCapacity,
    @@ -184,7 +203,7 @@ size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* accept NULL pointer */
       this function compresses at the requested compression level,
       __ignoring any other advanced parameter__ .
       If any advanced parameter was set using the advanced API,
    -  they will all be reset. Only `compressionLevel` remains.
    +  they will all be reset. Only @compressionLevel remains.
      
     


    @@ -384,7 +403,8 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
    /* accept NULL pointer */ * ZSTD_c_stableOutBuffer * ZSTD_c_blockDelimiters * ZSTD_c_validateSequences - * ZSTD_c_useBlockSplitter + * ZSTD_c_blockSplitterLevel + * ZSTD_c_splitAfterSequences * ZSTD_c_useRowMatchFinder * ZSTD_c_prefetchCDictTables * ZSTD_c_enableSeqProducerFallback @@ -411,7 +431,8 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */ ZSTD_c_experimentalParam16=1013, ZSTD_c_experimentalParam17=1014, ZSTD_c_experimentalParam18=1015, - ZSTD_c_experimentalParam19=1016 + ZSTD_c_experimentalParam19=1016, + ZSTD_c_experimentalParam20=1017 } ZSTD_cParameter;

    typedef struct {
    diff --git a/lib/zstd.h b/lib/zstd.h
    index 22aca768c..d2d6795e4 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -218,7 +218,7 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
     
     /*======  Compression helper functions  ======*/
     
    -/* ZSTD_compressBound() :
    +/*! ZSTD_compressBound() :
      * maximum compressed size in worst case single-pass scenario.
      * When invoking `ZSTD_compress()`, or any other one-pass compression function,
      * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)
    
    From b3035b36c631614e32707cce0ab04c72c79c49a7 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Tue, 5 Nov 2024 00:09:13 -0800
    Subject: [PATCH 166/405] blind fix for QNX
    
    following notification from @rainbowball.
    fix #4186.
    
    Note: there is currently no QNX compilation test in CI
    so this is a "blind" fix,
    and this target can be silently broken again in the future.
    ---
     programs/util.h | 14 ++++++--------
     1 file changed, 6 insertions(+), 8 deletions(-)
    
    diff --git a/programs/util.h b/programs/util.h
    index 571d39421..ec8139684 100644
    --- a/programs/util.h
    +++ b/programs/util.h
    @@ -11,23 +11,18 @@
     #ifndef UTIL_H_MODULE
     #define UTIL_H_MODULE
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
     /*-****************************************
     *  Dependencies
     ******************************************/
     #include "platform.h"     /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */
     #include        /* size_t, ptrdiff_t */
    +#include         /* FILE */
     #include     /* stat, utime */
     #include      /* stat, chmod */
     #include "../lib/common/mem.h"          /* U64 */
     
    -
     /*-************************************************************
    -* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW
    +*  Fix fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW
     ***************************************************************/
     #if defined(_MSC_VER) && (_MSC_VER >= 1400)
     #  define UTIL_fseek _fseeki64
    @@ -39,7 +34,6 @@ extern "C" {
     #  define UTIL_fseek fseek
     #endif
     
    -
     /*-*************************************************
     *  Sleep & priority functions: Windows - Posix - others
     ***************************************************/
    @@ -88,6 +82,10 @@ extern "C" {
     #endif
     
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*-****************************************
     *  Console log
     ******************************************/
    
    From d0fe334c8552edb764b853854037697c6710fa64 Mon Sep 17 00:00:00 2001
    From: Lukas Oberhuber 
    Date: Fri, 8 Nov 2024 00:08:33 +0000
    Subject: [PATCH 167/405] cmake: Fix #4038 MacOS target older OS and SDK
     versions
    
    This fix ensures that when `MACOSX_DEPLOYMENT_TARGET` and `SDKROOT` are set, they are respected when building the libraries and executables.
    ---
     Makefile | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/Makefile b/Makefile
    index 95d45afb4..e80505b7f 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -200,9 +200,9 @@ travis-install:
     .PHONY: clangbuild-darwin-fat
     clangbuild-darwin-fat: clean
     	clang -v
    -	CXX=clang++ CC=clang CFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation -arch arm64" $(MAKE) zstd-release
    +	CXX=clang++ CC=clang CFLAGS+="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation -arch arm64" $(MAKE) zstd-release
     	mv programs/zstd programs/zstd_arm64
    -	CXX=clang++ CC=clang CFLAGS="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation -arch x86_64" $(MAKE) zstd-release
    +	CXX=clang++ CC=clang CFLAGS+="-Werror -Wconversion -Wno-sign-conversion -Wdocumentation -arch x86_64" $(MAKE) zstd-release
     	mv programs/zstd programs/zstd_x64
     	lipo -create programs/zstd_x64 programs/zstd_arm64 -output programs/zstd
     
    
    From 2d1bbc37ebf4cbf48a2f107a3816f3e137fb5d49 Mon Sep 17 00:00:00 2001
    From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
    Date: Mon, 11 Nov 2024 05:27:06 +0000
    Subject: [PATCH 168/405] Bump github/codeql-action from 3.26.2 to 3.27.1
    
    Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.2 to 3.27.1.
    - [Release notes](https://github.com/github/codeql-action/releases)
    - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/github/codeql-action/compare/429e1977040da7a23b6822b13c129cd1ba93dbb2...4f3212b61783c3c68e8309a0f18a699764811cda)
    
    ---
    updated-dependencies:
    - dependency-name: github/codeql-action
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] 
    ---
     .github/workflows/scorecards.yml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
    index ccd7956a5..0ae40d859 100644
    --- a/.github/workflows/scorecards.yml
    +++ b/.github/workflows/scorecards.yml
    @@ -59,6 +59,6 @@ jobs:
     
           # Upload the results to GitHub's code scanning dashboard.
           - name: "Upload to code-scanning"
    -        uses: github/codeql-action/upload-sarif@429e1977040da7a23b6822b13c129cd1ba93dbb2 # tag=v3.26.2
    +        uses: github/codeql-action/upload-sarif@4f3212b61783c3c68e8309a0f18a699764811cda # tag=v3.27.1
             with:
               sarif_file: results.sarif
    
    From a9d279c97c76f3d5018f96fd4f65b28cb501e3ad Mon Sep 17 00:00:00 2001
    From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
    Date: Mon, 18 Nov 2024 05:12:44 +0000
    Subject: [PATCH 169/405] Bump msys2/setup-msys2 from 2.24.1 to 2.25.0
    
    Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.24.1 to 2.25.0.
    - [Release notes](https://github.com/msys2/setup-msys2/releases)
    - [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/msys2/setup-msys2/compare/ddf331adaebd714795f1042345e6ca57bd66cea8...c52d1fa9c7492275e60fe763540fb601f5f232a1)
    
    ---
    updated-dependencies:
    - dependency-name: msys2/setup-msys2
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] 
    ---
     .github/workflows/dev-long-tests.yml    | 2 +-
     .github/workflows/dev-short-tests.yml   | 2 +-
     .github/workflows/windows-artifacts.yml | 2 +-
     3 files changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml
    index fa603e401..043f42356 100644
    --- a/.github/workflows/dev-long-tests.yml
    +++ b/.github/workflows/dev-long-tests.yml
    @@ -263,7 +263,7 @@ jobs:
             shell: msys2 {0}
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
    -    - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # tag=v2.24.1
    +    - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # tag=v2.25.0
           with:
             msystem: MINGW64
             install: make
    diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml
    index 99aa166c9..5e459aabf 100644
    --- a/.github/workflows/dev-short-tests.yml
    +++ b/.github/workflows/dev-short-tests.yml
    @@ -499,7 +499,7 @@ jobs:
             shell: msys2 {0}
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
    -    - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # tag=v2.24.1
    +    - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # tag=v2.25.0
           with:
             msystem: ${{ matrix.msystem }}
             install: make diffutils
    diff --git a/.github/workflows/windows-artifacts.yml b/.github/workflows/windows-artifacts.yml
    index ff81b504a..0524d5f63 100644
    --- a/.github/workflows/windows-artifacts.yml
    +++ b/.github/workflows/windows-artifacts.yml
    @@ -24,7 +24,7 @@ jobs:
             shell: msys2 {0}
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
    -    - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # tag=v2.24.1
    +    - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # tag=v2.25.0
           with:
             msystem: ${{ matrix.msystem }}
             install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc
    
    From 194062a4e73fef16e29e9175426fe1a3b9b23a73 Mon Sep 17 00:00:00 2001
    From: Dimitrios Apostolou 
    Date: Wed, 20 Nov 2024 16:11:17 +0100
    Subject: [PATCH 170/405] Fix printing of filesize if >4GB
    
    ---
     programs/zstdcli.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/programs/zstdcli.c b/programs/zstdcli.c
    index 8f94352fe..90e090b58 100644
    --- a/programs/zstdcli.c
    +++ b/programs/zstdcli.c
    @@ -696,7 +696,7 @@ static void printDefaultCParams(const char* filename, const char* dictFileName,
         unsigned long long fileSize = UTIL_getFileSize(filename);
         const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;
         const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
    -    if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filename, (unsigned)fileSize);
    +    if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%llu bytes)\n", filename, fileSize);
         else DISPLAY("%s (src size unknown)\n", filename);
         DISPLAY(" - windowLog     : %u\n", cParams.windowLog);
         DISPLAY(" - chainLog      : %u\n", cParams.chainLog);
    
    From 10beb7cb53ba328722d82c271d7b450b97869c92 Mon Sep 17 00:00:00 2001
    From: nhz2 
    Date: Sun, 24 Nov 2024 19:05:15 -0500
    Subject: [PATCH 171/405] Fix typo in ZSTD_compressBound docs
    
    ---
     lib/zstd.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/zstd.h b/lib/zstd.h
    index d2d6795e4..a78b6db45 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -224,7 +224,7 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
      * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)
      * as it eliminates one potential failure scenario,
      * aka not enough room in dst buffer to write the compressed frame.
    - * Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE .
    + * Note : ZSTD_compressBound() itself can fail, if @srcSize >= ZSTD_MAX_INPUT_SIZE .
      *        In which case, ZSTD_compressBound() will return an error code
      *        which can be tested using ZSTD_isError().
      *
    
    From b683c0dbe278f71e371376847deebd44fdcf392f Mon Sep 17 00:00:00 2001
    From: Robert Rose 
    Date: Sun, 24 Nov 2024 23:36:53 +0100
    Subject: [PATCH 172/405] prevent possible segfault when creating seek table
    
    Add a check whether the seek table of a `ZSTD_seekable` is initialized
    before creating a new seek table from it. Return `NULL`, if the check
    fails.
    ---
     contrib/seekable_format/zstdseek_decompress.c | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/contrib/seekable_format/zstdseek_decompress.c b/contrib/seekable_format/zstdseek_decompress.c
    index 4fefc5f2e..5ee6e0541 100644
    --- a/contrib/seekable_format/zstdseek_decompress.c
    +++ b/contrib/seekable_format/zstdseek_decompress.c
    @@ -252,6 +252,8 @@ size_t ZSTD_seekable_free(ZSTD_seekable* zs)
     
     ZSTD_seekTable* ZSTD_seekTable_create_fromSeekable(const ZSTD_seekable* zs)
     {
    +    assert(zs != NULL);
    +    if (zs->seekTable.entries == NULL) return NULL;
         ZSTD_seekTable* const st = (ZSTD_seekTable*)malloc(sizeof(ZSTD_seekTable));
         if (st==NULL) return NULL;
     
    
    From fcf88ae39b560f8605f8e7c56e243cb1a3a98e5c Mon Sep 17 00:00:00 2001
    From: Dimitri Papadopoulos
     <3234522+DimitriPapadopoulos@users.noreply.github.com>
    Date: Tue, 26 Nov 2024 11:15:39 +0100
    Subject: [PATCH 173/405] Fix new typos found by codespell
    
    ---
     doc/zstd_compression_format.md | 2 +-
     lib/compress/hist.h            | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md
    index 78279ce71..a2bf20cbc 100644
    --- a/doc/zstd_compression_format.md
    +++ b/doc/zstd_compression_format.md
    @@ -1120,7 +1120,7 @@ For the purpose of counting total allocated probability points, it counts as one
     
     Symbols probabilities are read one by one, in order.
     After each probability is decoded, the total nb of probability points is updated.
    -This is used to dermine how many bits must be read to decode the probability of next symbol.
    +This is used to determine how many bits must be read to decode the probability of next symbol.
     
     When a symbol has a __probability__ of `zero` (decoded from reading a Value `1`),
     it is followed by a 2-bits repeat flag.
    diff --git a/lib/compress/hist.h b/lib/compress/hist.h
    index e6e39d348..bea2a9ebf 100644
    --- a/lib/compress/hist.h
    +++ b/lib/compress/hist.h
    @@ -75,7 +75,7 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
                                const void* src, size_t srcSize);
     
     /*! HIST_add() :
    - *  Lowest level: just add nb of occurences of characters from @src into @count.
    + *  Lowest level: just add nb of occurrences of characters from @src into @count.
      *  @count is not reset. @count array is presumed large enough (i.e. 1 KB).
      @  This function does not need any additional stack memory.
      */
    
    From 5e0a83ec255a0f4bb6a3cf8c4abcae46bfc2c3c5 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?=E9=83=91=E8=8B=8F=E6=B3=A2=20=28Super=20Zheng=29?=
     
    Date: Wed, 7 Aug 2024 11:22:50 +0800
    Subject: [PATCH 174/405] Disallow 32-bit mode in clang section
    
    Fix register %rbx is only available in 64-bit mode
    ---
     lib/common/cpu.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/common/cpu.h b/lib/common/cpu.h
    index d9cdf8feb..3f15d560f 100644
    --- a/lib/common/cpu.h
    +++ b/lib/common/cpu.h
    @@ -35,7 +35,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
         U32 f7b = 0;
         U32 f7c = 0;
     #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
    -#if !defined(__clang__) || __clang_major__ >= 16
    +#if !defined(_M_X64) || !defined(__clang__) || __clang_major__ >= 16
         int reg[4];
         __cpuid((int*)reg, 0);
         {
    
    From c254ea097b017cac8f9b33856370afb729048035 Mon Sep 17 00:00:00 2001
    From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
    Date: Mon, 9 Dec 2024 05:38:13 +0000
    Subject: [PATCH 175/405] Bump msys2/setup-msys2 from 2.25.0 to 2.26.0
    
    Bumps [msys2/setup-msys2](https://github.com/msys2/setup-msys2) from 2.25.0 to 2.26.0.
    - [Release notes](https://github.com/msys2/setup-msys2/releases)
    - [Changelog](https://github.com/msys2/setup-msys2/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/msys2/setup-msys2/compare/c52d1fa9c7492275e60fe763540fb601f5f232a1...d44ca8e88d8b43d56cf5670f91747359d5537f97)
    
    ---
    updated-dependencies:
    - dependency-name: msys2/setup-msys2
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] 
    ---
     .github/workflows/dev-long-tests.yml    | 2 +-
     .github/workflows/dev-short-tests.yml   | 2 +-
     .github/workflows/windows-artifacts.yml | 2 +-
     3 files changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml
    index 043f42356..75c6f6653 100644
    --- a/.github/workflows/dev-long-tests.yml
    +++ b/.github/workflows/dev-long-tests.yml
    @@ -263,7 +263,7 @@ jobs:
             shell: msys2 {0}
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
    -    - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # tag=v2.25.0
    +    - uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # tag=v2.26.0
           with:
             msystem: MINGW64
             install: make
    diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml
    index 5e459aabf..7ed068d6e 100644
    --- a/.github/workflows/dev-short-tests.yml
    +++ b/.github/workflows/dev-short-tests.yml
    @@ -499,7 +499,7 @@ jobs:
             shell: msys2 {0}
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
    -    - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # tag=v2.25.0
    +    - uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # tag=v2.26.0
           with:
             msystem: ${{ matrix.msystem }}
             install: make diffutils
    diff --git a/.github/workflows/windows-artifacts.yml b/.github/workflows/windows-artifacts.yml
    index 0524d5f63..35999476e 100644
    --- a/.github/workflows/windows-artifacts.yml
    +++ b/.github/workflows/windows-artifacts.yml
    @@ -24,7 +24,7 @@ jobs:
             shell: msys2 {0}
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v3
    -    - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # tag=v2.25.0
    +    - uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # tag=v2.26.0
           with:
             msystem: ${{ matrix.msystem }}
             install: make zlib git p7zip mingw-w64-${{matrix.env}}-gcc
    
    From e190e7944e42309a60b31c9d025c877219e7f878 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Mon, 9 Dec 2024 10:53:38 -0800
    Subject: [PATCH 176/405] Update cmake minimum requirement to 3.10
    
    CMake warns on the current minimum requirement (3.5). Update to 3.10.
    This means support is still available for the default on Ubuntu 18.04, which
    exited LTS standard in April of 2023.
    [draft]
    ---
     build/cmake/CMakeLists.txt | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt
    index 399b818fc..b43671cc2 100644
    --- a/build/cmake/CMakeLists.txt
    +++ b/build/cmake/CMakeLists.txt
    @@ -7,7 +7,7 @@
     # in the COPYING file in the root directory of this source tree).
     # ################################################################
     
    -cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
    +cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
     
     # As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies.
     # Set and use the newest cmake policies that are validated to work
    
    From 4a4786bef0b5b4b4fb190de6816b4d9df503a5d8 Mon Sep 17 00:00:00 2001
    From: Diego Nieto Cid 
    Date: Tue, 10 Dec 2024 10:20:32 -0300
    Subject: [PATCH 177/405] tests: fix non-regular file test on GNU/Hurd
    
    Since commit b21b03ca6 [1] the behaviour of writes to /dev/zero has been
    fixed and now the non-regular file removal test no longer needs to be
    done on /dev/random (which no longer works as random is not writable now).
    
    [1] https://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=b21b03ca624b89caeedfe58430cea4b40317d39f
    ---
     tests/playTests.sh | 5 +----
     1 file changed, 1 insertion(+), 4 deletions(-)
    
    diff --git a/tests/playTests.sh b/tests/playTests.sh
    index 026490051..692e93e89 100755
    --- a/tests/playTests.sh
    +++ b/tests/playTests.sh
    @@ -109,10 +109,7 @@ isTerminal=${isTerminal:-$detectedTerminal}
     
     isWindows=false
     INTOVOID="/dev/null"
    -case "$UNAME" in
    -  GNU) DEVDEVICE="/dev/random" ;;
    -  *) DEVDEVICE="/dev/zero" ;;
    -esac
    +DEVDEVICE="/dev/zero"
     case "$OS" in
       Windows*)
         isWindows=true
    
    From 17beeb5d1a978cb7775d37ee5f2b184368262ef5 Mon Sep 17 00:00:00 2001
    From: daniellerozenblit <48103643+daniellerozenblit@users.noreply.github.com>
    Date: Thu, 12 Dec 2024 13:09:29 -0500
    Subject: [PATCH 178/405] Change CLI to employ multithreading by default
     (#4211)
    
    * Change CLI to employ multithreading by default
    
    * Document changes to benchmarking, print number of threads for display level >= 4, and add lower bound of 1 for the default number of threads
    ---
     programs/fileio_common.h | 11 ++++----
     programs/zstd.1.md       |  5 +++-
     programs/zstdcli.c       | 56 +++++++++++++++++++++-------------------
     3 files changed, 39 insertions(+), 33 deletions(-)
    
    diff --git a/programs/fileio_common.h b/programs/fileio_common.h
    index 55491b8e3..7a014ee4b 100644
    --- a/programs/fileio_common.h
    +++ b/programs/fileio_common.h
    @@ -28,11 +28,14 @@ extern "C" {
     #define GB *(1U<<30)
     #undef MAX
     #define MAX(a,b) ((a)>(b) ? (a) : (b))
    +#undef MIN  /* in case it would be already defined */
    +#define MIN(a,b)    ((a) < (b) ? (a) : (b))
     
     extern FIO_display_prefs_t g_display_prefs;
     
    -#define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
    -#define DISPLAYOUT(...)      fprintf(stdout, __VA_ARGS__)
    +#define DISPLAY_F(f, ...)    fprintf((f), __VA_ARGS__)
    +#define DISPLAYOUT(...)      DISPLAY_F(stdout, __VA_ARGS__)
    +#define DISPLAY(...)         DISPLAY_F(stderr, __VA_ARGS__)
     #define DISPLAYLEVEL(l, ...) { if (g_display_prefs.displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
     
     extern UTIL_time_t g_displayClock;
    @@ -56,10 +59,6 @@ extern UTIL_time_t g_displayClock;
     #define DISPLAYUPDATE_PROGRESS(...) { if (SHOULD_DISPLAY_PROGRESS()) { DISPLAYUPDATE(1, __VA_ARGS__); }}
     #define DISPLAY_SUMMARY(...) { if (SHOULD_DISPLAY_SUMMARY()) { DISPLAYLEVEL(1, __VA_ARGS__); } }
     
    -#undef MIN  /* in case it would be already defined */
    -#define MIN(a,b)    ((a) < (b) ? (a) : (b))
    -
    -
     #define EXM_THROW(error, ...)                                             \
     {                                                                         \
         DISPLAYLEVEL(1, "zstd: ");                                            \
    diff --git a/programs/zstd.1.md b/programs/zstd.1.md
    index fabf8d6fc..b4e848640 100644
    --- a/programs/zstd.1.md
    +++ b/programs/zstd.1.md
    @@ -343,7 +343,7 @@ If the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a
     
     `ZSTD_NBTHREADS` can be used to set the number of threads `zstd` will attempt to use during compression.
     If the value of `ZSTD_NBTHREADS` is not a valid unsigned integer, it will be ignored with a warning message.
    -`ZSTD_NBTHREADS` has a default value of (`1`), and is capped at ZSTDMT_NBWORKERS_MAX==200.
    +`ZSTD_NBTHREADS` has a default value of `max(1, min(4, nbCores/4))`, and is capped at ZSTDMT_NBWORKERS_MAX==200.
     `zstd` must be compiled with multithread support for this variable to have any effect.
     
     They can both be overridden by corresponding command line arguments:
    @@ -664,9 +664,12 @@ BENCHMARK
     The `zstd` CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer's performance.
     `zstd -b [FILE(s)]` will benchmark `zstd` for both compression and decompression using default compression level.
     Note that results are very dependent on the content being compressed.
    +
     It's possible to pass multiple files to the benchmark, and even a directory with `-r DIRECTORY`.
     When no `FILE` is provided, the benchmark will use a procedurally generated `lorem ipsum` text.
     
    +Benchmarking will employ `max(1, min(4, nbCores/4))` worker threads by default in order to match the behavior of the normal CLI I/O.
    +
     * `-b#`:
         benchmark file(s) using compression level #
     * `-e#`:
    diff --git a/programs/zstdcli.c b/programs/zstdcli.c
    index 90e090b58..024552d52 100644
    --- a/programs/zstdcli.c
    +++ b/programs/zstdcli.c
    @@ -8,22 +8,6 @@
      * You may select, at your option, one of the above-listed licenses.
      */
     
    -
    -/*-************************************
    -*  Tuning parameters
    -**************************************/
    -#ifndef ZSTDCLI_CLEVEL_DEFAULT
    -#  define ZSTDCLI_CLEVEL_DEFAULT 3
    -#endif
    -
    -#ifndef ZSTDCLI_CLEVEL_MAX
    -#  define ZSTDCLI_CLEVEL_MAX 19   /* without using --ultra */
    -#endif
    -
    -#ifndef ZSTDCLI_NBTHREADS_DEFAULT
    -#  define ZSTDCLI_NBTHREADS_DEFAULT 1
    -#endif
    -
     /*-************************************
     *  Dependencies
     **************************************/
    @@ -46,6 +30,23 @@
     #endif
     #include "../lib/zstd.h"  /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */
     #include "fileio_asyncio.h"
    +#include "fileio_common.h"
    +
    +/*-************************************
    +*  Tuning parameters
    +**************************************/
    +#ifndef ZSTDCLI_CLEVEL_DEFAULT
    +#  define ZSTDCLI_CLEVEL_DEFAULT 3
    +#endif
    +
    +#ifndef ZSTDCLI_CLEVEL_MAX
    +#  define ZSTDCLI_CLEVEL_MAX 19   /* without using --ultra */
    +#endif
    +
    +#ifndef ZSTDCLI_NBTHREADS_DEFAULT
    +#define ZSTDCLI_NBTHREADS_DEFAULT MAX(1, MIN(4, UTIL_countLogicalCores() / 4))
    +#endif
    +
     
     
     /*-************************************
    @@ -99,9 +100,7 @@ typedef enum { cover, fastCover, legacy } dictType;
     /*-************************************
     *  Display Macros
     **************************************/
    -#define DISPLAY_F(f, ...)    fprintf((f), __VA_ARGS__)
    -#define DISPLAYOUT(...)      DISPLAY_F(stdout, __VA_ARGS__)
    -#define DISPLAY(...)         DISPLAY_F(stderr, __VA_ARGS__)
    +#undef DISPLAYLEVEL
     #define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
     static int g_displayLevel = DISPLAY_LEVEL_DEFAULT;   /* 0 : no display,  1: errors,  2 : + result + interaction + warnings,  3 : + progression,  4 : + information */
     
    @@ -760,7 +759,7 @@ static int init_cLevel(void) {
     }
     
     #ifdef ZSTD_MULTITHREAD
    -static unsigned init_nbThreads(void) {
    +static unsigned default_nbThreads(void) {
         const char* const env = getenv(ENV_NBTHREADS);
         if (env != NULL) {
             const char* ptr = env;
    @@ -855,7 +854,7 @@ int main(int argCount, const char* argv[])
         ZSTD_paramSwitch_e mmapDict=ZSTD_ps_auto;
         ZSTD_paramSwitch_e useRowMatchFinder = ZSTD_ps_auto;
         FIO_compressionType_t cType = FIO_zstdCompression;
    -    unsigned nbWorkers = 0;
    +    int nbWorkers = -1; /* -1 means unset */
         double compressibility = -1.0;  /* lorem ipsum generator */
         unsigned bench_nbSeconds = 3;   /* would be better if this value was synchronized from bench */
         size_t blockSize = 0;
    @@ -896,7 +895,6 @@ int main(int argCount, const char* argv[])
     #endif
         ZSTD_paramSwitch_e literalCompressionMode = ZSTD_ps_auto;
     
    -
         /* init */
         checkLibVersion();
         (void)recursive; (void)cLevelLast;    /* not used when ZSTD_NOBENCH set */
    @@ -904,9 +902,6 @@ int main(int argCount, const char* argv[])
         assert(argCount >= 1);
         if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAYLEVEL(1, "zstd: allocation error \n"); exit(1); }
         programName = lastNameFromPath(programName);
    -#ifdef ZSTD_MULTITHREAD
    -    nbWorkers = init_nbThreads();
    -#endif
     
         /* preset behaviors */
         if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=0, singleThread=0;
    @@ -1298,7 +1293,7 @@ int main(int argCount, const char* argv[])
         DISPLAYLEVEL(3, WELCOME_MESSAGE);
     
     #ifdef ZSTD_MULTITHREAD
    -    if ((operation==zom_decompress) && (!singleThread) && (nbWorkers > 1)) {
    +    if ((operation==zom_decompress) && (nbWorkers > 1)) {
             DISPLAYLEVEL(2, "Warning : decompression does not support multi-threading\n");
         }
         if ((nbWorkers==0) && (!singleThread)) {
    @@ -1311,6 +1306,15 @@ int main(int argCount, const char* argv[])
                 DISPLAYLEVEL(3, "Note: %d physical core(s) detected \n", nbWorkers);
             }
         }
    +    /* Resolve to default if nbWorkers is still unset */
    +    if (nbWorkers == -1) {
    +      if (operation == zom_decompress) {
    +        nbWorkers = 1;
    +      } else {
    +        nbWorkers = default_nbThreads();
    +      }
    +    }
    +    DISPLAYLEVEL(4, "Compressing with %u worker threads \n", nbWorkers);
     #else
         (void)singleThread; (void)nbWorkers; (void)defaultLogicalCores;
     #endif
    
    From 1198a582d3c931c7faba149cbf1b48910da3f256 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 12 Dec 2024 11:39:40 -0800
    Subject: [PATCH 179/405] Update VERSION_LESS usage to VERSION_GREATER_THAN
    
    ---
     build/cmake/CMakeModules/AddZstdCompilationFlags.cmake | 9 ++++-----
     1 file changed, 4 insertions(+), 5 deletions(-)
    
    diff --git a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake
    index 6f55450c3..153c51bae 100644
    --- a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake
    +++ b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake
    @@ -1,11 +1,10 @@
     include(CheckCXXCompilerFlag)
     include(CheckCCompilerFlag)
    -# VERSION_GREATER_EQUAL requires CMake 3.7 or later.
    -# https://cmake.org/cmake/help/latest/command/if.html#version-greater-equal
    -if (CMAKE_VERSION VERSION_LESS 3.18)
    -    set(ZSTD_HAVE_CHECK_LINKER_FLAG false)
    -else ()
    +
    +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
         set(ZSTD_HAVE_CHECK_LINKER_FLAG true)
    +else ()
    +    set(ZSTD_HAVE_CHECK_LINKER_FLAG false)
     endif ()
     if (ZSTD_HAVE_CHECK_LINKER_FLAG)
         include(CheckLinkerFlag)
    
    From 7236e05b0a4f5e9c9435661fe7b2bfedeba29ec4 Mon Sep 17 00:00:00 2001
    From: Elliot Gorokhovsky 
    Date: Tue, 12 Mar 2024 08:26:01 -0700
    Subject: [PATCH 180/405] Revert "Pin tsan and msan CI jobs to ubuntu-20.04
     (#3945)"
    
    This reverts commit ee6acaf26bbf842837513087c91776b83d4d9560.
    ---
     .github/workflows/dev-long-tests.yml | 34 ++++++++++++++--------------
     1 file changed, 17 insertions(+), 17 deletions(-)
    
    diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml
    index 75c6f6653..d5e476b4c 100644
    --- a/.github/workflows/dev-long-tests.yml
    +++ b/.github/workflows/dev-long-tests.yml
    @@ -61,14 +61,14 @@ jobs:
           run: MOREFLAGS="-DZSTD_NO_INTRINSICS" make -C tests fuzztest
     
       tsan-zstreamtest:
    -    runs-on: ubuntu-20.04
    +    runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
         - name: thread sanitizer zstreamtest
           run: CC=clang ZSTREAM_TESTTIME=-T3mn make tsan-test-zstream
     
       ubsan-zstreamtest:
    -    runs-on: ubuntu-20.04
    +    runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
         - name: undefined behavior sanitizer zstreamtest
    @@ -76,7 +76,7 @@ jobs:
     
       # lasts ~15mn
       tsan-fuzztest:
    -    runs-on: ubuntu-20.04
    +    runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
         - name: thread sanitizer fuzztest
    @@ -95,7 +95,7 @@ jobs:
     
       # lasts ~23mn
       gcc-8-asan-ubsan-testzstd:
    -    runs-on: ubuntu-20.04
    +    runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1
         - name: gcc-8 + ASan + UBSan + Test Zstd
    @@ -107,14 +107,14 @@ jobs:
             CC=gcc-8 make -j uasan-test-zstd 
    Date: Sat, 14 Dec 2024 11:57:14 -0800
    Subject: [PATCH 181/405] minor: more accurate parameter
    
    just pass ldm_bucketLog, instead of the entire ldm* state
    ---
     lib/compress/zstd_ldm.c | 25 +++++++++++++------------
     1 file changed, 13 insertions(+), 12 deletions(-)
    
    diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
    index 17c069fe1..e06431374 100644
    --- a/lib/compress/zstd_ldm.c
    +++ b/lib/compress/zstd_ldm.c
    @@ -170,22 +170,22 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)
     /** ZSTD_ldm_getBucket() :
      *  Returns a pointer to the start of the bucket associated with hash. */
     static ldmEntry_t* ZSTD_ldm_getBucket(
    -        ldmState_t* ldmState, size_t hash, ldmParams_t const ldmParams)
    +        const ldmState_t* ldmState, size_t hash, U32 const bucketSizeLog)
     {
    -    return ldmState->hashTable + (hash << ldmParams.bucketSizeLog);
    +    return ldmState->hashTable + (hash << bucketSizeLog);
     }
     
     /** ZSTD_ldm_insertEntry() :
      *  Insert the entry with corresponding hash into the hash table */
     static void ZSTD_ldm_insertEntry(ldmState_t* ldmState,
                                      size_t const hash, const ldmEntry_t entry,
    -                                 ldmParams_t const ldmParams)
    +                                 U32 const bucketSizeLog)
     {
         BYTE* const pOffset = ldmState->bucketOffsets + hash;
         unsigned const offset = *pOffset;
     
    -    *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + offset) = entry;
    -    *pOffset = (BYTE)((offset + 1) & ((1u << ldmParams.bucketSizeLog) - 1));
    +    *(ZSTD_ldm_getBucket(ldmState, hash, bucketSizeLog) + offset) = entry;
    +    *pOffset = (BYTE)((offset + 1) & ((1u << bucketSizeLog) - 1));
     
     }
     
    @@ -273,7 +273,8 @@ void ZSTD_ldm_fillHashTable(
                 const BYTE* iend, ldmParams_t const* params)
     {
         U32 const minMatchLength = params->minMatchLength;
    -    U32 const hBits = params->hashLog - params->bucketSizeLog;
    +    U32 const bucketSizeLog = params->bucketSizeLog;
    +    U32 const hBits = params->hashLog - bucketSizeLog;
         BYTE const* const base = ldmState->window.base;
         BYTE const* const istart = ip;
         ldmRollingHashState_t hashState;
    @@ -288,7 +289,7 @@ void ZSTD_ldm_fillHashTable(
             unsigned n;
     
             numSplits = 0;
    -        hashed = ZSTD_ldm_gear_feed(&hashState, ip, iend - ip, splits, &numSplits);
    +        hashed = ZSTD_ldm_gear_feed(&hashState, ip, (size_t)(iend - ip), splits, &numSplits);
     
             for (n = 0; n < numSplits; n++) {
                 if (ip + splits[n] >= istart + minMatchLength) {
    @@ -299,7 +300,7 @@ void ZSTD_ldm_fillHashTable(
     
                     entry.offset = (U32)(split - base);
                     entry.checksum = (U32)(xxhash >> 32);
    -                ZSTD_ldm_insertEntry(ldmState, hash, entry, *params);
    +                ZSTD_ldm_insertEntry(ldmState, hash, entry, params->bucketSizeLog);
                 }
             }
     
    @@ -379,7 +380,7 @@ size_t ZSTD_ldm_generateSequences_internal(
                 candidates[n].split = split;
                 candidates[n].hash = hash;
                 candidates[n].checksum = (U32)(xxhash >> 32);
    -            candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *params);
    +            candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, params->bucketSizeLog);
                 PREFETCH_L1(candidates[n].bucket);
             }
     
    @@ -402,7 +403,7 @@ size_t ZSTD_ldm_generateSequences_internal(
                  * the previous one, we merely register it in the hash table and
                  * move on */
                 if (split < anchor) {
    -                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
    +                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);
                     continue;
                 }
     
    @@ -449,7 +450,7 @@ size_t ZSTD_ldm_generateSequences_internal(
                 /* No match found -- insert an entry into the hash table
                  * and process the next candidate match */
                 if (bestEntry == NULL) {
    -                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
    +                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);
                     continue;
                 }
     
    @@ -470,7 +471,7 @@ size_t ZSTD_ldm_generateSequences_internal(
     
                 /* Insert the current entry into the hash table --- it must be
                  * done after the previous block to avoid clobbering bestEntry */
    -            ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
    +            ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);
     
                 anchor = split + forwardMatchLength;
     
    
    From fc726da7747b159520de2edb0febab30342d2744 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Tue, 17 Dec 2024 17:55:07 -0800
    Subject: [PATCH 182/405] Move #includes out of `extern "C"` blocks
    
    Do some include shuffling for `**.h` files within lib, programs, tests, and zlibWrapper.
    `lib/legacy` and `lib/deprecated` are untouched.
    `#include`s within `extern "C"` blocks in .cpp files are untouched.
    
    todo: shuffling for `xxhash.h`
    ---
     contrib/seekable_format/zstd_seekable.h |  6 +++---
     lib/common/bitstream.h                  |  8 ++++----
     lib/common/debug.h                      |  9 ++++-----
     lib/common/error_private.h              |  8 +++-----
     lib/common/fse.h                        | 16 +++++++--------
     lib/common/huf.h                        |  7 +++----
     lib/common/mem.h                        |  8 ++++----
     lib/common/pool.h                       |  8 ++++----
     lib/common/threading.h                  | 27 +++++++++++++++++++++----
     lib/common/zstd_trace.h                 |  4 ++--
     lib/compress/zstd_double_fast.h         |  6 +++---
     lib/compress/zstd_fast.h                |  6 +++---
     lib/compress/zstd_lazy.h                |  4 ++--
     lib/compress/zstd_ldm.h                 |  6 +++---
     lib/compress/zstd_opt.h                 |  4 ++--
     lib/compress/zstdmt_compress.h          | 11 +++++-----
     lib/zdict.h                             |  8 ++++----
     lib/zstd.h                              | 15 ++++++++------
     programs/benchfn.h                      |  8 ++++----
     programs/benchzstd.h                    |  8 ++++----
     programs/fileio_asyncio.h               |  8 ++++----
     programs/fileio_common.h                | 16 ++++++++++-----
     programs/platform.h                     | 21 +++++++++----------
     programs/timefn.h                       | 11 +++++-----
     programs/util.c                         |  9 ---------
     programs/util.h                         |  4 +++-
     zlibWrapper/zstd_zlibwrapper.h          | 10 ++++-----
     27 files changed, 135 insertions(+), 121 deletions(-)
    
    diff --git a/contrib/seekable_format/zstd_seekable.h b/contrib/seekable_format/zstd_seekable.h
    index a0e5e3573..b1f83d0e0 100644
    --- a/contrib/seekable_format/zstd_seekable.h
    +++ b/contrib/seekable_format/zstd_seekable.h
    @@ -1,13 +1,13 @@
     #ifndef SEEKABLE_H
     #define SEEKABLE_H
     
    +#include 
    +#include "zstd.h"   /* ZSTDLIB_API */
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include 
    -#include "zstd.h"   /* ZSTDLIB_API */
    -
     
     #define ZSTD_seekTableFooterSize 9
     
    diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h
    index 676044989..bce91e801 100644
    --- a/lib/common/bitstream.h
    +++ b/lib/common/bitstream.h
    @@ -14,9 +14,6 @@
     #ifndef BITSTREAM_H_MODULE
     #define BITSTREAM_H_MODULE
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*
     *  This API consists of small unitary functions, which must be inlined for best performance.
     *  Since link-time-optimization is not available for all compilers,
    @@ -32,7 +29,6 @@ extern "C" {
     #include "error_private.h"  /* error codes and messages */
     #include "bits.h"           /* ZSTD_highbit32 */
     
    -
     /*=========================================
     *  Target specific
     =========================================*/
    @@ -44,6 +40,10 @@ extern "C" {
     #  endif
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     #define STREAM_ACCUMULATOR_MIN_32  25
     #define STREAM_ACCUMULATOR_MIN_64  57
     #define STREAM_ACCUMULATOR_MIN    ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
    diff --git a/lib/common/debug.h b/lib/common/debug.h
    index a16b69e57..8ef37a908 100644
    --- a/lib/common/debug.h
    +++ b/lib/common/debug.h
    @@ -32,10 +32,6 @@
     #ifndef DEBUG_H_12987983217
     #define DEBUG_H_12987983217
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     
     /* static assert is triggered at compile time, leaving no runtime artefact.
      * static assert only works with compile-time constants.
    @@ -75,9 +71,12 @@ extern "C" {
     #  endif
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     #if (DEBUGLEVEL>=2)
     #  define ZSTD_DEPS_NEED_IO
    -#  include "zstd_deps.h"
     extern int g_debuglevel; /* the variable is only declared,
                                 it actually lives in debug.c,
                                 and is shared by the whole process.
    diff --git a/lib/common/error_private.h b/lib/common/error_private.h
    index 0156010c7..06233aaa8 100644
    --- a/lib/common/error_private.h
    +++ b/lib/common/error_private.h
    @@ -13,11 +13,6 @@
     #ifndef ERROR_H_MODULE
     #define ERROR_H_MODULE
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
     /* ****************************************
     *  Dependencies
     ******************************************/
    @@ -26,6 +21,9 @@ extern "C" {
     #include "debug.h"
     #include "zstd_deps.h"       /* size_t */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     
     /* ****************************************
     *  Compiler-specific
    diff --git a/lib/common/fse.h b/lib/common/fse.h
    index 2ae128e60..4c41b06ef 100644
    --- a/lib/common/fse.h
    +++ b/lib/common/fse.h
    @@ -11,11 +11,6 @@
      * in the COPYING file in the root directory of this source tree).
      * You may select, at your option, one of the above-listed licenses.
     ****************************************************************** */
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #ifndef FSE_H
     #define FSE_H
     
    @@ -25,6 +20,14 @@ extern "C" {
     ******************************************/
     #include "zstd_deps.h"    /* size_t, ptrdiff_t */
     
    +#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
    +#define FSE_H_FSE_STATIC_LINKING_ONLY
    +#include "bitstream.h"
    +#endif 
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     
     /*-*****************************************
     *  FSE_PUBLIC_API : control library symbols visibility
    @@ -233,9 +236,6 @@ If there is an error, the function will return an error code, which can be teste
     #if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
     #define FSE_H_FSE_STATIC_LINKING_ONLY
     
    -/* *** Dependency *** */
    -#include "bitstream.h"
    -
     
     /* *****************************************
     *  Static allocation
    diff --git a/lib/common/huf.h b/lib/common/huf.h
    index 99bf85d6f..bfcec4a81 100644
    --- a/lib/common/huf.h
    +++ b/lib/common/huf.h
    @@ -12,10 +12,6 @@
      * You may select, at your option, one of the above-listed licenses.
     ****************************************************************** */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #ifndef HUF_H_298734234
     #define HUF_H_298734234
     
    @@ -25,6 +21,9 @@ extern "C" {
     #define FSE_STATIC_LINKING_ONLY
     #include "fse.h"
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     
     /* ***   Tool functions *** */
     #define HUF_BLOCKSIZE_MAX (128 * 1024)   /**< maximum input size for a single block compressed with HUF_compress */
    diff --git a/lib/common/mem.h b/lib/common/mem.h
    index a02141c9d..1b0a946ad 100644
    --- a/lib/common/mem.h
    +++ b/lib/common/mem.h
    @@ -11,10 +11,6 @@
     #ifndef MEM_H_MODULE
     #define MEM_H_MODULE
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-****************************************
     *  Dependencies
     ******************************************/
    @@ -77,6 +73,10 @@ extern "C" {
     #endif
     
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*-**************************************************************
     *  Memory I/O API
     *****************************************************************/
    diff --git a/lib/common/pool.h b/lib/common/pool.h
    index cca4de73a..d34082dc1 100644
    --- a/lib/common/pool.h
    +++ b/lib/common/pool.h
    @@ -11,15 +11,15 @@
     #ifndef POOL_H
     #define POOL_H
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     
     #include "zstd_deps.h"
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_customMem */
     #include "../zstd.h"
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     typedef struct POOL_ctx_s POOL_ctx;
     
     /*! POOL_create() :
    diff --git a/lib/common/threading.h b/lib/common/threading.h
    index fb5c1c878..25448548d 100644
    --- a/lib/common/threading.h
    +++ b/lib/common/threading.h
    @@ -16,10 +16,6 @@
     
     #include "debug.h"
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
     
     /**
    @@ -60,6 +56,11 @@ extern "C" {
     #define ZSTD_pthread_cond_signal(a)     WakeConditionVariable((a))
     #define ZSTD_pthread_cond_broadcast(a)  WakeAllConditionVariable((a))
     
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* ZSTD_pthread_create() and ZSTD_pthread_join() */
     typedef HANDLE ZSTD_pthread_t;
     
    @@ -73,10 +74,19 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread);
      */
     
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #elif defined(ZSTD_MULTITHREAD)    /* posix assumed ; need a better detection method */
     /* ===   POSIX Systems   === */
     #  include 
     
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     #if DEBUGLEVEL < 1
     
     #define ZSTD_pthread_mutex_t            pthread_mutex_t
    @@ -123,9 +133,18 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);
     
     #endif
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #else  /* ZSTD_MULTITHREAD not defined */
     /* No multithreading support */
     
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     typedef int ZSTD_pthread_mutex_t;
     #define ZSTD_pthread_mutex_init(a, b)   ((void)(a), (void)(b), 0)
     #define ZSTD_pthread_mutex_destroy(a)   ((void)(a))
    diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h
    index 173d63fb1..b9187079c 100644
    --- a/lib/common/zstd_trace.h
    +++ b/lib/common/zstd_trace.h
    @@ -11,12 +11,12 @@
     #ifndef ZSTD_TRACE_H
     #define ZSTD_TRACE_H
     
    +#include 
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include 
    -
     /* weak symbol support
      * For now, enable conservatively:
      * - Only GNUC
    diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h
    index ce6ed8c97..ae66f3142 100644
    --- a/lib/compress/zstd_double_fast.h
    +++ b/lib/compress/zstd_double_fast.h
    @@ -11,13 +11,13 @@
     #ifndef ZSTD_DOUBLE_FAST_H
     #define ZSTD_DOUBLE_FAST_H
     
    +#include "../common/mem.h"      /* U32 */
    +#include "zstd_compress_internal.h"     /* ZSTD_CCtx, size_t */
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include "../common/mem.h"      /* U32 */
    -#include "zstd_compress_internal.h"     /* ZSTD_CCtx, size_t */
    -
     #ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
     
     void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
    diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h
    index 9e4236b47..f92cf35b9 100644
    --- a/lib/compress/zstd_fast.h
    +++ b/lib/compress/zstd_fast.h
    @@ -11,13 +11,13 @@
     #ifndef ZSTD_FAST_H
     #define ZSTD_FAST_H
     
    +#include "../common/mem.h"      /* U32 */
    +#include "zstd_compress_internal.h"
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include "../common/mem.h"      /* U32 */
    -#include "zstd_compress_internal.h"
    -
     void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
                             void const* end, ZSTD_dictTableLoadMethod_e dtlm,
                             ZSTD_tableFillPurpose_e tfp);
    diff --git a/lib/compress/zstd_lazy.h b/lib/compress/zstd_lazy.h
    index 3635813bd..bec17b124 100644
    --- a/lib/compress/zstd_lazy.h
    +++ b/lib/compress/zstd_lazy.h
    @@ -11,12 +11,12 @@
     #ifndef ZSTD_LAZY_H
     #define ZSTD_LAZY_H
     
    +#include "zstd_compress_internal.h"
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include "zstd_compress_internal.h"
    -
     /**
      * Dedicated Dictionary Search Structure bucket log. In the
      * ZSTD_dedicatedDictSearch mode, the hashTable has
    diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h
    index f147021d2..847c2befb 100644
    --- a/lib/compress/zstd_ldm.h
    +++ b/lib/compress/zstd_ldm.h
    @@ -11,13 +11,13 @@
     #ifndef ZSTD_LDM_H
     #define ZSTD_LDM_H
     
    +#include "zstd_compress_internal.h"   /* ldmParams_t, U32 */
    +#include "../zstd.h"   /* ZSTD_CCtx, size_t */
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include "zstd_compress_internal.h"   /* ldmParams_t, U32 */
    -#include "../zstd.h"   /* ZSTD_CCtx, size_t */
    -
     /*-*************************************
     *  Long distance matching
     ***************************************/
    diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h
    index d4e711315..7ce6fdae7 100644
    --- a/lib/compress/zstd_opt.h
    +++ b/lib/compress/zstd_opt.h
    @@ -11,12 +11,12 @@
     #ifndef ZSTD_OPT_H
     #define ZSTD_OPT_H
     
    +#include "zstd_compress_internal.h"
    +
     #if defined (__cplusplus)
     extern "C" {
     #endif
     
    -#include "zstd_compress_internal.h"
    -
     #if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \
      || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \
      || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)
    diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h
    index ed4dc0e99..9a58b5ad3 100644
    --- a/lib/compress/zstdmt_compress.h
    +++ b/lib/compress/zstdmt_compress.h
    @@ -11,6 +11,11 @@
      #ifndef ZSTDMT_COMPRESS_H
      #define ZSTDMT_COMPRESS_H
     
    +/* ===   Dependencies   === */
    +#include "../common/zstd_deps.h"   /* size_t */
    +#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters */
    +#include "../zstd.h"            /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
    +
      #if defined (__cplusplus)
      extern "C" {
      #endif
    @@ -25,12 +30,6 @@
      *        otherwise ZSTDMT_createCCtx*() will fail.
      */
     
    -/* ===   Dependencies   === */
    -#include "../common/zstd_deps.h"   /* size_t */
    -#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters */
    -#include "../zstd.h"            /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
    -
    -
     /* ===   Constants   === */
     #ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */
     #  define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256)
    diff --git a/lib/zdict.h b/lib/zdict.h
    index bcccf750e..340a9a24e 100644
    --- a/lib/zdict.h
    +++ b/lib/zdict.h
    @@ -8,16 +8,16 @@
      * You may select, at your option, one of the above-listed licenses.
      */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #ifndef ZSTD_ZDICT_H
     #define ZSTD_ZDICT_H
     
    +
     /*======  Dependencies  ======*/
     #include   /* size_t */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     
     /* =====   ZDICTLIB_API : control library symbols visibility   ===== */
     #ifndef ZDICTLIB_VISIBLE
    diff --git a/lib/zstd.h b/lib/zstd.h
    index a78b6db45..7571f8069 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -7,16 +7,22 @@
      * in the COPYING file in the root directory of this source tree).
      * You may select, at your option, one of the above-listed licenses.
      */
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     
     #ifndef ZSTD_H_235446
     #define ZSTD_H_235446
     
    +
     /* ======   Dependencies   ======*/
     #include    /* size_t */
     
    +#include "zstd_errors.h" /* list of errors */
    +#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
    +#include    /* INT_MAX */
    +#endif /* ZSTD_STATIC_LINKING_ONLY */
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     
     /* =====   ZSTDLIB_API : control library symbols visibility   ===== */
     #ifndef ZSTDLIB_VISIBLE
    @@ -240,7 +246,6 @@ ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed s
     
     
     /*======  Error helper functions  ======*/
    -#include "zstd_errors.h" /* list of errors */
     /* ZSTD_isError() :
      * Most ZSTD_* functions returning a size_t value can be tested for error,
      * using ZSTD_isError().
    @@ -1215,8 +1220,6 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
     #if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
     #define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
     
    -#include    /* INT_MAX */
    -
     /* This can be overridden externally to hide static symbols. */
     #ifndef ZSTDLIB_STATIC_API
     #  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
    diff --git a/programs/benchfn.h b/programs/benchfn.h
    index 1bd93d135..3ba3a4f55 100644
    --- a/programs/benchfn.h
    +++ b/programs/benchfn.h
    @@ -15,10 +15,6 @@
      * or detecting and returning an error
      */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #ifndef BENCH_FN_H_23876
     #define BENCH_FN_H_23876
     
    @@ -26,6 +22,10 @@ extern "C" {
     #include    /* size_t */
     
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* ====  Benchmark any function, iterated on a set of blocks  ==== */
     
     /* BMK_runTime_t: valid result return type */
    diff --git a/programs/benchzstd.h b/programs/benchzstd.h
    index 6388d4d58..7ea018b12 100644
    --- a/programs/benchzstd.h
    +++ b/programs/benchzstd.h
    @@ -14,10 +14,6 @@
       * and display progress result and final summary
       */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #ifndef BENCH_ZSTD_H_3242387
     #define BENCH_ZSTD_H_3242387
     
    @@ -27,6 +23,10 @@ extern "C" {
     #include "../lib/zstd.h"     /* ZSTD_compressionParameters */
     
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* ===  Constants  === */
     
     #define MB_UNIT 1000000
    diff --git a/programs/fileio_asyncio.h b/programs/fileio_asyncio.h
    index feb25a3f9..1c30a73da 100644
    --- a/programs/fileio_asyncio.h
    +++ b/programs/fileio_asyncio.h
    @@ -22,10 +22,6 @@
     #ifndef ZSTD_FILEIO_ASYNCIO_H
     #define ZSTD_FILEIO_ASYNCIO_H
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #include "../lib/common/mem.h"     /* U32, U64 */
     #include "fileio_types.h"
     #include "platform.h"
    @@ -35,6 +31,10 @@ extern "C" {
     
     #define MAX_IO_JOBS          (10)
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     typedef struct {
         /* These struct fields should be set only on creation and not changed afterwards */
         POOL_ctx* threadPool;
    diff --git a/programs/fileio_common.h b/programs/fileio_common.h
    index 7a014ee4b..87f99cda9 100644
    --- a/programs/fileio_common.h
    +++ b/programs/fileio_common.h
    @@ -11,15 +11,22 @@
     #ifndef ZSTD_FILEIO_COMMON_H
     #define ZSTD_FILEIO_COMMON_H
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #include "../lib/common/mem.h"     /* U32, U64 */
     #include "fileio_types.h"
     #include "platform.h"
     #include "timefn.h"     /* UTIL_getTime, UTIL_clockSpanMicro */
     
    +#if !(defined(_MSC_VER) && _MSC_VER >= 1400) \
    +    && !(!defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L)) \
    +    && !(defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)) \
    +    && (defined(_WIN32) && !defined(__DJGPP__))
    +#   include 
    +#endif
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*-*************************************
     *  Macros
     ***************************************/
    @@ -89,7 +96,6 @@ extern UTIL_time_t g_displayClock;
     #   define LONG_SEEK fseeko64
     #   define LONG_TELL ftello64
     #elif defined(_WIN32) && !defined(__DJGPP__)
    -#   include 
         static int LONG_SEEK(FILE* file, __int64 offset, int origin) {
             LARGE_INTEGER off;
             DWORD method;
    diff --git a/programs/platform.h b/programs/platform.h
    index 4d2b9490e..05a26a564 100644
    --- a/programs/platform.h
    +++ b/programs/platform.h
    @@ -11,12 +11,6 @@
     #ifndef PLATFORM_H_MODULE
     #define PLATFORM_H_MODULE
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
    -
     /* **************************************
     *  Compiler Options
     ****************************************/
    @@ -144,10 +138,20 @@ extern "C" {
     #  include       /* _isatty */
     #  include  /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
     #  include    /* FILE */
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     static __inline int IS_CONSOLE(FILE* stdStream) {
         DWORD dummy;
         return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);
     }
    +
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #else
     #  define IS_CONSOLE(stdStream) 0
     #endif
    @@ -210,9 +214,4 @@ static __inline int IS_CONSOLE(FILE* stdStream) {
     #  endif
     #endif
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* PLATFORM_H_MODULE */
    diff --git a/programs/timefn.h b/programs/timefn.h
    index b814ff8d8..dc7463be3 100644
    --- a/programs/timefn.h
    +++ b/programs/timefn.h
    @@ -11,12 +11,6 @@
     #ifndef TIME_FN_H_MODULE_287987
     #define TIME_FN_H_MODULE_287987
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
    -
     /*-****************************************
     *  Types
     ******************************************/
    @@ -32,6 +26,11 @@ extern "C" {
       typedef unsigned long long PTime;  /* does not support compilers without long long support */
     #endif
     
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* UTIL_time_t contains a nanosecond time counter.
      * The absolute value is not meaningful.
      * It's only valid to compute the difference between 2 measurements. */
    diff --git a/programs/util.c b/programs/util.c
    index 7f65f9373..065a35855 100644
    --- a/programs/util.c
    +++ b/programs/util.c
    @@ -8,11 +8,6 @@
      * You may select, at your option, one of the above-listed licenses.
      */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
     /*-****************************************
     *  Dependencies
     ******************************************/
    @@ -1646,7 +1641,3 @@ int UTIL_countLogicalCores(void)
     {
         return UTIL_countCores(1);
     }
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    diff --git a/programs/util.h b/programs/util.h
    index ec8139684..5868f5eae 100644
    --- a/programs/util.h
    +++ b/programs/util.h
    @@ -20,6 +20,9 @@
     #include     /* stat, utime */
     #include      /* stat, chmod */
     #include "../lib/common/mem.h"          /* U64 */
    +#if not (defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__))
    +#include 
    +#endif
     
     /*-************************************************************
     *  Fix fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW
    @@ -116,7 +119,6 @@ int UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg, const
     #define STRDUP(s) _strdup(s)
     #else
     #define PATH_SEP '/'
    -#include 
     #define STRDUP(s) strdup(s)
     #endif
     
    diff --git a/zlibWrapper/zstd_zlibwrapper.h b/zlibWrapper/zstd_zlibwrapper.h
    index 230bf8411..dae6787d3 100644
    --- a/zlibWrapper/zstd_zlibwrapper.h
    +++ b/zlibWrapper/zstd_zlibwrapper.h
    @@ -11,11 +11,6 @@
     #ifndef ZSTD_ZLIBWRAPPER_H
     #define ZSTD_ZLIBWRAPPER_H
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
     #define ZLIB_CONST
     #define Z_PREFIX
     #define ZLIB_INTERNAL   /* disables gz*64 functions but fixes zlib 1.2.4 with Z_PREFIX */
    @@ -29,6 +24,11 @@ extern "C" {
         #define _Z_OF OF
     #endif
     
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* returns a string with version of zstd library */
     const char * zstdVersion(void);
     
    
    From 5222dd87cff5533a83938d0e54b724f675266bf6 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Tue, 17 Dec 2024 18:11:58 -0800
    Subject: [PATCH 183/405] Oopsie with fse.h
    
    ---
     lib/common/fse.h | 21 +++++++++++----------
     1 file changed, 11 insertions(+), 10 deletions(-)
    
    diff --git a/lib/common/fse.h b/lib/common/fse.h
    index 4c41b06ef..9f031f31f 100644
    --- a/lib/common/fse.h
    +++ b/lib/common/fse.h
    @@ -20,11 +20,6 @@
     ******************************************/
     #include "zstd_deps.h"    /* size_t, ptrdiff_t */
     
    -#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
    -#define FSE_H_FSE_STATIC_LINKING_ONLY
    -#include "bitstream.h"
    -#endif 
    -
     #if defined (__cplusplus)
     extern "C" {
     #endif
    @@ -230,12 +225,16 @@ FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<
     If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
     */
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #endif  /* FSE_H */
     
     
     #if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
     #define FSE_H_FSE_STATIC_LINKING_ONLY
    -
    +#include "bitstream.h"
     
     /* *****************************************
     *  Static allocation
    @@ -258,6 +257,10 @@ If there is an error, the function will return an error code, which can be teste
      *  FSE advanced API
      ***************************************** */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
     /**< same as FSE_optimalTableLog(), which used `minus==2` */
     
    @@ -631,10 +634,8 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
     
     #define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
     
    -
    -#endif /* FSE_STATIC_LINKING_ONLY */
    -
    -
     #if defined (__cplusplus)
     }
     #endif
    +
    +#endif /* FSE_STATIC_LINKING_ONLY */
    
    From ded4c1ec18bf39db0ce6b4263ddf6daac6712e94 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Tue, 17 Dec 2024 18:18:02 -0800
    Subject: [PATCH 184/405] Oopsie with util.h
    
    ---
     programs/util.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/programs/util.h b/programs/util.h
    index 5868f5eae..93d6c807f 100644
    --- a/programs/util.h
    +++ b/programs/util.h
    @@ -20,7 +20,7 @@
     #include     /* stat, utime */
     #include      /* stat, chmod */
     #include "../lib/common/mem.h"          /* U64 */
    -#if not (defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__))
    +#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__))
     #include 
     #endif
     
    
    From fa5bfb603065e0f426c3ede2b5e239a13b69ea22 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Tue, 17 Dec 2024 18:34:04 -0800
    Subject: [PATCH 185/405] Oopsie with zstd.h
    
    ---
     lib/zstd.h | 12 ++++++++++--
     1 file changed, 10 insertions(+), 2 deletions(-)
    
    diff --git a/lib/zstd.h b/lib/zstd.h
    index 7571f8069..1ae47c2b6 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -1205,6 +1205,10 @@ ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
     ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
     ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #endif  /* ZSTD_H_235446 */
     
     
    @@ -1220,6 +1224,10 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
     #if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
     #define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* This can be overridden externally to hide static symbols. */
     #ifndef ZSTDLIB_STATIC_API
     #  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
    @@ -3138,8 +3146,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_
     ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.")
     ZSTDLIB_STATIC_API size_t ZSTD_insertBlock    (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize);  /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
     
    -#endif   /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
    -
     #if defined (__cplusplus)
     }
     #endif
    +
    +#endif   /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
    
    From 58a7f4b869e02e02ab7e119f20fca9ea631dd83d Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Tue, 17 Dec 2024 18:37:33 -0800
    Subject: [PATCH 186/405] Oopsie with threading.h
    
    ---
     lib/common/threading.h | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/lib/common/threading.h b/lib/common/threading.h
    index 25448548d..85b6a3ac8 100644
    --- a/lib/common/threading.h
    +++ b/lib/common/threading.h
    @@ -140,7 +140,6 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);
     #else  /* ZSTD_MULTITHREAD not defined */
     /* No multithreading support */
     
    -
     #if defined (__cplusplus)
     extern "C" {
     #endif
    @@ -160,10 +159,11 @@ typedef int ZSTD_pthread_cond_t;
     
     /* do not use ZSTD_pthread_t */
     
    -#endif /* ZSTD_MULTITHREAD */
    -
     #if defined (__cplusplus)
     }
     #endif
     
    +#endif /* ZSTD_MULTITHREAD */
    +
    +
     #endif /* THREADING_H_938743 */
    
    From 63acf9a9955302c9595d6eccf3e8813256dfe069 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Wed, 18 Dec 2024 09:56:50 -0800
    Subject: [PATCH 187/405] Oopsie with huf.h, debug.h
    
    ---
     lib/common/debug.h | 10 +---------
     lib/common/huf.h   |  4 ++--
     2 files changed, 3 insertions(+), 11 deletions(-)
    
    diff --git a/lib/common/debug.h b/lib/common/debug.h
    index 8ef37a908..4b60ddf7f 100644
    --- a/lib/common/debug.h
    +++ b/lib/common/debug.h
    @@ -71,12 +71,9 @@
     #  endif
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #if (DEBUGLEVEL>=2)
     #  define ZSTD_DEPS_NEED_IO
    +#  include "zstd_deps.h"
     extern int g_debuglevel; /* the variable is only declared,
                                 it actually lives in debug.c,
                                 and is shared by the whole process.
    @@ -107,9 +104,4 @@ extern int g_debuglevel; /* the variable is only declared,
     #  define DEBUGLOG(l, ...) do { } while (0)    /* disabled */
     #endif
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* DEBUG_H_12987983217 */
    diff --git a/lib/common/huf.h b/lib/common/huf.h
    index bfcec4a81..962fe43fa 100644
    --- a/lib/common/huf.h
    +++ b/lib/common/huf.h
    @@ -278,8 +278,8 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
     size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);
     #endif
     
    -#endif   /* HUF_H_298734234 */
    -
     #if defined (__cplusplus)
     }
     #endif
    +
    +#endif   /* HUF_H_298734234 */
    
    From f25b9f11ba1df6e2a5bfe7e73e43c24c7c0906db Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Wed, 18 Dec 2024 10:10:20 -0800
    Subject: [PATCH 188/405] Oopsie with zdict.h
    
    ---
     lib/zdict.h | 13 ++++++++++---
     1 file changed, 10 insertions(+), 3 deletions(-)
    
    diff --git a/lib/zdict.h b/lib/zdict.h
    index 340a9a24e..599b79301 100644
    --- a/lib/zdict.h
    +++ b/lib/zdict.h
    @@ -271,11 +271,19 @@ ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictS
     ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode);
     ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode);
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #endif   /* ZSTD_ZDICT_H */
     
     #if defined(ZDICT_STATIC_LINKING_ONLY) && !defined(ZSTD_ZDICT_H_STATIC)
     #define ZSTD_ZDICT_H_STATIC
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* This can be overridden externally to hide static symbols. */
     #ifndef ZDICTLIB_STATIC_API
     #  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
    @@ -466,9 +474,8 @@ ZDICTLIB_STATIC_API
     size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,
                                       const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);
     
    -
    -#endif   /* ZSTD_ZDICT_H_STATIC */
    -
     #if defined (__cplusplus)
     }
     #endif
    +
    +#endif   /* ZSTD_ZDICT_H_STATIC */
    
    From 07ffcc6b65a0eb95afc63a73e595384aef9f3552 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Wed, 18 Dec 2024 12:35:10 -0800
    Subject: [PATCH 189/405] Separate xxhash includes from extern C blocks
    
    ---
     lib/common/xxhash.h | 108 +++++++++++++++++++++++++++++++++++++-------
     1 file changed, 91 insertions(+), 17 deletions(-)
    
    diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h
    index e59e44267..477fd4792 100644
    --- a/lib/common/xxhash.h
    +++ b/lib/common/xxhash.h
    @@ -227,10 +227,6 @@
      * xxHash prototypes and implementation
      */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ****************************
      *  INLINE mode
      ******************************/
    @@ -537,6 +533,9 @@ extern "C" {
     /*! @brief Version number, encoded as two digits each */
     #define XXH_VERSION_NUMBER  (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @brief Obtains the xxHash version.
      *
    @@ -547,6 +546,9 @@ extern "C" {
      */
     XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void);
     
    +#if defined (__cplusplus)
    +}
    +#endif
     
     /* ****************************
     *  Common basic types
    @@ -593,6 +595,10 @@ typedef uint32_t XXH32_hash_t;
     #   endif
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*!
      * @}
      *
    @@ -821,6 +827,9 @@ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canoni
     #endif
     /*! @endcond */
     
    +#if defined (__cplusplus)
    +} /* end of extern "C" */
    +#endif
     
     /*!
      * @}
    @@ -859,6 +868,9 @@ typedef uint64_t XXH64_hash_t;
     #  endif
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @}
      *
    @@ -1562,6 +1574,11 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE con
     
     
     #endif  /* !XXH_NO_XXH3 */
    +
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* XXH_NO_LONG_LONG */
     
     /*!
    @@ -1748,6 +1765,10 @@ struct XXH3_state_s {
         } while(0)
     
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*!
      * @brief Calculates the 128-bit hash of @p data using XXH3.
      *
    @@ -1963,8 +1984,13 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
                                          XXH64_hash_t seed64);
     #endif /* !XXH_NO_STREAM */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* !XXH_NO_XXH3 */
     #endif  /* XXH_NO_LONG_LONG */
    +
     #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
     #  define XXH_IMPLEMENTATION
     #endif
    @@ -2263,10 +2289,12 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
      * @{
      */
     
    -
     /* *************************************
     *  Includes & Memory related functions
     ***************************************/
    +#include    /* memcmp, memcpy */
    +#include    /* ULLONG_MAX */
    +
     #if defined(XXH_NO_STREAM)
     /* nothing */
     #elif defined(XXH_NO_STDLIB)
    @@ -2280,9 +2308,17 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
      * without access to dynamic allocation.
      */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }
     static void XXH_free(void* p) { (void)p; }
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #else
     
     /*
    @@ -2291,6 +2327,9 @@ static void XXH_free(void* p) { (void)p; }
      */
     #include 
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @internal
      * @brief Modify this function to use a different routine than malloc().
    @@ -2303,10 +2342,15 @@ static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }
      */
     static void XXH_free(void* p) { free(p); }
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* XXH_NO_STDLIB */
     
    -#include 
    -
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @internal
      * @brief Modify this function to use a different routine than memcpy().
    @@ -2316,8 +2360,9 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size)
         return memcpy(dest,src,size);
     }
     
    -#include    /* ULLONG_MAX */
    -
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
     
     /* *************************************
     *  Compiler Specific Options
    @@ -2452,6 +2497,10 @@ typedef XXH32_hash_t xxh_u32;
     #  define U32  xxh_u32
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* ***   Memory access   *** */
     
     /*!
    @@ -3608,6 +3657,10 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can
         return XXH_readBE64(src);
     }
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #ifndef XXH_NO_XXH3
     
     /* *********************************************************************
    @@ -3928,6 +3981,10 @@ enum XXH_VECTOR_TYPE /* fake enum */ {
     #  pragma GCC optimize("-O2")
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     #if XXH_VECTOR == XXH_NEON
     
     /*
    @@ -4050,6 +4107,10 @@ XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
     # endif
     #endif  /* XXH_VECTOR == XXH_NEON */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     /*
      * VSX and Z Vector helpers.
      *
    @@ -4111,6 +4172,9 @@ typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;
     #  if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))
     #    define XXH_vec_revb vec_revb
     #  else
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * A polyfill for POWER9's vec_revb().
      */
    @@ -4120,9 +4184,15 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)
                                       0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };
         return vec_perm(val, val, vByteSwap);
     }
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
     #  endif
     # endif /* XXH_VSX_BE */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * Performs an unaligned vector load and byte swaps it on big endian.
      */
    @@ -4167,6 +4237,11 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)
         return result;
     }
     # endif /* XXH_vec_mulo, XXH_vec_mule */
    +
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif /* XXH_VECTOR == XXH_VSX */
     
     #if XXH_VECTOR == XXH_SVE
    @@ -4200,7 +4275,9 @@ do { \
     #  endif
     #endif  /* XXH_NO_PREFETCH */
     
    -
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /* ==========================================
      * XXH3 default settings
      * ========================================== */
    @@ -6877,8 +6954,6 @@ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_
     #endif /* !XXH_NO_STREAM */
     /* 128-bit utility functions */
     
    -#include    /* memcmp, memcpy */
    -
     /* return : 1 is equal, 0 if different */
     /*! @ingroup XXH3_family */
     XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2)
    @@ -7007,14 +7082,13 @@ XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)
     
     #endif  /* XXH_NO_LONG_LONG */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* XXH_NO_XXH3 */
     
     /*!
      * @}
      */
     #endif  /* XXH_IMPLEMENTATION */
    -
    -
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    
    From a7bb6d6c490a5b60b58666e73890c19921907e18 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Wed, 18 Dec 2024 12:41:53 -0800
    Subject: [PATCH 190/405] Oopsie with xxhash.h [1/?]
    
    ---
     lib/common/xxhash.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h
    index 477fd4792..68ec6b29f 100644
    --- a/lib/common/xxhash.h
    +++ b/lib/common/xxhash.h
    @@ -7080,12 +7080,12 @@ XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)
     #  pragma GCC pop_options
     #endif
     
    -#endif  /* XXH_NO_LONG_LONG */
     
     #if defined (__cplusplus)
     } /* extern "C" */
     #endif
     
    +#endif  /* XXH_NO_LONG_LONG */
     #endif  /* XXH_NO_XXH3 */
     
     /*!
    
    From d51e6072a847f91610637e44feef972fd41167ea Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 19 Dec 2024 14:59:02 -0800
    Subject: [PATCH 191/405] Test: remove extern C from some lib/common files
    
    ---
     lib/common/bitstream.h |  8 --------
     lib/common/fse.h       | 16 ----------------
     2 files changed, 24 deletions(-)
    
    diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h
    index bce91e801..bcfa09b89 100644
    --- a/lib/common/bitstream.h
    +++ b/lib/common/bitstream.h
    @@ -40,10 +40,6 @@
     #  endif
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #define STREAM_ACCUMULATOR_MIN_32  25
     #define STREAM_ACCUMULATOR_MIN_64  57
     #define STREAM_ACCUMULATOR_MIN    ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
    @@ -450,8 +446,4 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
         return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
     }
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* BITSTREAM_H_MODULE */
    diff --git a/lib/common/fse.h b/lib/common/fse.h
    index 9f031f31f..b1940d942 100644
    --- a/lib/common/fse.h
    +++ b/lib/common/fse.h
    @@ -20,10 +20,6 @@
     ******************************************/
     #include "zstd_deps.h"    /* size_t, ptrdiff_t */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-*****************************************
     *  FSE_PUBLIC_API : control library symbols visibility
     ******************************************/
    @@ -225,10 +221,6 @@ FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<
     If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
     */
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif  /* FSE_H */
     
     
    @@ -257,10 +249,6 @@ If there is an error, the function will return an error code, which can be teste
      *  FSE advanced API
      ***************************************** */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
     /**< same as FSE_optimalTableLog(), which used `minus==2` */
     
    @@ -634,8 +622,4 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
     
     #define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* FSE_STATIC_LINKING_ONLY */
    
    From d0d5ce4c00469d4f11970e649e55217a659b4690 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 19 Dec 2024 16:00:11 -0800
    Subject: [PATCH 192/405] Remove extern C blocks from lib/* internal APIs
     (except xxhash.h)
    
    ---
     lib/common/error_private.h            |  8 --------
     lib/common/huf.h                      |  8 --------
     lib/common/mem.h                      | 10 ----------
     lib/common/pool.h                     |  9 ---------
     lib/common/threading.h                | 27 ---------------------------
     lib/common/zstd_internal.h            |  8 --------
     lib/common/zstd_trace.h               |  8 --------
     lib/compress/zstd_compress_internal.h |  8 --------
     lib/compress/zstd_cwksp.h             |  8 --------
     lib/compress/zstd_double_fast.h       |  8 --------
     lib/compress/zstd_fast.h              |  8 --------
     lib/compress/zstd_lazy.h              |  9 ---------
     lib/compress/zstd_ldm.h               |  8 --------
     lib/compress/zstd_opt.h               |  8 --------
     lib/compress/zstd_preSplit.h          |  8 --------
     lib/compress/zstdmt_compress.h        | 10 ----------
     lib/dictBuilder/divsufsort.h          | 10 ----------
     17 files changed, 163 deletions(-)
    
    diff --git a/lib/common/error_private.h b/lib/common/error_private.h
    index 06233aaa8..9dcc85951 100644
    --- a/lib/common/error_private.h
    +++ b/lib/common/error_private.h
    @@ -21,10 +21,6 @@
     #include "debug.h"
     #include "zstd_deps.h"       /* size_t */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ****************************************
     *  Compiler-specific
     ******************************************/
    @@ -159,8 +155,4 @@ void _force_has_format_string(const char *format, ...) {
             }                                                                          \
         } while(0)
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ERROR_H_MODULE */
    diff --git a/lib/common/huf.h b/lib/common/huf.h
    index 962fe43fa..4b142c4f9 100644
    --- a/lib/common/huf.h
    +++ b/lib/common/huf.h
    @@ -21,10 +21,6 @@
     #define FSE_STATIC_LINKING_ONLY
     #include "fse.h"
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ***   Tool functions *** */
     #define HUF_BLOCKSIZE_MAX (128 * 1024)   /**< maximum input size for a single block compressed with HUF_compress */
     size_t HUF_compressBound(size_t size);   /**< maximum compressed size (worst case) */
    @@ -278,8 +274,4 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
     size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);
     #endif
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif   /* HUF_H_298734234 */
    diff --git a/lib/common/mem.h b/lib/common/mem.h
    index 1b0a946ad..ca756e237 100644
    --- a/lib/common/mem.h
    +++ b/lib/common/mem.h
    @@ -72,11 +72,6 @@
       typedef   signed long long  S64;
     #endif
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-**************************************************************
     *  Memory I/O API
     *****************************************************************/
    @@ -424,9 +419,4 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
     /* code only tested on 32 and 64 bits systems */
     MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* MEM_H_MODULE */
    diff --git a/lib/common/pool.h b/lib/common/pool.h
    index d34082dc1..f39b7f1eb 100644
    --- a/lib/common/pool.h
    +++ b/lib/common/pool.h
    @@ -16,10 +16,6 @@
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_customMem */
     #include "../zstd.h"
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     typedef struct POOL_ctx_s POOL_ctx;
     
     /*! POOL_create() :
    @@ -82,9 +78,4 @@ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
      */
     int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif
    diff --git a/lib/common/threading.h b/lib/common/threading.h
    index 85b6a3ac8..e123cdf14 100644
    --- a/lib/common/threading.h
    +++ b/lib/common/threading.h
    @@ -56,11 +56,6 @@
     #define ZSTD_pthread_cond_signal(a)     WakeConditionVariable((a))
     #define ZSTD_pthread_cond_broadcast(a)  WakeAllConditionVariable((a))
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ZSTD_pthread_create() and ZSTD_pthread_join() */
     typedef HANDLE ZSTD_pthread_t;
     
    @@ -73,20 +68,10 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread);
      * add here more wrappers as required
      */
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #elif defined(ZSTD_MULTITHREAD)    /* posix assumed ; need a better detection method */
     /* ===   POSIX Systems   === */
     #  include 
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #if DEBUGLEVEL < 1
     
     #define ZSTD_pthread_mutex_t            pthread_mutex_t
    @@ -133,17 +118,9 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);
     
     #endif
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #else  /* ZSTD_MULTITHREAD not defined */
     /* No multithreading support */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     typedef int ZSTD_pthread_mutex_t;
     #define ZSTD_pthread_mutex_init(a, b)   ((void)(a), (void)(b), 0)
     #define ZSTD_pthread_mutex_destroy(a)   ((void)(a))
    @@ -159,10 +136,6 @@ typedef int ZSTD_pthread_cond_t;
     
     /* do not use ZSTD_pthread_t */
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_MULTITHREAD */
     
     
    diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h
    index ecb9cfba8..e40d15a05 100644
    --- a/lib/common/zstd_internal.h
    +++ b/lib/common/zstd_internal.h
    @@ -39,10 +39,6 @@
     #  define ZSTD_TRACE 0
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ---- static assert (debug) --- */
     #define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)
     #define ZSTD_isError ERR_isError   /* for inlining */
    @@ -385,8 +381,4 @@ MEM_STATIC int ZSTD_cpuSupportsBmi2(void)
         return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
     }
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif   /* ZSTD_CCOMMON_H_MODULE */
    diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h
    index b9187079c..198438a7c 100644
    --- a/lib/common/zstd_trace.h
    +++ b/lib/common/zstd_trace.h
    @@ -13,10 +13,6 @@
     
     #include 
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* weak symbol support
      * For now, enable conservatively:
      * - Only GNUC
    @@ -157,8 +153,4 @@ ZSTD_WEAK_ATTR void ZSTD_trace_decompress_end(
     
     #endif /* ZSTD_TRACE */
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_TRACE_H */
    diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
    index 2d3510adc..bbca66cd3 100644
    --- a/lib/compress/zstd_compress_internal.h
    +++ b/lib/compress/zstd_compress_internal.h
    @@ -26,10 +26,6 @@
     #include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */
     #include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-*************************************
     *  Constants
     ***************************************/
    @@ -1426,10 +1422,6 @@ MEM_STATIC int ZSTD_comparePackedTags(size_t packedTag1, size_t packedTag2) {
         return tag1 == tag2;
     }
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     /* ===============================================================
      * Shared internal declarations
      * These prototypes may be called from sources not in lib/compress
    diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h
    index aa4c3e49e..77518002d 100644
    --- a/lib/compress/zstd_cwksp.h
    +++ b/lib/compress/zstd_cwksp.h
    @@ -19,10 +19,6 @@
     #include "../common/portability_macros.h"
     #include "../common/compiler.h" /* ZS2_isPower2 */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-*************************************
     *  Constants
     ***************************************/
    @@ -766,8 +762,4 @@ MEM_STATIC void ZSTD_cwksp_bump_oversized_duration(
         }
     }
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_CWKSP_H */
    diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h
    index ae66f3142..a4d4d345e 100644
    --- a/lib/compress/zstd_double_fast.h
    +++ b/lib/compress/zstd_double_fast.h
    @@ -14,10 +14,6 @@
     #include "../common/mem.h"      /* U32 */
     #include "zstd_compress_internal.h"     /* ZSTD_CCtx, size_t */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
     
     void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
    @@ -43,8 +39,4 @@ size_t ZSTD_compressBlock_doubleFast_extDict(
     #define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT NULL
     #endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_DOUBLE_FAST_H */
    diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h
    index f92cf35b9..8bbed8f97 100644
    --- a/lib/compress/zstd_fast.h
    +++ b/lib/compress/zstd_fast.h
    @@ -14,10 +14,6 @@
     #include "../common/mem.h"      /* U32 */
     #include "zstd_compress_internal.h"
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
                             void const* end, ZSTD_dictTableLoadMethod_e dtlm,
                             ZSTD_tableFillPurpose_e tfp);
    @@ -31,8 +27,4 @@ size_t ZSTD_compressBlock_fast_extDict(
             ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
             void const* src, size_t srcSize);
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_FAST_H */
    diff --git a/lib/compress/zstd_lazy.h b/lib/compress/zstd_lazy.h
    index bec17b124..cd4e1c7fa 100644
    --- a/lib/compress/zstd_lazy.h
    +++ b/lib/compress/zstd_lazy.h
    @@ -13,10 +13,6 @@
     
     #include "zstd_compress_internal.h"
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /**
      * Dedicated Dictionary Search Structure bucket log. In the
      * ZSTD_dedicatedDictSearch mode, the hashTable has
    @@ -194,9 +190,4 @@ size_t ZSTD_compressBlock_btlazy2_extDict(
     #define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT NULL
     #endif
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_LAZY_H */
    diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h
    index 847c2befb..592b95a98 100644
    --- a/lib/compress/zstd_ldm.h
    +++ b/lib/compress/zstd_ldm.h
    @@ -14,10 +14,6 @@
     #include "zstd_compress_internal.h"   /* ldmParams_t, U32 */
     #include "../zstd.h"   /* ZSTD_CCtx, size_t */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-*************************************
     *  Long distance matching
     ***************************************/
    @@ -110,8 +106,4 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize);
     void ZSTD_ldm_adjustParameters(ldmParams_t* params,
                                    ZSTD_compressionParameters const* cParams);
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_FAST_H */
    diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h
    index 7ce6fdae7..cace81494 100644
    --- a/lib/compress/zstd_opt.h
    +++ b/lib/compress/zstd_opt.h
    @@ -13,10 +13,6 @@
     
     #include "zstd_compress_internal.h"
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \
      || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \
      || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)
    @@ -73,8 +69,4 @@ size_t ZSTD_compressBlock_btultra2(
     #define ZSTD_COMPRESSBLOCK_BTULTRA2 NULL
     #endif
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_OPT_H */
    diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h
    index d606a52b5..b89a200dc 100644
    --- a/lib/compress/zstd_preSplit.h
    +++ b/lib/compress/zstd_preSplit.h
    @@ -13,10 +13,6 @@
     
     #include   /* size_t */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208
     
     /* ZSTD_splitBlock():
    @@ -34,8 +30,4 @@ size_t ZSTD_splitBlock(const void* blockStart, size_t blockSize,
                         int level,
                         void* workspace, size_t wkspSize);
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_PRESPLIT_H */
    diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h
    index 9a58b5ad3..91b489b9c 100644
    --- a/lib/compress/zstdmt_compress.h
    +++ b/lib/compress/zstdmt_compress.h
    @@ -16,11 +16,6 @@
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters */
     #include "../zstd.h"            /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
     
    - #if defined (__cplusplus)
    - extern "C" {
    - #endif
    -
    -
     /* Note : This is an internal API.
      *        These APIs used to be exposed with ZSTDLIB_API,
      *        because it used to be the only way to invoke MT compression.
    @@ -104,9 +99,4 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
      */
     ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx);
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif   /* ZSTDMT_COMPRESS_H */
    diff --git a/lib/dictBuilder/divsufsort.h b/lib/dictBuilder/divsufsort.h
    index 5440994af..3ed2b287a 100644
    --- a/lib/dictBuilder/divsufsort.h
    +++ b/lib/dictBuilder/divsufsort.h
    @@ -27,11 +27,6 @@
     #ifndef _DIVSUFSORT_H
     #define _DIVSUFSORT_H 1
     
    -#ifdef __cplusplus
    -extern "C" {
    -#endif /* __cplusplus */
    -
    -
     /*- Prototypes -*/
     
     /**
    @@ -59,9 +54,4 @@ divsufsort(const unsigned char *T, int *SA, int n, int openMP);
     int
     divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP);
     
    -
    -#ifdef __cplusplus
    -} /* extern "C" */
    -#endif /* __cplusplus */
    -
     #endif /* _DIVSUFSORT_H */
    
    From c727d5cd675dc04e07c0113d168ce93dc5624e54 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 19 Dec 2024 16:20:23 -0800
    Subject: [PATCH 193/405] Remove unnecessary extern C declarations from
     programs/ and contrib/
    
    ---
     contrib/pzstd/test/PzstdTest.cpp     |  2 --
     contrib/pzstd/test/RoundTripTest.cpp |  2 --
     programs/benchfn.h                   | 10 ----------
     programs/benchzstd.h                 |  9 ---------
     programs/datagen.h                   |  8 ++++++++
     programs/fileio.h                    | 10 ----------
     programs/fileio_asyncio.h            |  8 --------
     programs/fileio_common.h             |  7 -------
     programs/timefn.h                    | 10 ----------
     9 files changed, 8 insertions(+), 58 deletions(-)
    
    diff --git a/contrib/pzstd/test/PzstdTest.cpp b/contrib/pzstd/test/PzstdTest.cpp
    index 75453f5f6..3249f860a 100644
    --- a/contrib/pzstd/test/PzstdTest.cpp
    +++ b/contrib/pzstd/test/PzstdTest.cpp
    @@ -7,9 +7,7 @@
      * in the COPYING file in the root directory of this source tree).
      */
     #include "Pzstd.h"
    -extern "C" {
     #include "datagen.h"
    -}
     #include "test/RoundTrip.h"
     #include "utils/ScopeGuard.h"
     
    diff --git a/contrib/pzstd/test/RoundTripTest.cpp b/contrib/pzstd/test/RoundTripTest.cpp
    index c37646d1c..27c5028e8 100644
    --- a/contrib/pzstd/test/RoundTripTest.cpp
    +++ b/contrib/pzstd/test/RoundTripTest.cpp
    @@ -6,9 +6,7 @@
      * LICENSE file in the root directory of this source tree) and the GPLv2 (found
      * in the COPYING file in the root directory of this source tree).
      */
    -extern "C" {
     #include "datagen.h"
    -}
     #include "Options.h"
     #include "test/RoundTrip.h"
     #include "utils/ScopeGuard.h"
    diff --git a/programs/benchfn.h b/programs/benchfn.h
    index 3ba3a4f55..3fc6e0d04 100644
    --- a/programs/benchfn.h
    +++ b/programs/benchfn.h
    @@ -21,11 +21,6 @@
     /* ===  Dependencies  === */
     #include    /* size_t */
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ====  Benchmark any function, iterated on a set of blocks  ==== */
     
     /* BMK_runTime_t: valid result return type */
    @@ -175,9 +170,4 @@ typedef union {
     } BMK_timedFnState_shell;
     BMK_timedFnState_t* BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms);
     
    -
     #endif   /* BENCH_FN_H_23876 */
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    diff --git a/programs/benchzstd.h b/programs/benchzstd.h
    index 7ea018b12..5125c20e8 100644
    --- a/programs/benchzstd.h
    +++ b/programs/benchzstd.h
    @@ -22,11 +22,6 @@
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_compressionParameters */
     #include "../lib/zstd.h"     /* ZSTD_compressionParameters */
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ===  Constants  === */
     
     #define MB_UNIT 1000000
    @@ -194,7 +189,3 @@ BMK_benchOutcome_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize,
     
     
     #endif   /* BENCH_ZSTD_H_3242387 */
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    diff --git a/programs/datagen.h b/programs/datagen.h
    index ca7270006..461fb716c 100644
    --- a/programs/datagen.h
    +++ b/programs/datagen.h
    @@ -14,6 +14,10 @@
     
     #include    /* size_t */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     void RDG_genStdout(unsigned long long size, double matchProba, double litProba, unsigned seed);
     void RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba, unsigned seed);
     /*!RDG_genBuffer
    @@ -27,4 +31,8 @@ void RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba
        Same as RDG_genBuffer, but generates data into stdout
     */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif
    diff --git a/programs/fileio.h b/programs/fileio.h
    index 224d89525..6babf40e1 100644
    --- a/programs/fileio.h
    +++ b/programs/fileio.h
    @@ -17,11 +17,6 @@
     #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_compressionParameters */
     #include "../lib/zstd.h"           /* ZSTD_* */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
    -
     /* *************************************
     *  Special i/o constants
     **************************************/
    @@ -173,9 +168,4 @@ char const* FIO_zlibVersion(void);
     char const* FIO_lz4Version(void);
     char const* FIO_lzmaVersion(void);
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif  /* FILEIO_H_23981798732 */
    diff --git a/programs/fileio_asyncio.h b/programs/fileio_asyncio.h
    index 1c30a73da..d4980ef5b 100644
    --- a/programs/fileio_asyncio.h
    +++ b/programs/fileio_asyncio.h
    @@ -31,10 +31,6 @@
     
     #define MAX_IO_JOBS          (10)
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     typedef struct {
         /* These struct fields should be set only on creation and not changed afterwards */
         POOL_ctx* threadPool;
    @@ -196,8 +192,4 @@ FILE* AIO_ReadPool_getFile(const ReadPoolCtx_t *ctx);
      * Closes the current set file. Waits for all current enqueued tasks to complete and resets state. */
     int AIO_ReadPool_closeFile(ReadPoolCtx_t *ctx);
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* ZSTD_FILEIO_ASYNCIO_H */
    diff --git a/programs/fileio_common.h b/programs/fileio_common.h
    index 87f99cda9..e073dc101 100644
    --- a/programs/fileio_common.h
    +++ b/programs/fileio_common.h
    @@ -23,10 +23,6 @@
     #   include 
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*-*************************************
     *  Macros
     ***************************************/
    @@ -124,7 +120,4 @@ extern UTIL_time_t g_displayClock;
     #   define LONG_TELL ftell
     #endif
     
    -#if defined (__cplusplus)
    -}
    -#endif
     #endif /* ZSTD_FILEIO_COMMON_H */
    diff --git a/programs/timefn.h b/programs/timefn.h
    index dc7463be3..80f72e228 100644
    --- a/programs/timefn.h
    +++ b/programs/timefn.h
    @@ -26,11 +26,6 @@
       typedef unsigned long long PTime;  /* does not support compilers without long long support */
     #endif
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* UTIL_time_t contains a nanosecond time counter.
      * The absolute value is not meaningful.
      * It's only valid to compute the difference between 2 measurements. */
    @@ -61,9 +56,4 @@ PTime UTIL_clockSpanMicro(UTIL_time_t clockStart);
     
     #define SEC_TO_MICRO ((PTime)1000000)  /* nb of microseconds in a second */
     
    -
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #endif /* TIME_FN_H_MODULE_287987 */
    
    From 10b9d81909f8631e3ac64bd45e3bdd04982e39d6 Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 19 Dec 2024 16:54:32 -0800
    Subject: [PATCH 194/405] Remove unnecessary extern C declarations from
     xxhash.h
    
    ---
     lib/common/xxhash.h | 90 ---------------------------------------------
     1 file changed, 90 deletions(-)
    
    diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h
    index 68ec6b29f..a849b75f9 100644
    --- a/lib/common/xxhash.h
    +++ b/lib/common/xxhash.h
    @@ -533,9 +533,6 @@
     /*! @brief Version number, encoded as two digits each */
     #define XXH_VERSION_NUMBER  (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*!
      * @brief Obtains the xxHash version.
      *
    @@ -546,10 +543,6 @@ extern "C" {
      */
     XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void);
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     /* ****************************
     *  Common basic types
     ******************************/
    @@ -595,10 +588,6 @@ typedef uint32_t XXH32_hash_t;
     #   endif
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*!
      * @}
      *
    @@ -827,10 +816,6 @@ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canoni
     #endif
     /*! @endcond */
     
    -#if defined (__cplusplus)
    -} /* end of extern "C" */
    -#endif
    -
     /*!
      * @}
      * @ingroup public
    @@ -868,9 +853,6 @@ typedef uint64_t XXH64_hash_t;
     #  endif
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*!
      * @}
      *
    @@ -1575,10 +1557,6 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE con
     
     #endif  /* !XXH_NO_XXH3 */
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     #endif  /* XXH_NO_LONG_LONG */
     
     /*!
    @@ -1764,11 +1742,6 @@ struct XXH3_state_s {
             tmp_xxh3_state_ptr->extSecret = NULL;                \
         } while(0)
     
    -
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /*!
      * @brief Calculates the 128-bit hash of @p data using XXH3.
      *
    @@ -1984,10 +1957,6 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
                                          XXH64_hash_t seed64);
     #endif /* !XXH_NO_STREAM */
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     #endif  /* !XXH_NO_XXH3 */
     #endif  /* XXH_NO_LONG_LONG */
     
    @@ -2308,17 +2277,9 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
      * without access to dynamic allocation.
      */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }
     static void XXH_free(void* p) { (void)p; }
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     #else
     
     /*
    @@ -2327,9 +2288,6 @@ static void XXH_free(void* p) { (void)p; }
      */
     #include 
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*!
      * @internal
      * @brief Modify this function to use a different routine than malloc().
    @@ -2342,15 +2300,8 @@ static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }
      */
     static void XXH_free(void* p) { free(p); }
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     #endif  /* XXH_NO_STDLIB */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*!
      * @internal
      * @brief Modify this function to use a different routine than memcpy().
    @@ -2360,10 +2311,6 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size)
         return memcpy(dest,src,size);
     }
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     /* *************************************
     *  Compiler Specific Options
     ***************************************/
    @@ -2497,10 +2444,6 @@ typedef XXH32_hash_t xxh_u32;
     #  define U32  xxh_u32
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     /* ***   Memory access   *** */
     
     /*!
    @@ -3657,10 +3600,6 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can
         return XXH_readBE64(src);
     }
     
    -#if defined (__cplusplus)
    -}
    -#endif
    -
     #ifndef XXH_NO_XXH3
     
     /* *********************************************************************
    @@ -3981,10 +3920,6 @@ enum XXH_VECTOR_TYPE /* fake enum */ {
     #  pragma GCC optimize("-O2")
     #endif
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
    -
     #if XXH_VECTOR == XXH_NEON
     
     /*
    @@ -4107,10 +4042,6 @@ XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
     # endif
     #endif  /* XXH_VECTOR == XXH_NEON */
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     /*
      * VSX and Z Vector helpers.
      *
    @@ -4172,9 +4103,6 @@ typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;
     #  if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))
     #    define XXH_vec_revb vec_revb
     #  else
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*!
      * A polyfill for POWER9's vec_revb().
      */
    @@ -4184,15 +4112,9 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)
                                       0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };
         return vec_perm(val, val, vByteSwap);
     }
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
     #  endif
     # endif /* XXH_VSX_BE */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /*!
      * Performs an unaligned vector load and byte swaps it on big endian.
      */
    @@ -4238,10 +4160,6 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)
     }
     # endif /* XXH_vec_mulo, XXH_vec_mule */
     
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     #endif /* XXH_VECTOR == XXH_VSX */
     
     #if XXH_VECTOR == XXH_SVE
    @@ -4275,9 +4193,6 @@ do { \
     #  endif
     #endif  /* XXH_NO_PREFETCH */
     
    -#if defined (__cplusplus)
    -extern "C" {
    -#endif
     /* ==========================================
      * XXH3 default settings
      * ========================================== */
    @@ -7080,11 +6995,6 @@ XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)
     #  pragma GCC pop_options
     #endif
     
    -
    -#if defined (__cplusplus)
    -} /* extern "C" */
    -#endif
    -
     #endif  /* XXH_NO_LONG_LONG */
     #endif  /* XXH_NO_XXH3 */
     
    
    From c7af0428c6cceac32a192392d954dc8e6e1ba79a Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 19 Dec 2024 17:48:00 -0800
    Subject: [PATCH 195/405] Oopsie with fileio_common.h
    
    ---
     programs/fileio_common.h | 8 +-------
     1 file changed, 1 insertion(+), 7 deletions(-)
    
    diff --git a/programs/fileio_common.h b/programs/fileio_common.h
    index e073dc101..274a6d10c 100644
    --- a/programs/fileio_common.h
    +++ b/programs/fileio_common.h
    @@ -16,13 +16,6 @@
     #include "platform.h"
     #include "timefn.h"     /* UTIL_getTime, UTIL_clockSpanMicro */
     
    -#if !(defined(_MSC_VER) && _MSC_VER >= 1400) \
    -    && !(!defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L)) \
    -    && !(defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)) \
    -    && (defined(_WIN32) && !defined(__DJGPP__))
    -#   include 
    -#endif
    -
     /*-*************************************
     *  Macros
     ***************************************/
    @@ -92,6 +85,7 @@ extern UTIL_time_t g_displayClock;
     #   define LONG_SEEK fseeko64
     #   define LONG_TELL ftello64
     #elif defined(_WIN32) && !defined(__DJGPP__)
    +#   include 
         static int LONG_SEEK(FILE* file, __int64 offset, int origin) {
             LARGE_INTEGER off;
             DWORD method;
    
    From 8f49db5a022f5f77ad2c9a468b5929855bb6f36b Mon Sep 17 00:00:00 2001
    From: Victor Zhang 
    Date: Thu, 19 Dec 2024 17:54:41 -0800
    Subject: [PATCH 196/405] Revert "Remove unnecessary extern C declarations from
     xxhash.h"
    
    This reverts commit 10b9d81909f8631e3ac64bd45e3bdd04982e39d6.
    ---
     lib/common/xxhash.h | 90 +++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 90 insertions(+)
    
    diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h
    index a849b75f9..68ec6b29f 100644
    --- a/lib/common/xxhash.h
    +++ b/lib/common/xxhash.h
    @@ -533,6 +533,9 @@
     /*! @brief Version number, encoded as two digits each */
     #define XXH_VERSION_NUMBER  (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @brief Obtains the xxHash version.
      *
    @@ -543,6 +546,10 @@
      */
     XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void);
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     /* ****************************
     *  Common basic types
     ******************************/
    @@ -588,6 +595,10 @@ typedef uint32_t XXH32_hash_t;
     #   endif
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*!
      * @}
      *
    @@ -816,6 +827,10 @@ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canoni
     #endif
     /*! @endcond */
     
    +#if defined (__cplusplus)
    +} /* end of extern "C" */
    +#endif
    +
     /*!
      * @}
      * @ingroup public
    @@ -853,6 +868,9 @@ typedef uint64_t XXH64_hash_t;
     #  endif
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @}
      *
    @@ -1557,6 +1575,10 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE con
     
     #endif  /* !XXH_NO_XXH3 */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* XXH_NO_LONG_LONG */
     
     /*!
    @@ -1742,6 +1764,11 @@ struct XXH3_state_s {
             tmp_xxh3_state_ptr->extSecret = NULL;                \
         } while(0)
     
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /*!
      * @brief Calculates the 128-bit hash of @p data using XXH3.
      *
    @@ -1957,6 +1984,10 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
                                          XXH64_hash_t seed64);
     #endif /* !XXH_NO_STREAM */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* !XXH_NO_XXH3 */
     #endif  /* XXH_NO_LONG_LONG */
     
    @@ -2277,9 +2308,17 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
      * without access to dynamic allocation.
      */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }
     static void XXH_free(void* p) { (void)p; }
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #else
     
     /*
    @@ -2288,6 +2327,9 @@ static void XXH_free(void* p) { (void)p; }
      */
     #include 
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @internal
      * @brief Modify this function to use a different routine than malloc().
    @@ -2300,8 +2342,15 @@ static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }
      */
     static void XXH_free(void* p) { free(p); }
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* XXH_NO_STDLIB */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * @internal
      * @brief Modify this function to use a different routine than memcpy().
    @@ -2311,6 +2360,10 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size)
         return memcpy(dest,src,size);
     }
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     /* *************************************
     *  Compiler Specific Options
     ***************************************/
    @@ -2444,6 +2497,10 @@ typedef XXH32_hash_t xxh_u32;
     #  define U32  xxh_u32
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     /* ***   Memory access   *** */
     
     /*!
    @@ -3600,6 +3657,10 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can
         return XXH_readBE64(src);
     }
     
    +#if defined (__cplusplus)
    +}
    +#endif
    +
     #ifndef XXH_NO_XXH3
     
     /* *********************************************************************
    @@ -3920,6 +3981,10 @@ enum XXH_VECTOR_TYPE /* fake enum */ {
     #  pragma GCC optimize("-O2")
     #endif
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
     #if XXH_VECTOR == XXH_NEON
     
     /*
    @@ -4042,6 +4107,10 @@ XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
     # endif
     #endif  /* XXH_VECTOR == XXH_NEON */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     /*
      * VSX and Z Vector helpers.
      *
    @@ -4103,6 +4172,9 @@ typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;
     #  if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))
     #    define XXH_vec_revb vec_revb
     #  else
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * A polyfill for POWER9's vec_revb().
      */
    @@ -4112,9 +4184,15 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)
                                       0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };
         return vec_perm(val, val, vByteSwap);
     }
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
     #  endif
     # endif /* XXH_VSX_BE */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /*!
      * Performs an unaligned vector load and byte swaps it on big endian.
      */
    @@ -4160,6 +4238,10 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)
     }
     # endif /* XXH_vec_mulo, XXH_vec_mule */
     
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif /* XXH_VECTOR == XXH_VSX */
     
     #if XXH_VECTOR == XXH_SVE
    @@ -4193,6 +4275,9 @@ do { \
     #  endif
     #endif  /* XXH_NO_PREFETCH */
     
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
     /* ==========================================
      * XXH3 default settings
      * ========================================== */
    @@ -6995,6 +7080,11 @@ XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)
     #  pragma GCC pop_options
     #endif
     
    +
    +#if defined (__cplusplus)
    +} /* extern "C" */
    +#endif
    +
     #endif  /* XXH_NO_LONG_LONG */
     #endif  /* XXH_NO_XXH3 */
     
    
    From d06e8778bc4b150507abe0a8b7eaed08f2d16a17 Mon Sep 17 00:00:00 2001
    From: Bent 
    Date: Thu, 19 Dec 2024 12:16:08 +0100
    Subject: [PATCH 197/405] added UNAME_TARGET_SYSTEM build flag to configure
     shared lib flags
    
    ---
     lib/Makefile | 9 +++++++--
     1 file changed, 7 insertions(+), 2 deletions(-)
    
    diff --git a/lib/Makefile b/lib/Makefile
    index 020d2ff5d..2fe436bc2 100644
    --- a/lib/Makefile
    +++ b/lib/Makefile
    @@ -73,13 +73,15 @@ endif
     
     # macOS linker doesn't support -soname, and use different extension
     # see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html
    -ifeq ($(UNAME), Darwin)
    +UNAME_TARGET_SYSTEM ?= $(UNAME)
    +
    +ifeq ($(UNAME_TARGET_SYSTEM), Darwin)
       SHARED_EXT = dylib
       SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT)
       SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT)
       SONAME_FLAGS = -install_name $(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER)
     else
    -  ifeq ($(UNAME), AIX)
    +  ifeq ($(UNAME_TARGET_SYSTEM), AIX)
         SONAME_FLAGS =
       else
         SONAME_FLAGS = -Wl,-soname=libzstd.$(SHARED_EXT).$(LIBVER_MAJOR)
    @@ -108,6 +110,9 @@ ifndef BUILD_DIR
     # determine BUILD_DIR from compilation flags
     
     libzstd.a:
    +	@echo uname_target $(UNAME_TARGET)
    +	@echo target_system $(TARGET_SYSTEM)
    +	@echo uname $(uname)
     	$(SET_CACHE_DIRECTORY)
     
     else
    
    From 5a7f5c745cfb7135f27002efc79fee1804d21d44 Mon Sep 17 00:00:00 2001
    From: Bent 
    Date: Thu, 19 Dec 2024 12:22:10 +0100
    Subject: [PATCH 198/405] removed debug echos
    
    ---
     lib/Makefile | 3 ---
     1 file changed, 3 deletions(-)
    
    diff --git a/lib/Makefile b/lib/Makefile
    index 2fe436bc2..a6a0eb09d 100644
    --- a/lib/Makefile
    +++ b/lib/Makefile
    @@ -110,9 +110,6 @@ ifndef BUILD_DIR
     # determine BUILD_DIR from compilation flags
     
     libzstd.a:
    -	@echo uname_target $(UNAME_TARGET)
    -	@echo target_system $(TARGET_SYSTEM)
    -	@echo uname $(uname)
     	$(SET_CACHE_DIRECTORY)
     
     else
    
    From 125f05282b0566790551e6756bdbc0290addfcb2 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Mon, 9 Dec 2024 18:17:34 -0800
    Subject: [PATCH 199/405] publish new symbol
     ZSTD_compressSequencesAndLiterals()
    
    ---
     lib/zstd.h         | 15 +++++++++++++++
     programs/zstdcli.c |  2 --
     2 files changed, 15 insertions(+), 2 deletions(-)
    
    diff --git a/lib/zstd.h b/lib/zstd.h
    index a78b6db45..cfacd58d0 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -1656,6 +1656,21 @@ ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
                             const void* src, size_t srcSize);
     
     
    +/*! ZSTD_compressSequencesAndLiterals() :
    + * This is a variant of ZSTD_compressSequences() which,
    + * instead of receiving (src,srcSize) as input parameter, receives (literals,litSize),
    + * aka all literals already extracted and grouped into a single continuous buffer.
    + * This can be useful if the process generating the sequences also happens to generate the buffer of literals,
    + * thus skipping an extraction + caching stage.
    + * To be valid, `litSize` must be equal to the sum of all @.litLength fields in @inSeqs.
    + * @return : final compressed size, or a ZSTD error code.
    + */
    +ZSTDLIB_STATIC_API size_t
    +ZSTD_compressSequencesAndLiterals( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
    +                        const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    +                        const void* literals, size_t litSize);
    +
    +
     /*! ZSTD_writeSkippableFrame() :
      * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
      *
    diff --git a/programs/zstdcli.c b/programs/zstdcli.c
    index 024552d52..2a9a77624 100644
    --- a/programs/zstdcli.c
    +++ b/programs/zstdcli.c
    @@ -635,8 +635,6 @@ static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressi
             return 0;
         }
     
    -    DISPLAYLEVEL(4, "windowLog=%d, chainLog=%d, hashLog=%d, searchLog=%d \n", params->windowLog, params->chainLog, params->hashLog, params->searchLog);
    -    DISPLAYLEVEL(4, "minMatch=%d, targetLength=%d, strategy=%d \n", params->minMatch, params->targetLength, params->strategy);
         if (stringPtr[0] != 0) return 0; /* check the end of string */
         return 1;
     }
    
    From a00f45a03751a90f620425f30690d86d872dfef1 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Mon, 9 Dec 2024 21:39:34 -0800
    Subject: [PATCH 200/405] created ZSTD_storeSeqOnly()
    
    makes it possible to register a sequence without copying its literals.
    ---
     lib/compress/zstd_compress.c          |  9 ++--
     lib/compress/zstd_compress_internal.h | 76 ++++++++++++++++++---------
     2 files changed, 57 insertions(+), 28 deletions(-)
    
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 3d78b7da3..9df219ded 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -6666,9 +6666,11 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
     }
     
     size_t
    -ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
    +ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx,
    +                                         ZSTD_sequencePosition* seqPos,
                                        const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
    -                                   const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch)
    +                                   const void* src, size_t blockSize,
    +                                         ZSTD_paramSwitch_e externalRepSearch)
     {
         U32 idx = seqPos->idx;
         U32 startPosInSequence = seqPos->posInSequence;
    @@ -6855,7 +6857,7 @@ static size_t determine_blockSize(ZSTD_sequenceFormat_e mode,
         }
     }
     
    -/* Compress, block-by-block, all of the sequences given.
    +/* Compress all provided sequences, block-by-block.
      *
      * Returns the cumulative size of all compressed blocks (including their headers),
      * otherwise a ZSTD error.
    @@ -6896,7 +6898,6 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
             FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size");
             assert(blockSize <= remaining);
             ZSTD_resetSeqStore(&cctx->seqStore);
    -        DEBUGLOG(5, "Working on new block. Blocksize: %zu (total:%zu)", blockSize, (ip - (const BYTE*)src) + blockSize);
     
             additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize, cctx->appliedParams.searchForExternalRepcodes);
             FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
    diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
    index 2d3510adc..d49023d88 100644
    --- a/lib/compress/zstd_compress_internal.h
    +++ b/lib/compress/zstd_compress_internal.h
    @@ -671,6 +671,57 @@ ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE con
     #define OFFBASE_TO_OFFSET(o)  (assert(OFFBASE_IS_OFFSET(o)), (o) - ZSTD_REP_NUM)
     #define OFFBASE_TO_REPCODE(o) (assert(OFFBASE_IS_REPCODE(o)), (o))  /* returns ID 1,2,3 */
     
    +/*! ZSTD_storeSeqOnly() :
    + *  Store a sequence (litlen, litPtr, offBase and matchLength) into seqStore_t.
    + *  Literals themselves are not copied, but @litPtr is updated.
    + *  @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().
    + *  @matchLength : must be >= MINMATCH
    +*/
    +HINT_INLINE UNUSED_ATTR void
    +ZSTD_storeSeqOnly(seqStore_t* seqStorePtr,
    +              size_t litLength,
    +              U32 offBase,
    +              size_t matchLength)
    +{
    +#if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)
    +    static const BYTE* g_start = NULL;
    +    if (g_start==NULL) g_start = (const BYTE*)literals;  /* note : index only works for compression within a single segment */
    +    {   U32 const pos = (U32)((const BYTE*)literals - g_start);
    +        DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offBase%7u",
    +               pos, (U32)litLength, (U32)matchLength, (U32)offBase);
    +    }
    +#endif
    +    assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
    +    /* update seqStorePtr->lit, so that we know how many literals were or will be copied */
    +    assert(seqStorePtr->maxNbLit <= 128 KB);
    +    assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
    +    seqStorePtr->lit += litLength;
    +
    +    /* literal Length */
    +    if (litLength>0xFFFF) {
    +        assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
    +        seqStorePtr->longLengthType = ZSTD_llt_literalLength;
    +        seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
    +    }
    +    seqStorePtr->sequences[0].litLength = (U16)litLength;
    +
    +    /* match offset */
    +    seqStorePtr->sequences[0].offBase = offBase;
    +
    +    /* match Length */
    +    assert(matchLength >= MINMATCH);
    +    {   size_t const mlBase = matchLength - MINMATCH;
    +        if (mlBase>0xFFFF) {
    +            assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
    +            seqStorePtr->longLengthType = ZSTD_llt_matchLength;
    +            seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
    +        }
    +        seqStorePtr->sequences[0].mlBase = (U16)mlBase;
    +    }
    +
    +    seqStorePtr->sequences++;
    +}
    +
     /*! ZSTD_storeSeq() :
      *  Store a sequence (litlen, litPtr, offBase and matchLength) into seqStore_t.
      *  @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().
    @@ -710,31 +761,8 @@ ZSTD_storeSeq(seqStore_t* seqStorePtr,
         } else {
             ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);
         }
    -    seqStorePtr->lit += litLength;
     
    -    /* literal Length */
    -    if (litLength>0xFFFF) {
    -        assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
    -        seqStorePtr->longLengthType = ZSTD_llt_literalLength;
    -        seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
    -    }
    -    seqStorePtr->sequences[0].litLength = (U16)litLength;
    -
    -    /* match offset */
    -    seqStorePtr->sequences[0].offBase = offBase;
    -
    -    /* match Length */
    -    assert(matchLength >= MINMATCH);
    -    {   size_t const mlBase = matchLength - MINMATCH;
    -        if (mlBase>0xFFFF) {
    -            assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
    -            seqStorePtr->longLengthType = ZSTD_llt_matchLength;
    -            seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
    -        }
    -        seqStorePtr->sequences[0].mlBase = (U16)mlBase;
    -    }
    -
    -    seqStorePtr->sequences++;
    +    ZSTD_storeSeqOnly(seqStorePtr, litLength, offBase, matchLength);
     }
     
     /* ZSTD_updateRep() :
    
    From b4a40a845fffc07a0e95a8a59fdbb1b87934d256 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Tue, 10 Dec 2024 11:04:25 -0800
    Subject: [PATCH 201/405] move Sequences definition to zstd_compress_internal.h
    
    they should not be in common/zstd_internal.h,
    since these definitions are not shared beyond lib/compress/.
    ---
     build/single_file_libs/examples/zstd_errors.h | 106 ++++++++++++++++++
     doc/zstd_manual.html                          |  16 ++-
     lib/common/zstd_internal.h                    |  60 ----------
     lib/compress/zstd_compress.c                  |   2 +-
     lib/compress/zstd_compress_internal.h         |  64 +++++++++++
     lib/compress/zstd_compress_sequences.h        |   1 +
     6 files changed, 187 insertions(+), 62 deletions(-)
     create mode 100644 build/single_file_libs/examples/zstd_errors.h
    
    diff --git a/build/single_file_libs/examples/zstd_errors.h b/build/single_file_libs/examples/zstd_errors.h
    new file mode 100644
    index 000000000..20e488f15
    --- /dev/null
    +++ b/build/single_file_libs/examples/zstd_errors.h
    @@ -0,0 +1,106 @@
    +/*
    + * Copyright (c) Meta Platforms, Inc. and affiliates.
    + * All rights reserved.
    + *
    + * This source code is licensed under both the BSD-style license (found in the
    + * LICENSE file in the root directory of this source tree) and the GPLv2 (found
    + * in the COPYING file in the root directory of this source tree).
    + * You may select, at your option, one of the above-listed licenses.
    + */
    +
    +#ifndef ZSTD_ERRORS_H_398273423
    +#define ZSTD_ERRORS_H_398273423
    +
    +#if defined (__cplusplus)
    +extern "C" {
    +#endif
    +
    +/* =====   ZSTDERRORLIB_API : control library symbols visibility   ===== */
    +#ifndef ZSTDERRORLIB_VISIBLE
    +   /* Backwards compatibility with old macro name */
    +#  ifdef ZSTDERRORLIB_VISIBILITY
    +#    define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY
    +#  elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
    +#    define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility ("default")))
    +#  else
    +#    define ZSTDERRORLIB_VISIBLE
    +#  endif
    +#endif
    +
    +#ifndef ZSTDERRORLIB_HIDDEN
    +#  if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
    +#    define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility ("hidden")))
    +#  else
    +#    define ZSTDERRORLIB_HIDDEN
    +#  endif
    +#endif
    +
    +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
    +#  define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE
    +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
    +#  define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
    +#else
    +#  define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE
    +#endif
    +
    +/*-*********************************************
    + *  Error codes list
    + *-*********************************************
    + *  Error codes _values_ are pinned down since v1.3.1 only.
    + *  Therefore, don't rely on values if you may link to any version < v1.3.1.
    + *
    + *  Only values < 100 are considered stable.
    + *
    + *  note 1 : this API shall be used with static linking only.
    + *           dynamic linking is not yet officially supported.
    + *  note 2 : Prefer relying on the enum than on its value whenever possible
    + *           This is the only supported way to use the error list < v1.3.1
    + *  note 3 : ZSTD_isError() is always correct, whatever the library version.
    + **********************************************/
    +typedef enum {
    +  ZSTD_error_no_error = 0,
    +  ZSTD_error_GENERIC  = 1,
    +  ZSTD_error_prefix_unknown                = 10,
    +  ZSTD_error_version_unsupported           = 12,
    +  ZSTD_error_frameParameter_unsupported    = 14,
    +  ZSTD_error_frameParameter_windowTooLarge = 16,
    +  ZSTD_error_corruption_detected = 20,
    +  ZSTD_error_checksum_wrong      = 22,
    +  ZSTD_error_literals_headerWrong = 24,
    +  ZSTD_error_dictionary_corrupted      = 30,
    +  ZSTD_error_dictionary_wrong          = 32,
    +  ZSTD_error_dictionaryCreation_failed = 34,
    +  ZSTD_error_parameter_unsupported   = 40,
    +  ZSTD_error_parameter_combination_unsupported = 41,
    +  ZSTD_error_parameter_outOfBound    = 42,
    +  ZSTD_error_tableLog_tooLarge       = 44,
    +  ZSTD_error_maxSymbolValue_tooLarge = 46,
    +  ZSTD_error_maxSymbolValue_tooSmall = 48,
    +  ZSTD_error_stabilityCondition_notRespected = 50,
    +  ZSTD_error_stage_wrong       = 60,
    +  ZSTD_error_init_missing      = 62,
    +  ZSTD_error_memory_allocation = 64,
    +  ZSTD_error_workSpace_tooSmall= 66,
    +  ZSTD_error_dstSize_tooSmall = 70,
    +  ZSTD_error_srcSize_wrong    = 72,
    +  ZSTD_error_dstBuffer_null   = 74,
    +  ZSTD_error_noForwardProgress_destFull = 80,
    +  ZSTD_error_noForwardProgress_inputEmpty = 82,
    +  /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
    +  ZSTD_error_frameIndex_tooLarge = 100,
    +  ZSTD_error_seekableIO          = 102,
    +  ZSTD_error_dstBuffer_wrong     = 104,
    +  ZSTD_error_srcBuffer_wrong     = 105,
    +  ZSTD_error_sequenceProducer_failed = 106,
    +  ZSTD_error_externalSequences_invalid = 107,
    +  ZSTD_error_maxCode = 120  /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
    +} ZSTD_ErrorCode;
    +
    +ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);   /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
    +
    +
    +#if defined (__cplusplus)
    +}
    +#endif
    +
    +#endif /* ZSTD_ERRORS_H_398273423 */
    diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
    index 8118b7362..bcd1f05da 100644
    --- a/doc/zstd_manual.html
    +++ b/doc/zstd_manual.html
    @@ -154,7 +154,7 @@ size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in w
      it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)
      as it eliminates one potential failure scenario,
      aka not enough room in dst buffer to write the compressed frame.
    - Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE .
    + Note : ZSTD_compressBound() itself can fail, if @srcSize >= ZSTD_MAX_INPUT_SIZE .
             In which case, ZSTD_compressBound() will return an error code
             which can be tested using ZSTD_isError().
     
    @@ -1410,6 +1410,20 @@ ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
      
     


    +
    ZSTDLIB_STATIC_API size_t
    +ZSTD_compressSequencesAndLiterals( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
    +            const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    +            const void* literals, size_t litSize);
    +

    This is a variant of ZSTD_compressSequences() which, + instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), + aka all literals already extracted and grouped into a single continuous buffer. + This can be useful if the process generating the sequences also happens to generate the buffer of literals, + thus skipping an extraction + caching stage. + To be valid, `litSize` must be equal to the sum of all @.litLength fields in @inSeqs. + @return : final compressed size, or a ZSTD error code. + +


    +
    ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
                                     const void* src, size_t srcSize, unsigned magicVariant);
     

    Generates a zstd skippable frame containing data given by src, and writes it to dst buffer. diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index ecb9cfba8..1122e2f39 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -278,62 +278,6 @@ typedef enum { /*-******************************************* * Private declarations *********************************************/ -typedef struct seqDef_s { - U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */ - U16 litLength; - U16 mlBase; /* mlBase == matchLength - MINMATCH */ -} seqDef; - -/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */ -typedef enum { - ZSTD_llt_none = 0, /* no longLengthType */ - ZSTD_llt_literalLength = 1, /* represents a long literal */ - ZSTD_llt_matchLength = 2 /* represents a long match */ -} ZSTD_longLengthType_e; - -typedef struct { - seqDef* sequencesStart; - seqDef* sequences; /* ptr to end of sequences */ - BYTE* litStart; - BYTE* lit; /* ptr to end of literals */ - BYTE* llCode; - BYTE* mlCode; - BYTE* ofCode; - size_t maxNbSeq; - size_t maxNbLit; - - /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength - * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment - * the existing value of the litLength or matchLength by 0x10000. - */ - ZSTD_longLengthType_e longLengthType; - U32 longLengthPos; /* Index of the sequence to apply long length modification to */ -} seqStore_t; - -typedef struct { - U32 litLength; - U32 matchLength; -} ZSTD_sequenceLength; - -/** - * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences - * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. - */ -MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq) -{ - ZSTD_sequenceLength seqLen; - seqLen.litLength = seq->litLength; - seqLen.matchLength = seq->mlBase + MINMATCH; - if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) { - if (seqStore->longLengthType == ZSTD_llt_literalLength) { - seqLen.litLength += 0x10000; - } - if (seqStore->longLengthType == ZSTD_llt_matchLength) { - seqLen.matchLength += 0x10000; - } - } - return seqLen; -} /** * Contains the compressed frame size and an upper-bound for the decompressed frame size. @@ -347,10 +291,6 @@ typedef struct { unsigned long long decompressedBound; } ZSTD_frameSizeInfo; /* decompress & legacy */ -const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ -int ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ - - /* ZSTD_invalidateRepCodes() : * ensures next compression will not use repcodes from previous block. * Note : only works with regular variant; diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9df219ded..a86748dae 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6909,7 +6909,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) { cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed"); - DEBUGLOG(5, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize); + DEBUGLOG(5, "Block too small (%zu): data remains uncompressed: cSize=%zu", blockSize, cBlockSize); cSize += cBlockSize; ip += blockSize; op += cBlockSize; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index d49023d88..e9f058771 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -83,6 +83,70 @@ typedef struct { ZSTD_fseCTables_t fse; } ZSTD_entropyCTables_t; +/*********************************************** +* Sequences * +***********************************************/ +typedef struct seqDef_s { + U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */ + U16 litLength; + U16 mlBase; /* mlBase == matchLength - MINMATCH */ +} seqDef; + +/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */ +typedef enum { + ZSTD_llt_none = 0, /* no longLengthType */ + ZSTD_llt_literalLength = 1, /* represents a long literal */ + ZSTD_llt_matchLength = 2 /* represents a long match */ +} ZSTD_longLengthType_e; + +typedef struct { + seqDef* sequencesStart; + seqDef* sequences; /* ptr to end of sequences */ + BYTE* litStart; + BYTE* lit; /* ptr to end of literals */ + BYTE* llCode; + BYTE* mlCode; + BYTE* ofCode; + size_t maxNbSeq; + size_t maxNbLit; + + /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength + * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment + * the existing value of the litLength or matchLength by 0x10000. + */ + ZSTD_longLengthType_e longLengthType; + U32 longLengthPos; /* Index of the sequence to apply long length modification to */ +} seqStore_t; + +typedef struct { + U32 litLength; + U32 matchLength; +} ZSTD_sequenceLength; + +/** + * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences + * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. + */ +MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq) +{ + ZSTD_sequenceLength seqLen; + seqLen.litLength = seq->litLength; + seqLen.matchLength = seq->mlBase + MINMATCH; + if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) { + if (seqStore->longLengthType == ZSTD_llt_literalLength) { + seqLen.litLength += 0x10000; + } + if (seqStore->longLengthType == ZSTD_llt_matchLength) { + seqLen.matchLength += 0x10000; + } + } + return seqLen; +} + +const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ +int ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ + + /*********************************************** * Entropy buffer statistics structs and funcs * ***********************************************/ diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index 4a3a05da9..fb393cca2 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -11,6 +11,7 @@ #ifndef ZSTD_COMPRESS_SEQUENCES_H #define ZSTD_COMPRESS_SEQUENCES_H +#include "zstd_compress_internal.h" /* seqDef */ #include "../common/fse.h" /* FSE_repeat, FSE_CTable */ #include "../common/zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ From 9671813375cec4576f874eab00ebe669e3cfbe36 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 11:06:58 -0800 Subject: [PATCH 202/405] codemod: seqDef -> SeqDef SeqDef is a type name, so it should start with a Capital letter. It's an internal symbol, no impact on public API. --- lib/compress/zstd_compress.c | 16 ++++++++-------- lib/compress/zstd_compress_internal.h | 10 +++++----- lib/compress/zstd_compress_sequences.c | 8 ++++---- lib/compress/zstd_compress_sequences.h | 4 ++-- lib/compress/zstd_compress_superblock.c | 18 +++++++++--------- lib/dictBuilder/zdict.c | 2 +- tests/decodecorpus.c | 4 ++-- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a86748dae..16544e985 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1722,7 +1722,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer); size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(seqDef)) + + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(SeqDef)) + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); size_t const tmpWorkSpace = ZSTD_cwksp_alloc_size(TMP_WORKSPACE_SIZE); size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); @@ -2224,7 +2224,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, needsIndexReset, ZSTD_resetTarget_CCtx), ""); - zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned64(ws, maxNbSeq * sizeof(seqDef)); + zc->seqStore.sequencesStart = (SeqDef*)ZSTD_cwksp_reserve_aligned64(ws, maxNbSeq * sizeof(SeqDef)); /* ldm hash table */ if (params->ldmParams.enableLdm == ZSTD_ps_enable) { @@ -2700,7 +2700,7 @@ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* par int ZSTD_seqToCodes(const seqStore_t* seqStorePtr) { - const seqDef* const sequences = seqStorePtr->sequencesStart; + const SeqDef* const sequences = seqStorePtr->sequencesStart; BYTE* const llCodeTable = seqStorePtr->llCode; BYTE* const ofCodeTable = seqStorePtr->ofCode; BYTE* const mlCodeTable = seqStorePtr->mlCode; @@ -2907,7 +2907,7 @@ ZSTD_entropyCompressSeqStore_internal( FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable; FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable; FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable; - const seqDef* const sequences = seqStorePtr->sequencesStart; + const SeqDef* const sequences = seqStorePtr->sequencesStart; const size_t nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); const BYTE* const ofCodeTable = seqStorePtr->ofCode; const BYTE* const llCodeTable = seqStorePtr->llCode; @@ -3385,7 +3385,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const seqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM]) { - const seqDef* inSeqs = seqStore->sequencesStart; + const SeqDef* inSeqs = seqStore->sequencesStart; const size_t nbInSequences = seqStore->sequences - inSeqs; const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart); @@ -3929,7 +3929,7 @@ static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); size_t i; for (i = 0; i < nbSeqs; ++i) { - seqDef const seq = seqStore->sequencesStart[i]; + SeqDef const seq = seqStore->sequencesStart[i]; literalsBytes += seq.litLength; if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) { literalsBytes += 0x10000; @@ -3944,7 +3944,7 @@ static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); size_t i; for (i = 0; i < nbSeqs; ++i) { - seqDef seq = seqStore->sequencesStart[i]; + SeqDef seq = seqStore->sequencesStart[i]; matchBytes += seq.mlBase + MINMATCH; if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) { matchBytes += 0x10000; @@ -4030,7 +4030,7 @@ ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRe U32 idx = 0; U32 const longLitLenIdx = seqStore->longLengthType == ZSTD_llt_literalLength ? seqStore->longLengthPos : nbSeq; for (; idx < nbSeq; ++idx) { - seqDef* const seq = seqStore->sequencesStart + idx; + SeqDef* const seq = seqStore->sequencesStart + idx; U32 const ll0 = (seq->litLength == 0) && (idx != longLitLenIdx); U32 const offBase = seq->offBase; assert(offBase > 0); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index e9f058771..fcd8622cf 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -86,11 +86,11 @@ typedef struct { /*********************************************** * Sequences * ***********************************************/ -typedef struct seqDef_s { +typedef struct SeqDef_s { U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */ U16 litLength; U16 mlBase; /* mlBase == matchLength - MINMATCH */ -} seqDef; +} SeqDef; /* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */ typedef enum { @@ -100,8 +100,8 @@ typedef enum { } ZSTD_longLengthType_e; typedef struct { - seqDef* sequencesStart; - seqDef* sequences; /* ptr to end of sequences */ + SeqDef* sequencesStart; + SeqDef* sequences; /* ptr to end of sequences */ BYTE* litStart; BYTE* lit; /* ptr to end of literals */ BYTE* llCode; @@ -127,7 +127,7 @@ typedef struct { * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. */ -MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq) +MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, SeqDef const* seq) { ZSTD_sequenceLength seqLen; seqLen.litLength = seq->litLength; diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index 8872d4d35..7a9d595b1 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -293,7 +293,7 @@ ZSTD_encodeSequences_body( FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable, FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable, - seqDef const* sequences, size_t nbSeq, int longOffsets) + SeqDef const* sequences, size_t nbSeq, int longOffsets) { BIT_CStream_t blockStream; FSE_CState_t stateMatchLength; @@ -387,7 +387,7 @@ ZSTD_encodeSequences_default( FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable, FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable, - seqDef const* sequences, size_t nbSeq, int longOffsets) + SeqDef const* sequences, size_t nbSeq, int longOffsets) { return ZSTD_encodeSequences_body(dst, dstCapacity, CTable_MatchLength, mlCodeTable, @@ -405,7 +405,7 @@ ZSTD_encodeSequences_bmi2( FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable, FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable, - seqDef const* sequences, size_t nbSeq, int longOffsets) + SeqDef const* sequences, size_t nbSeq, int longOffsets) { return ZSTD_encodeSequences_body(dst, dstCapacity, CTable_MatchLength, mlCodeTable, @@ -421,7 +421,7 @@ size_t ZSTD_encodeSequences( FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable, FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable, - seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2) + SeqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2) { DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity); #if DYNAMIC_BMI2 diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index fb393cca2..b974d1cfc 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -11,7 +11,7 @@ #ifndef ZSTD_COMPRESS_SEQUENCES_H #define ZSTD_COMPRESS_SEQUENCES_H -#include "zstd_compress_internal.h" /* seqDef */ +#include "zstd_compress_internal.h" /* SeqDef */ #include "../common/fse.h" /* FSE_repeat, FSE_CTable */ #include "../common/zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ @@ -43,7 +43,7 @@ size_t ZSTD_encodeSequences( FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable, FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable, - seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2); + SeqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2); size_t ZSTD_fseBitCost( FSE_CTable const* ctable, diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 97321bc76..a8882c169 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -127,7 +127,7 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, - const seqDef* sequences, size_t nbSeqs, + const SeqDef* sequences, size_t nbSeqs, size_t litSize, int lastSubBlock) { size_t matchLengthSum = 0; @@ -162,7 +162,7 @@ ZSTD_seqDecompressedSize(seqStore_t const* seqStore, static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables, const ZSTD_fseCTablesMetadata_t* fseMetadata, - const seqDef* sequences, size_t nbSeq, + const SeqDef* sequences, size_t nbSeq, const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, const ZSTD_CCtx_params* cctxParams, void* dst, size_t dstCapacity, @@ -262,7 +262,7 @@ ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables, * Or 0 if it failed to compress. */ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, const ZSTD_entropyCTablesMetadata_t* entropyMetadata, - const seqDef* sequences, size_t nbSeq, + const SeqDef* sequences, size_t nbSeq, const BYTE* literals, size_t litSize, const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, const ZSTD_CCtx_params* cctxParams, @@ -426,7 +426,7 @@ static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMe return 0; } -static size_t countLiterals(seqStore_t const* seqStore, const seqDef* sp, size_t seqCount) +static size_t countLiterals(seqStore_t const* seqStore, const SeqDef* sp, size_t seqCount) { size_t n, total = 0; assert(sp != NULL); @@ -439,7 +439,7 @@ static size_t countLiterals(seqStore_t const* seqStore, const seqDef* sp, size_t #define BYTESCALE 256 -static size_t sizeBlockSequences(const seqDef* sp, size_t nbSeqs, +static size_t sizeBlockSequences(const SeqDef* sp, size_t nbSeqs, size_t targetBudget, size_t avgLitCost, size_t avgSeqCost, int firstSubBlock) { @@ -486,9 +486,9 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, const int bmi2, U32 lastBlock, void* workspace, size_t wkspSize) { - const seqDef* const sstart = seqStorePtr->sequencesStart; - const seqDef* const send = seqStorePtr->sequences; - const seqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */ + const SeqDef* const sstart = seqStorePtr->sequencesStart; + const SeqDef* const send = seqStorePtr->sequences; + const SeqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */ size_t const nbSeqs = (size_t)(send - sstart); const BYTE* const lstart = seqStorePtr->litStart; const BYTE* const lend = seqStorePtr->lit; @@ -647,7 +647,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, op += cSize; /* We have to regenerate the repcodes because we've skipped some sequences */ if (sp < send) { - const seqDef* seq; + const SeqDef* seq; repcodes_t rep; ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep)); for (seq = sstart; seq < sp; ++seq) { diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 82e999e80..1164f03f5 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -608,7 +608,7 @@ static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params, } if (nbSeq >= 2) { /* rep offsets */ - const seqDef* const seq = seqStorePtr->sequencesStart; + const SeqDef* const seq = seqStorePtr->sequencesStart; U32 offset1 = seq[0].offBase - ZSTD_REP_NUM; U32 offset2 = seq[1].offBase - ZSTD_REP_NUM; if (offset1 >= MAXREPOFFSET) offset1 = 0; diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index f25e5dc7c..dd425ac52 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -182,7 +182,7 @@ BYTE CONTENT_BUFFER[MAX_DECOMPRESSED_SIZE]; BYTE FRAME_BUFFER[MAX_DECOMPRESSED_SIZE * 2]; BYTE LITERAL_BUFFER[ZSTD_BLOCKSIZE_MAX]; -seqDef SEQUENCE_BUFFER[MAX_NB_SEQ]; +SeqDef SEQUENCE_BUFFER[MAX_NB_SEQ]; BYTE SEQUENCE_LITERAL_BUFFER[ZSTD_BLOCKSIZE_MAX]; /* storeSeq expects a place to copy literals to */ BYTE SEQUENCE_LLCODE[ZSTD_BLOCKSIZE_MAX]; BYTE SEQUENCE_MLCODE[ZSTD_BLOCKSIZE_MAX]; @@ -842,7 +842,7 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr, FSE_CTable* CTable_OffsetBits = frame->stats.offcodeCTable; FSE_CTable* CTable_MatchLength = frame->stats.matchlengthCTable; U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ - const seqDef* const sequences = seqStorePtr->sequencesStart; + const SeqDef* const sequences = seqStorePtr->sequencesStart; const BYTE* const ofCodeTable = seqStorePtr->ofCode; const BYTE* const llCodeTable = seqStorePtr->llCode; const BYTE* const mlCodeTable = seqStorePtr->mlCode; From a2245721ca3e91261d7c948f7a71d195caf1f871 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 11:09:52 -0800 Subject: [PATCH 203/405] codemod: seqStore_t -> SeqStore_t same idea, SeqStore_t is a type name, it should start with a Capital letter. --- lib/compress/zstd_compress.c | 50 ++++++++++----------- lib/compress/zstd_compress_internal.h | 36 +++++++-------- lib/compress/zstd_compress_superblock.c | 6 +-- lib/compress/zstd_double_fast.c | 14 +++--- lib/compress/zstd_double_fast.h | 6 +-- lib/compress/zstd_fast.c | 14 +++--- lib/compress/zstd_fast.h | 6 +-- lib/compress/zstd_lazy.c | 58 ++++++++++++------------- lib/compress/zstd_lazy.h | 54 +++++++++++------------ lib/compress/zstd_ldm.c | 2 +- lib/compress/zstd_ldm.h | 2 +- lib/compress/zstd_opt.c | 22 +++++----- lib/compress/zstd_opt.h | 14 +++--- lib/dictBuilder/zdict.c | 2 +- lib/legacy/zstd_v01.c | 4 +- lib/legacy/zstd_v02.c | 2 +- lib/legacy/zstd_v03.c | 2 +- lib/legacy/zstd_v05.c | 2 +- lib/legacy/zstd_v06.c | 4 +- lib/legacy/zstd_v07.c | 4 +- tests/decodecorpus.c | 8 ++-- 21 files changed, 156 insertions(+), 156 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 16544e985..075f491d6 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -218,7 +218,7 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) } /* private API call, for dictBuilder only */ -const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } +const SeqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } /* Returns true if the strategy supports using a row based matchfinder */ static int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) { @@ -2698,7 +2698,7 @@ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* par /* See doc/zstd_compression_format.md for detailed format description */ -int ZSTD_seqToCodes(const seqStore_t* seqStorePtr) +int ZSTD_seqToCodes(const SeqStore_t* seqStorePtr) { const SeqDef* const sequences = seqStorePtr->sequencesStart; BYTE* const llCodeTable = seqStorePtr->llCode; @@ -2769,7 +2769,7 @@ typedef struct { */ static ZSTD_symbolEncodingTypeStats_t ZSTD_buildSequencesStatistics( - const seqStore_t* seqStorePtr, size_t nbSeq, + const SeqStore_t* seqStorePtr, size_t nbSeq, const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy, BYTE* dst, const BYTE* const dstEnd, ZSTD_strategy strategy, unsigned* countWorkspace, @@ -2894,7 +2894,7 @@ ZSTD_buildSequencesStatistics( #define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20 MEM_STATIC size_t ZSTD_entropyCompressSeqStore_internal( - const seqStore_t* seqStorePtr, + const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -3014,7 +3014,7 @@ ZSTD_entropyCompressSeqStore_internal( MEM_STATIC size_t ZSTD_entropyCompressSeqStore( - const seqStore_t* seqStorePtr, + const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -3137,14 +3137,14 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramS return selectedCompressor; } -static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr, +static void ZSTD_storeLastLiterals(SeqStore_t* seqStorePtr, const BYTE* anchor, size_t lastLLSize) { ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize); seqStorePtr->lit += lastLLSize; } -void ZSTD_resetSeqStore(seqStore_t* ssPtr) +void ZSTD_resetSeqStore(SeqStore_t* ssPtr) { ssPtr->lit = ssPtr->litStart; ssPtr->sequences = ssPtr->sequencesStart; @@ -3383,7 +3383,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) return ZSTDbss_compress; } -static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const seqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM]) +static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const SeqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM]) { const SeqDef* inSeqs = seqStore->sequencesStart; const size_t nbInSequences = seqStore->sequences - inSeqs; @@ -3552,7 +3552,7 @@ static int ZSTD_isRLE(const BYTE* src, size_t length) { * This is just a heuristic based on the compressibility. * It may return both false positives and false negatives. */ -static int ZSTD_maybeRLE(seqStore_t const* seqStore) +static int ZSTD_maybeRLE(SeqStore_t const* seqStore) { size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart); @@ -3714,7 +3714,7 @@ ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) * @return : size of fse tables or error code */ static size_t ZSTD_buildBlockEntropyStats_sequences( - const seqStore_t* seqStorePtr, + const SeqStore_t* seqStorePtr, const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -3753,7 +3753,7 @@ ZSTD_buildBlockEntropyStats_sequences( * Note : also employed in superblock */ size_t ZSTD_buildBlockEntropyStats( - const seqStore_t* seqStorePtr, + const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -3902,7 +3902,7 @@ ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize, * @return: estimated compressed size of the seqStore, or a zstd error. */ static size_t -ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CCtx* zc) +ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(SeqStore_t* seqStore, ZSTD_CCtx* zc) { ZSTD_entropyCTablesMetadata_t* const entropyMetadata = &zc->blockSplitCtx.entropyMetadata; DEBUGLOG(6, "ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize()"); @@ -3923,7 +3923,7 @@ ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CC } /* Returns literals bytes represented in a seqStore */ -static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) +static size_t ZSTD_countSeqStoreLiteralsBytes(const SeqStore_t* const seqStore) { size_t literalsBytes = 0; size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); @@ -3938,7 +3938,7 @@ static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) } /* Returns match bytes represented in a seqStore */ -static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) +static size_t ZSTD_countSeqStoreMatchBytes(const SeqStore_t* const seqStore) { size_t matchBytes = 0; size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); @@ -3955,8 +3955,8 @@ static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) /* Derives the seqStore that is a chunk of the originalSeqStore from [startIdx, endIdx). * Stores the result in resultSeqStore. */ -static void ZSTD_deriveSeqStoreChunk(seqStore_t* resultSeqStore, - const seqStore_t* originalSeqStore, +static void ZSTD_deriveSeqStoreChunk(SeqStore_t* resultSeqStore, + const SeqStore_t* originalSeqStore, size_t startIdx, size_t endIdx) { *resultSeqStore = *originalSeqStore; @@ -4025,7 +4025,7 @@ ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, c */ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes, - const seqStore_t* const seqStore, U32 const nbSeq) + const SeqStore_t* const seqStore, U32 const nbSeq) { U32 idx = 0; U32 const longLitLenIdx = seqStore->longLengthType == ZSTD_llt_literalLength ? seqStore->longLengthPos : nbSeq; @@ -4060,7 +4060,7 @@ ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRe */ static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, - const seqStore_t* const seqStore, + const SeqStore_t* const seqStore, repcodes_t* const dRep, repcodes_t* const cRep, void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -4152,11 +4152,11 @@ typedef struct { */ static void ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx, - ZSTD_CCtx* zc, const seqStore_t* origSeqStore) + ZSTD_CCtx* zc, const SeqStore_t* origSeqStore) { - seqStore_t* const fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk; - seqStore_t* const firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore; - seqStore_t* const secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore; + SeqStore_t* const fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk; + SeqStore_t* const firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore; + SeqStore_t* const secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore; size_t estimatedOriginalSize; size_t estimatedFirstHalfSize; size_t estimatedSecondHalfSize; @@ -4226,8 +4226,8 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, size_t i = 0; size_t srcBytesTotal = 0; U32* const partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */ - seqStore_t* const nextSeqStore = &zc->blockSplitCtx.nextSeqStore; - seqStore_t* const currSeqStore = &zc->blockSplitCtx.currSeqStore; + SeqStore_t* const nextSeqStore = &zc->blockSplitCtx.nextSeqStore; + SeqStore_t* const currSeqStore = &zc->blockSplitCtx.currSeqStore; size_t const numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq); /* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history @@ -4248,7 +4248,7 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, repcodes_t cRep; ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); - ZSTD_memset(nextSeqStore, 0, sizeof(seqStore_t)); + ZSTD_memset(nextSeqStore, 0, sizeof(SeqStore_t)); DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index fcd8622cf..121885e6c 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -92,7 +92,7 @@ typedef struct SeqDef_s { U16 mlBase; /* mlBase == matchLength - MINMATCH */ } SeqDef; -/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */ +/* Controls whether seqStore has a single "long" litLength or matchLength. See SeqStore_t. */ typedef enum { ZSTD_llt_none = 0, /* no longLengthType */ ZSTD_llt_literalLength = 1, /* represents a long literal */ @@ -116,7 +116,7 @@ typedef struct { */ ZSTD_longLengthType_e longLengthType; U32 longLengthPos; /* Index of the sequence to apply long length modification to */ -} seqStore_t; +} SeqStore_t; typedef struct { U32 litLength; @@ -127,7 +127,7 @@ typedef struct { * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. */ -MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, SeqDef const* seq) +MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(SeqStore_t const* seqStore, SeqDef const* seq) { ZSTD_sequenceLength seqLen; seqLen.litLength = seq->litLength; @@ -143,8 +143,8 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore return seqLen; } -const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ -int ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ +const SeqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ +int ZSTD_seqToCodes(const SeqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ /*********************************************** @@ -184,7 +184,7 @@ typedef struct { * Builds entropy for the block. * @return : 0 on success or error code */ size_t ZSTD_buildBlockEntropyStats( - const seqStore_t* seqStorePtr, + const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -469,11 +469,11 @@ typedef enum { */ #define ZSTD_MAX_NB_BLOCK_SPLITS 196 typedef struct { - seqStore_t fullSeqStoreChunk; - seqStore_t firstHalfSeqStore; - seqStore_t secondHalfSeqStore; - seqStore_t currSeqStore; - seqStore_t nextSeqStore; + SeqStore_t fullSeqStoreChunk; + SeqStore_t firstHalfSeqStore; + SeqStore_t secondHalfSeqStore; + SeqStore_t currSeqStore; + SeqStore_t nextSeqStore; U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS]; ZSTD_entropyCTablesMetadata_t entropyMetadata; @@ -502,7 +502,7 @@ struct ZSTD_CCtx_s { int isFirstBlock; int initialized; - seqStore_t seqStore; /* sequences storage ptrs */ + SeqStore_t seqStore; /* sequences storage ptrs */ ldmState_t ldmState; /* long distance matching state */ rawSeq* ldmSequences; /* Storage for the ldm output sequences */ size_t maxNbLdmSequences; @@ -586,7 +586,7 @@ typedef enum { } ZSTD_cParamMode_e; typedef size_t (*ZSTD_blockCompressor) ( - ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); @@ -736,13 +736,13 @@ ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE con #define OFFBASE_TO_REPCODE(o) (assert(OFFBASE_IS_REPCODE(o)), (o)) /* returns ID 1,2,3 */ /*! ZSTD_storeSeqOnly() : - * Store a sequence (litlen, litPtr, offBase and matchLength) into seqStore_t. + * Store a sequence (litlen, litPtr, offBase and matchLength) into SeqStore_t. * Literals themselves are not copied, but @litPtr is updated. * @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE(). * @matchLength : must be >= MINMATCH */ HINT_INLINE UNUSED_ATTR void -ZSTD_storeSeqOnly(seqStore_t* seqStorePtr, +ZSTD_storeSeqOnly(SeqStore_t* seqStorePtr, size_t litLength, U32 offBase, size_t matchLength) @@ -787,13 +787,13 @@ ZSTD_storeSeqOnly(seqStore_t* seqStorePtr, } /*! ZSTD_storeSeq() : - * Store a sequence (litlen, litPtr, offBase and matchLength) into seqStore_t. + * Store a sequence (litlen, litPtr, offBase and matchLength) into SeqStore_t. * @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE(). * @matchLength : must be >= MINMATCH * Allowed to over-read literals up to litLimit. */ HINT_INLINE UNUSED_ATTR void -ZSTD_storeSeq(seqStore_t* seqStorePtr, +ZSTD_storeSeq(SeqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offBase, size_t matchLength) @@ -1560,7 +1560,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, const ZSTD_CCtx_params* params, unsigned long long pledgedSrcSize); -void ZSTD_resetSeqStore(seqStore_t* ssPtr); +void ZSTD_resetSeqStore(SeqStore_t* ssPtr); /*! ZSTD_getCParamsFromCDict() : * as the name implies */ diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index a8882c169..d74f44548 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -126,7 +126,7 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, } static size_t -ZSTD_seqDecompressedSize(seqStore_t const* seqStore, +ZSTD_seqDecompressedSize(SeqStore_t const* seqStore, const SeqDef* sequences, size_t nbSeqs, size_t litSize, int lastSubBlock) { @@ -426,7 +426,7 @@ static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMe return 0; } -static size_t countLiterals(seqStore_t const* seqStore, const SeqDef* sp, size_t seqCount) +static size_t countLiterals(SeqStore_t const* seqStore, const SeqDef* sp, size_t seqCount) { size_t n, total = 0; assert(sp != NULL); @@ -476,7 +476,7 @@ static size_t sizeBlockSequences(const SeqDef* sp, size_t nbSeqs, * Sub-blocks are all compressed, except the last one when beneficial. * @return : compressed size of the super block (which features multiple ZSTD blocks) * or 0 if it failed to compress. */ -static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, +static size_t ZSTD_compressSubBlock_multi(const SeqStore_t* seqStorePtr, const ZSTD_compressedBlockState_t* prevCBlock, ZSTD_compressedBlockState_t* nextCBlock, const ZSTD_entropyCTablesMetadata_t* entropyMetadata, diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 50d698b37..1406c2d50 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -103,7 +103,7 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_doubleFast_noDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { ZSTD_compressionParameters const* cParams = &ms->cParams; @@ -326,7 +326,7 @@ _match_stored: FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { @@ -548,7 +548,7 @@ _match_stored: #define ZSTD_GEN_DFAST_FN(dictMode, mls) \ static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls( \ - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ void const* src, size_t srcSize) \ { \ return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \ @@ -566,7 +566,7 @@ ZSTD_GEN_DFAST_FN(dictMatchState, 7) size_t ZSTD_compressBlock_doubleFast( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { const U32 mls = ms->cParams.minMatch; @@ -586,7 +586,7 @@ size_t ZSTD_compressBlock_doubleFast( size_t ZSTD_compressBlock_doubleFast_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { const U32 mls = ms->cParams.minMatch; @@ -608,7 +608,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState( static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_doubleFast_extDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { @@ -757,7 +757,7 @@ ZSTD_GEN_DFAST_FN(extDict, 6) ZSTD_GEN_DFAST_FN(extDict, 7) size_t ZSTD_compressBlock_doubleFast_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h index ce6ed8c97..1a746fab9 100644 --- a/lib/compress/zstd_double_fast.h +++ b/lib/compress/zstd_double_fast.h @@ -25,13 +25,13 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, ZSTD_tableFillPurpose_e tfp); size_t ZSTD_compressBlock_doubleFast( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_doubleFast_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_doubleFast_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_DOUBLEFAST ZSTD_compressBlock_doubleFast diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 5373e3640..3c8d5b527 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -190,7 +190,7 @@ ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 ma FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_noDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, int useCmov) { @@ -424,7 +424,7 @@ _match: /* Requires: ip0, match0, offcode */ #define ZSTD_GEN_FAST_FN(dictMode, mml, cmov) \ static size_t ZSTD_compressBlock_fast_##dictMode##_##mml##_##cmov( \ - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ void const* src, size_t srcSize) \ { \ return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mml, cmov); \ @@ -441,7 +441,7 @@ ZSTD_GEN_FAST_FN(noDict, 6, 0) ZSTD_GEN_FAST_FN(noDict, 7, 0) size_t ZSTD_compressBlock_fast( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mml = ms->cParams.minMatch; @@ -481,7 +481,7 @@ size_t ZSTD_compressBlock_fast( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_dictMatchState_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -684,7 +684,7 @@ ZSTD_GEN_FAST_FN(dictMatchState, 6, 0) ZSTD_GEN_FAST_FN(dictMatchState, 7, 0) size_t ZSTD_compressBlock_fast_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; @@ -707,7 +707,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState( static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_extDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -965,7 +965,7 @@ ZSTD_GEN_FAST_FN(extDict, 6, 0) ZSTD_GEN_FAST_FN(extDict, 7, 0) size_t ZSTD_compressBlock_fast_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h index 9e4236b47..5a971cf32 100644 --- a/lib/compress/zstd_fast.h +++ b/lib/compress/zstd_fast.h @@ -22,13 +22,13 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm, ZSTD_tableFillPurpose_e tfp); size_t ZSTD_compressBlock_fast( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_fast_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_fast_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #if defined (__cplusplus) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index cfbadf458..9fe56c76b 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -1514,7 +1514,7 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_lazy_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const searchMethod_e searchMethod, const U32 depth, @@ -1782,42 +1782,42 @@ _storeSequence: #ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_greedy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_noDict); } size_t ZSTD_compressBlock_greedy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch); } size_t ZSTD_compressBlock_greedy_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict); } size_t ZSTD_compressBlock_greedy_dictMatchState_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch); @@ -1826,42 +1826,42 @@ size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( #ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch); } size_t ZSTD_compressBlock_lazy_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy_dictMatchState_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch); @@ -1870,42 +1870,42 @@ size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( #ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch); } size_t ZSTD_compressBlock_lazy2_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy2_dictMatchState_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch); @@ -1914,14 +1914,14 @@ size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( #ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btlazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_noDict); } size_t ZSTD_compressBlock_btlazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_dictMatchState); @@ -1935,7 +1935,7 @@ size_t ZSTD_compressBlock_btlazy2_dictMatchState( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_lazy_extDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const searchMethod_e searchMethod, const U32 depth) @@ -2139,14 +2139,14 @@ _storeSequence: #ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_greedy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0); } size_t ZSTD_compressBlock_greedy_extDict_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0); @@ -2155,7 +2155,7 @@ size_t ZSTD_compressBlock_greedy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { @@ -2163,7 +2163,7 @@ size_t ZSTD_compressBlock_lazy_extDict( } size_t ZSTD_compressBlock_lazy_extDict_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { @@ -2173,7 +2173,7 @@ size_t ZSTD_compressBlock_lazy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { @@ -2181,7 +2181,7 @@ size_t ZSTD_compressBlock_lazy2_extDict( } size_t ZSTD_compressBlock_lazy2_extDict_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2); @@ -2190,7 +2190,7 @@ size_t ZSTD_compressBlock_lazy2_extDict_row( #ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btlazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { diff --git a/lib/compress/zstd_lazy.h b/lib/compress/zstd_lazy.h index 3635813bd..21258145e 100644 --- a/lib/compress/zstd_lazy.h +++ b/lib/compress/zstd_lazy.h @@ -41,28 +41,28 @@ void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const redu #ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_greedy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dictMatchState_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_extDict_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_GREEDY ZSTD_compressBlock_greedy @@ -86,28 +86,28 @@ size_t ZSTD_compressBlock_greedy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dictMatchState_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_extDict_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_LAZY ZSTD_compressBlock_lazy @@ -131,28 +131,28 @@ size_t ZSTD_compressBlock_lazy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dictMatchState_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_extDict_row( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_LAZY2 ZSTD_compressBlock_lazy2 @@ -176,13 +176,13 @@ size_t ZSTD_compressBlock_lazy2_extDict_row( #ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btlazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btlazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btlazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_BTLAZY2 ZSTD_compressBlock_btlazy2 diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index e06431374..e636a42c0 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -665,7 +665,7 @@ void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { } size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize) { diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index f147021d2..624caf937 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -65,7 +65,7 @@ size_t ZSTD_ldm_generateSequences( * NOTE: This function does not return any errors. */ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index e4a8ee81e..1045cdd2c 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1073,7 +1073,7 @@ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, - seqStore_t* seqStore, + SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const int optLevel, @@ -1440,7 +1440,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt0( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode); @@ -1449,7 +1449,7 @@ static size_t ZSTD_compressBlock_opt0( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode); @@ -1458,7 +1458,7 @@ static size_t ZSTD_compressBlock_opt2( #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock_btopt"); @@ -1478,7 +1478,7 @@ size_t ZSTD_compressBlock_btopt( static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_initStats_ultra(ZSTD_matchState_t* ms, - seqStore_t* seqStore, + SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { @@ -1503,7 +1503,7 @@ void ZSTD_initStats_ultra(ZSTD_matchState_t* ms, } size_t ZSTD_compressBlock_btultra( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize); @@ -1511,7 +1511,7 @@ size_t ZSTD_compressBlock_btultra( } size_t ZSTD_compressBlock_btultra2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { U32 const curr = (U32)((const BYTE*)src - ms->window.base); @@ -1541,14 +1541,14 @@ size_t ZSTD_compressBlock_btultra2( #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_btopt_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict); @@ -1557,14 +1557,14 @@ size_t ZSTD_compressBlock_btopt_extDict( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btultra_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_btultra_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict); diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h index d4e711315..9e1cff91a 100644 --- a/lib/compress/zstd_opt.h +++ b/lib/compress/zstd_opt.h @@ -26,13 +26,13 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend); #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btopt_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btopt_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_BTOPT ZSTD_compressBlock_btopt @@ -46,20 +46,20 @@ size_t ZSTD_compressBlock_btopt_extDict( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btultra( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btultra_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btultra_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); /* note : no btultra2 variant for extDict nor dictMatchState, * because btultra2 is not meant to work with dictionaries * and is only specific for the first block (no prefix) */ size_t ZSTD_compressBlock_btultra2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_BTULTRA ZSTD_compressBlock_btultra diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 1164f03f5..d5e60a4da 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -580,7 +580,7 @@ static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params, if (ZSTD_isError(cSize)) { DISPLAYLEVEL(3, "warning : could not compress sample size %u \n", (unsigned)srcSize); return; } if (cSize) { /* if == 0; block is not compressible */ - const seqStore_t* const seqStorePtr = ZSTD_getSeqStore(esr.zc); + const SeqStore_t* const seqStorePtr = ZSTD_getSeqStore(esr.zc); /* literals stats */ { const BYTE* bytePtr; diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index 6cf51234a..ad3c9330e 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -1383,7 +1383,7 @@ typedef struct { BYTE* matchLength; BYTE* dumpsStart; BYTE* dumps; -} seqStore_t; +} SeqStore_t; typedef struct ZSTD_Cctx_s @@ -1391,7 +1391,7 @@ typedef struct ZSTD_Cctx_s const BYTE* base; U32 current; U32 nextUpdate; - seqStore_t seqStore; + SeqStore_t seqStore; #ifdef __AVX2__ __m256i hashTable[HASH_TABLESIZE>>3]; #else diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index 6d39b6e5b..d1e00385a 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -2722,7 +2722,7 @@ typedef struct { BYTE* matchLength; BYTE* dumpsStart; BYTE* dumps; -} seqStore_t; +} SeqStore_t; /* ************************************* diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 47195f337..7d82db666 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -2362,7 +2362,7 @@ typedef struct { BYTE* matchLength; BYTE* dumpsStart; BYTE* dumps; -} seqStore_t; +} SeqStore_t; /* ************************************* diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 44a877bf1..7a3af4214 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -491,7 +491,7 @@ typedef struct { U32 litLengthSum; U32 litSum; U32 offCodeSum; -} seqStore_t; +} SeqStore_t; diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index 3a8bd0c93..88a39e2a0 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -552,9 +552,9 @@ typedef struct { U32 cachedLitLength; const BYTE* cachedLiterals; ZSTDv06_stats_t stats; -} seqStore_t; +} SeqStore_t; -void ZSTDv06_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq); +void ZSTDv06_seqToCodes(const SeqStore_t* seqStorePtr, size_t const nbSeq); #endif /* ZSTDv06_CCOMMON_H_MODULE */ diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index 8778f079c..cdc56288c 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -2787,9 +2787,9 @@ typedef struct { U32 cachedLitLength; const BYTE* cachedLiterals; ZSTDv07_stats_t stats; -} seqStore_t; +} SeqStore_t; -void ZSTDv07_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq); +void ZSTDv07_seqToCodes(const SeqStore_t* seqStorePtr, size_t const nbSeq); /* custom memory allocation functions */ static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction, ZSTDv07_defaultFreeFunction, NULL }; diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index dd425ac52..bbe32ee72 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -657,7 +657,7 @@ static size_t writeLiteralsBlock(U32* seed, frame_t* frame, size_t contentSize) } } -static inline void initSeqStore(seqStore_t *seqStore) { +static inline void initSeqStore(SeqStore_t *seqStore) { seqStore->maxNbSeq = MAX_NB_SEQ; seqStore->maxNbLit = ZSTD_BLOCKSIZE_MAX; seqStore->sequencesStart = SEQUENCE_BUFFER; @@ -671,7 +671,7 @@ static inline void initSeqStore(seqStore_t *seqStore) { /* Randomly generate sequence commands */ static U32 -generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore, +generateSequences(U32* seed, frame_t* frame, SeqStore_t* seqStore, size_t contentSize, size_t literalsSize, dictInfo info) { /* The total length of all the matches */ @@ -832,7 +832,7 @@ static int isSymbolSubset(const BYTE* symbols, size_t len, const BYTE* set, BYTE return 1; } -static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr, +static size_t writeSequences(U32* seed, frame_t* frame, SeqStore_t* seqStorePtr, size_t nbSeq) { /* This code is mostly copied from ZSTD_compressSequences in zstd_compress.c */ @@ -1028,7 +1028,7 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr, static size_t writeSequencesBlock(U32* seed, frame_t* frame, size_t contentSize, size_t literalsSize, dictInfo info) { - seqStore_t seqStore; + SeqStore_t seqStore; size_t numSequences; From 8d4506bc9463607725e43131b71b2f09b7e1109d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 11:27:03 -0800 Subject: [PATCH 204/405] codemod: ZSTD_sequenceLength -> ZSTD_SequenceLength --- lib/compress/zstd_compress_internal.h | 8 ++++---- lib/compress/zstd_compress_superblock.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 121885e6c..92812192f 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -121,15 +121,15 @@ typedef struct { typedef struct { U32 litLength; U32 matchLength; -} ZSTD_sequenceLength; +} ZSTD_SequenceLength; /** - * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences + * Returns the ZSTD_SequenceLength for the given sequences. It handles the decoding of long sequences * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. */ -MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(SeqStore_t const* seqStore, SeqDef const* seq) +MEM_STATIC ZSTD_SequenceLength ZSTD_getSequenceLength(SeqStore_t const* seqStore, SeqDef const* seq) { - ZSTD_sequenceLength seqLen; + ZSTD_SequenceLength seqLen; seqLen.litLength = seq->litLength; seqLen.matchLength = seq->mlBase + MINMATCH; if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) { diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index d74f44548..f2806c9ab 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -134,7 +134,7 @@ ZSTD_seqDecompressedSize(SeqStore_t const* seqStore, size_t litLengthSum = 0; size_t n; for (n=0; n Date: Tue, 10 Dec 2024 11:34:12 -0800 Subject: [PATCH 205/405] codemod: symbolEncodingType_e -> SymbolEncodingType_e --- lib/common/zstd_internal.h | 2 +- lib/compress/zstd_compress.c | 14 +++++++------- lib/compress/zstd_compress_internal.h | 8 ++++---- lib/compress/zstd_compress_literals.c | 2 +- lib/compress/zstd_compress_sequences.c | 4 ++-- lib/compress/zstd_compress_sequences.h | 6 +++--- lib/compress/zstd_compress_superblock.c | 4 ++-- lib/decompress/zstd_decompress_block.c | 10 +++++----- tests/decodecorpus.c | 2 +- tests/fullbench.c | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 1122e2f39..b67ca8633 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -95,7 +95,7 @@ typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */) /* for a non-null block */ #define MIN_LITERALS_FOR_4_STREAMS 6 -typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e; +typedef enum { set_basic, set_rle, set_compressed, set_repeat } SymbolEncodingType_e; #define LONGNBSEQ 0x7F00 diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 075f491d6..1715dad3f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2805,7 +2805,7 @@ ZSTD_buildSequencesStatistics( assert(!(stats.LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ { size_t const countSize = ZSTD_buildCTable( op, (size_t)(oend - op), - CTable_LitLength, LLFSELog, (symbolEncodingType_e)stats.LLtype, + CTable_LitLength, LLFSELog, (SymbolEncodingType_e)stats.LLtype, countWorkspace, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL, prevEntropy->litlengthCTable, @@ -2837,7 +2837,7 @@ ZSTD_buildSequencesStatistics( assert(!(stats.Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ { size_t const countSize = ZSTD_buildCTable( op, (size_t)(oend - op), - CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)stats.Offtype, + CTable_OffsetBits, OffFSELog, (SymbolEncodingType_e)stats.Offtype, countWorkspace, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, prevEntropy->offcodeCTable, @@ -2867,7 +2867,7 @@ ZSTD_buildSequencesStatistics( assert(!(stats.MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ { size_t const countSize = ZSTD_buildCTable( op, (size_t)(oend - op), - CTable_MatchLength, MLFSELog, (symbolEncodingType_e)stats.MLtype, + CTable_MatchLength, MLFSELog, (SymbolEncodingType_e)stats.MLtype, countWorkspace, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML, prevEntropy->matchlengthCTable, @@ -3738,9 +3738,9 @@ ZSTD_buildBlockEntropyStats_sequences( entropyWorkspace, entropyWorkspaceSize) : ZSTD_buildDummySequencesStatistics(nextEntropy); FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!"); - fseMetadata->llType = (symbolEncodingType_e) stats.LLtype; - fseMetadata->ofType = (symbolEncodingType_e) stats.Offtype; - fseMetadata->mlType = (symbolEncodingType_e) stats.MLtype; + fseMetadata->llType = (SymbolEncodingType_e) stats.LLtype; + fseMetadata->ofType = (SymbolEncodingType_e) stats.Offtype; + fseMetadata->mlType = (SymbolEncodingType_e) stats.MLtype; fseMetadata->lastCountSize = stats.lastCountSize; return stats.size; } @@ -3811,7 +3811,7 @@ ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize, /* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */ static size_t -ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type, +ZSTD_estimateBlockSize_symbolType(SymbolEncodingType_e type, const BYTE* codeTable, size_t nbSeq, unsigned maxCode, const FSE_CTable* fseCTable, const U8* additionalBits, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 92812192f..3dcd52c95 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -156,7 +156,7 @@ int ZSTD_seqToCodes(const SeqStore_t* seqStorePtr); /* compress, dictBuilder, * hufDesSize refers to the size of huffman tree description in bytes. * This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */ typedef struct { - symbolEncodingType_e hType; + SymbolEncodingType_e hType; BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE]; size_t hufDesSize; } ZSTD_hufCTablesMetadata_t; @@ -167,9 +167,9 @@ typedef struct { * fseTablesSize refers to the size of fse tables in bytes. * This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */ typedef struct { - symbolEncodingType_e llType; - symbolEncodingType_e ofType; - symbolEncodingType_e mlType; + SymbolEncodingType_e llType; + SymbolEncodingType_e ofType; + SymbolEncodingType_e mlType; BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE]; size_t fseTablesSize; size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */ diff --git a/lib/compress/zstd_compress_literals.c b/lib/compress/zstd_compress_literals.c index bfd4f11ab..06036de5d 100644 --- a/lib/compress/zstd_compress_literals.c +++ b/lib/compress/zstd_compress_literals.c @@ -140,7 +140,7 @@ size_t ZSTD_compressLiterals ( size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); BYTE* const ostart = (BYTE*)dst; U32 singleStream = srcSize < 256; - symbolEncodingType_e hType = set_compressed; + SymbolEncodingType_e hType = set_compressed; size_t cLitSize; DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i, srcSize=%u, dstCapacity=%zu)", diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index 7a9d595b1..d4d28d819 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -153,7 +153,7 @@ size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog, return cost >> 8; } -symbolEncodingType_e +SymbolEncodingType_e ZSTD_selectEncodingType( FSE_repeat* repeatMode, unsigned const* count, unsigned const max, size_t const mostFrequent, size_t nbSeq, unsigned const FSELog, @@ -241,7 +241,7 @@ typedef struct { size_t ZSTD_buildCTable(void* dst, size_t dstCapacity, - FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type, + FSE_CTable* nextCTable, U32 FSELog, SymbolEncodingType_e type, unsigned* count, U32 max, const BYTE* codeTable, size_t nbSeq, const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax, diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index b974d1cfc..03247ea75 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -13,14 +13,14 @@ #include "zstd_compress_internal.h" /* SeqDef */ #include "../common/fse.h" /* FSE_repeat, FSE_CTable */ -#include "../common/zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ +#include "../common/zstd_internal.h" /* SymbolEncodingType_e, ZSTD_strategy */ typedef enum { ZSTD_defaultDisallowed = 0, ZSTD_defaultAllowed = 1 } ZSTD_defaultPolicy_e; -symbolEncodingType_e +SymbolEncodingType_e ZSTD_selectEncodingType( FSE_repeat* repeatMode, unsigned const* count, unsigned const max, size_t const mostFrequent, size_t nbSeq, unsigned const FSELog, @@ -31,7 +31,7 @@ ZSTD_selectEncodingType( size_t ZSTD_buildCTable(void* dst, size_t dstCapacity, - FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type, + FSE_CTable* nextCTable, U32 FSELog, SymbolEncodingType_e type, unsigned* count, U32 max, const BYTE* codeTable, size_t nbSeq, const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax, diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index f2806c9ab..672af2d32 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -51,7 +51,7 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, BYTE* const oend = ostart + dstSize; BYTE* op = ostart + lhSize; U32 const singleStream = lhSize == 3; - symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat; + SymbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat; size_t cLitSize = 0; DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy); @@ -327,7 +327,7 @@ static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t lit return 0; } -static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, +static size_t ZSTD_estimateSubBlockSize_symbolType(SymbolEncodingType_e type, const BYTE* codeTable, unsigned maxCode, size_t nbSeq, const FSE_CTable* fseCTable, const U8* additionalBits, diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index f865692f5..ca5044376 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -139,7 +139,7 @@ static size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, ""); { const BYTE* const istart = (const BYTE*) src; - symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); + SymbolEncodingType_e const litEncType = (SymbolEncodingType_e)(istart[0] & 3); size_t const blockSizeMax = ZSTD_blockSizeMax(dctx); switch(litEncType) @@ -645,7 +645,7 @@ void ZSTD_buildFSETable(ZSTD_seqSymbol* dt, * @return : nb bytes read from src, * or an error code if it fails */ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr, - symbolEncodingType_e type, unsigned max, U32 maxLog, + SymbolEncodingType_e type, unsigned max, U32 maxLog, const void* src, size_t srcSize, const U32* baseValue, const U8* nbAdditionalBits, const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable, @@ -728,9 +728,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, /* FSE table descriptors */ RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */ RETURN_ERROR_IF(*ip & 3, corruption_detected, ""); /* The last field, Reserved, must be all-zeroes. */ - { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); - symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); - symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); + { SymbolEncodingType_e const LLtype = (SymbolEncodingType_e)(*ip >> 6); + SymbolEncodingType_e const OFtype = (SymbolEncodingType_e)((*ip >> 4) & 3); + SymbolEncodingType_e const MLtype = (SymbolEncodingType_e)((*ip >> 2) & 3); ip++; /* Build DTables */ diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index bbe32ee72..c53d83251 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -505,7 +505,7 @@ static size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t con size_t compressedSize = 0; size_t maxLitSize = MIN(contentSize-3, g_maxBlockSize); - symbolEncodingType_e hType; + SymbolEncodingType_e hType; if (contentSize < 64) { /* make sure we get reasonably-sized literals for compression */ diff --git a/tests/fullbench.c b/tests/fullbench.c index c8f0c0af1..250359e92 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -170,7 +170,7 @@ FORCE_NOINLINE size_t ZSTD_decodeLiteralsHeader(ZSTD_DCtx* dctx, void const* src RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, ""); { BYTE const* istart = (BYTE const*)src; - symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); + SymbolEncodingType_e const litEncType = (SymbolEncodingType_e)(istart[0] & 3); if (litEncType == set_compressed) { RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3"); { From 0442e43acadd65b35b41f1fadae301a629d7e37e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 11:40:06 -0800 Subject: [PATCH 206/405] codemod: ZSTD_defaultPolicy_e -> ZSTD_DefaultPolicy_e --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_compress_sequences.c | 2 +- lib/compress/zstd_compress_sequences.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 1715dad3f..24afefa85 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2826,7 +2826,7 @@ ZSTD_buildSequencesStatistics( size_t const mostFrequent = HIST_countFast_wksp( countWorkspace, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ - ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; + ZSTD_DefaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; DEBUGLOG(5, "Building OF table"); nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode; stats.Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index d4d28d819..7beb9daa6 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -159,7 +159,7 @@ ZSTD_selectEncodingType( size_t const mostFrequent, size_t nbSeq, unsigned const FSELog, FSE_CTable const* prevCTable, short const* defaultNorm, U32 defaultNormLog, - ZSTD_defaultPolicy_e const isDefaultAllowed, + ZSTD_DefaultPolicy_e const isDefaultAllowed, ZSTD_strategy const strategy) { ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0); diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index 03247ea75..4be8e91f2 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -18,7 +18,7 @@ typedef enum { ZSTD_defaultDisallowed = 0, ZSTD_defaultAllowed = 1 -} ZSTD_defaultPolicy_e; +} ZSTD_DefaultPolicy_e; SymbolEncodingType_e ZSTD_selectEncodingType( @@ -26,7 +26,7 @@ ZSTD_selectEncodingType( size_t const mostFrequent, size_t nbSeq, unsigned const FSELog, FSE_CTable const* prevCTable, short const* defaultNorm, U32 defaultNormLog, - ZSTD_defaultPolicy_e const isDefaultAllowed, + ZSTD_DefaultPolicy_e const isDefaultAllowed, ZSTD_strategy const strategy); size_t From e9f8a119b4fcd44038dbb0d072aa44968d81bd9b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 12:02:44 -0800 Subject: [PATCH 207/405] ZSTD_entropyCompressSeqStore_internal() can accept an externally defined literals buffer --- lib/compress/zstd_compress.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 24afefa85..873c1671f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2894,11 +2894,12 @@ ZSTD_buildSequencesStatistics( #define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20 MEM_STATIC size_t ZSTD_entropyCompressSeqStore_internal( + void* dst, size_t dstCapacity, + const void* literals, size_t litSize, const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, void* entropyWorkspace, size_t entropyWkspSize, const int bmi2) { @@ -2926,12 +2927,9 @@ ZSTD_entropyCompressSeqStore_internal( assert(entropyWkspSize >= HUF_WORKSPACE_SIZE); /* Compress literals */ - { const BYTE* const literals = seqStorePtr->litStart; - size_t const numSequences = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - size_t const numLiterals = (size_t)(seqStorePtr->lit - seqStorePtr->litStart); + { size_t const numSequences = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); /* Base suspicion of uncompressibility on ratio of literals to sequences */ - unsigned const suspectUncompressible = (numSequences == 0) || (numLiterals / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO); - size_t const litSize = (size_t)(seqStorePtr->lit - literals); + int const suspectUncompressible = (numSequences == 0) || (litSize / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO); size_t const cSize = ZSTD_compressLiterals( op, dstCapacity, @@ -3012,7 +3010,7 @@ ZSTD_entropyCompressSeqStore_internal( return (size_t)(op - ostart); } -MEM_STATIC size_t +static size_t ZSTD_entropyCompressSeqStore( const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, @@ -3024,8 +3022,9 @@ ZSTD_entropyCompressSeqStore( int bmi2) { size_t const cSize = ZSTD_entropyCompressSeqStore_internal( - seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity, + seqStorePtr->litStart, (size_t)(seqStorePtr->lit - seqStorePtr->litStart), + seqStorePtr, prevEntropy, nextEntropy, cctxParams, entropyWorkspace, entropyWkspSize, bmi2); if (cSize == 0) return 0; /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block. From 0165eeb441de43ffe11b95b9073c0a694b66e6a4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 13:33:48 -0800 Subject: [PATCH 208/405] created ZSTD_entropyCompressSeqStore_wExtLitBuffer() can receive externally defined buffer of literals --- lib/compress/zstd_compress.c | 71 ++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 873c1671f..4f9f17447 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1039,7 +1039,7 @@ size_t ZSTD_CCtxParams_getParameter( switch(param) { case ZSTD_c_format : - *value = CCtxParams->format; + *value = (int)CCtxParams->format; break; case ZSTD_c_compressionLevel : *value = CCtxParams->compressionLevel; @@ -1054,16 +1054,16 @@ size_t ZSTD_CCtxParams_getParameter( *value = (int)CCtxParams->cParams.chainLog; break; case ZSTD_c_searchLog : - *value = CCtxParams->cParams.searchLog; + *value = (int)CCtxParams->cParams.searchLog; break; case ZSTD_c_minMatch : - *value = CCtxParams->cParams.minMatch; + *value = (int)CCtxParams->cParams.minMatch; break; case ZSTD_c_targetLength : - *value = CCtxParams->cParams.targetLength; + *value = (int)CCtxParams->cParams.targetLength; break; case ZSTD_c_strategy : - *value = (unsigned)CCtxParams->cParams.strategy; + *value = (int)CCtxParams->cParams.strategy; break; case ZSTD_c_contentSizeFlag : *value = CCtxParams->fParams.contentSizeFlag; @@ -1078,10 +1078,10 @@ size_t ZSTD_CCtxParams_getParameter( *value = CCtxParams->forceWindow; break; case ZSTD_c_forceAttachDict : - *value = CCtxParams->attachDictPref; + *value = (int)CCtxParams->attachDictPref; break; case ZSTD_c_literalCompressionMode : - *value = CCtxParams->literalCompressionMode; + *value = (int)CCtxParams->literalCompressionMode; break; case ZSTD_c_nbWorkers : #ifndef ZSTD_MULTITHREAD @@ -1115,19 +1115,19 @@ size_t ZSTD_CCtxParams_getParameter( *value = CCtxParams->enableDedicatedDictSearch; break; case ZSTD_c_enableLongDistanceMatching : - *value = CCtxParams->ldmParams.enableLdm; + *value = (int)CCtxParams->ldmParams.enableLdm; break; case ZSTD_c_ldmHashLog : - *value = CCtxParams->ldmParams.hashLog; + *value = (int)CCtxParams->ldmParams.hashLog; break; case ZSTD_c_ldmMinMatch : - *value = CCtxParams->ldmParams.minMatchLength; + *value = (int)CCtxParams->ldmParams.minMatchLength; break; case ZSTD_c_ldmBucketSizeLog : - *value = CCtxParams->ldmParams.bucketSizeLog; + *value = (int)CCtxParams->ldmParams.bucketSizeLog; break; case ZSTD_c_ldmHashRateLog : - *value = CCtxParams->ldmParams.hashRateLog; + *value = (int)CCtxParams->ldmParams.hashRateLog; break; case ZSTD_c_targetCBlockSize : *value = (int)CCtxParams->targetCBlockSize; @@ -1401,7 +1401,7 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength); - BOUNDCHECK(ZSTD_c_strategy, cParams.strategy); + BOUNDCHECK(ZSTD_c_strategy, (int)cParams.strategy); return 0; } @@ -2558,7 +2558,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, ? ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog) : 0; size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog; - int const h3log = srcCCtx->blockState.matchState.hashLog3; + U32 const h3log = srcCCtx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable, @@ -3011,19 +3011,20 @@ ZSTD_entropyCompressSeqStore_internal( } static size_t -ZSTD_entropyCompressSeqStore( +ZSTD_entropyCompressSeqStore_wExtLitBuffer( + void* dst, size_t dstCapacity, + const void* literals, size_t litSize, + size_t srcSize, const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, - size_t srcSize, void* entropyWorkspace, size_t entropyWkspSize, int bmi2) { size_t const cSize = ZSTD_entropyCompressSeqStore_internal( dst, dstCapacity, - seqStorePtr->litStart, (size_t)(seqStorePtr->lit - seqStorePtr->litStart), + literals, litSize, seqStorePtr, prevEntropy, nextEntropy, cctxParams, entropyWorkspace, entropyWkspSize, bmi2); if (cSize == 0) return 0; @@ -3048,6 +3049,28 @@ ZSTD_entropyCompressSeqStore( return cSize; } +static size_t +ZSTD_entropyCompressSeqStore( + const SeqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + void* dst, size_t dstCapacity, + size_t srcSize, + void* entropyWorkspace, size_t entropyWkspSize, + int bmi2) +{ + return ZSTD_entropyCompressSeqStore_wExtLitBuffer( + dst, dstCapacity, + seqStorePtr->litStart, (size_t)(seqStorePtr->lit - seqStorePtr->litStart), + srcSize, + seqStorePtr, + prevEntropy, nextEntropy, + cctxParams, + entropyWorkspace, entropyWkspSize, + bmi2); +} + /* ZSTD_selectBlockCompressor() : * Not static, but internal use only (used by long distance matcher) * assumption : strat is a valid strategy */ @@ -3101,7 +3124,7 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramS ZSTD_blockCompressor selectedCompressor; ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); - assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat)); + assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat)); DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder); if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) { static const ZSTD_blockCompressor rowBasedBlockCompressors[4][3] = { @@ -3385,7 +3408,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const SeqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM]) { const SeqDef* inSeqs = seqStore->sequencesStart; - const size_t nbInSequences = seqStore->sequences - inSeqs; + const size_t nbInSequences = (size_t)(seqStore->sequences - inSeqs); const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart); ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex; @@ -6931,10 +6954,10 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, if (!cctx->isFirstBlock && ZSTD_maybeRLE(&cctx->seqStore) && ZSTD_isRLE(ip, blockSize)) { - /* We don't want to emit our first block as a RLE even if it qualifies because - * doing so will cause the decoder (cli only) to throw a "should consume all input error." - * This is only an issue for zstd <= v1.4.3 - */ + /* We don't want to emit our first block as RLE even if it qualifies because + * doing so will cause the decoder (cli <= v1.4.3 only) to throw an (invalid) error + * "should consume all input error." + */ compressedSeqsSize = 1; } From c97522f7fb797cde035ab26f0ba97addb718c174 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 13:58:11 -0800 Subject: [PATCH 209/405] codemod: ZSTD_sequenceFormat_e -> ZSTD_SequenceFormat_e since it's a type name. Note: in contrast with previous names, this one is on the Public API side. So there is a #define, so that existing programs using ZSTD_sequenceFormat_e still work. --- doc/zstd_manual.html | 2 +- lib/compress/zstd_compress.c | 16 +++++++++------- lib/compress/zstd_compress_internal.h | 2 +- lib/zstd.h | 3 ++- tests/fuzz/sequence_compression_api.c | 10 +++++----- tests/fuzzer.c | 2 +- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index bcd1f05da..e6f8fc504 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1317,7 +1317,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr,

    typedef enum {
       ZSTD_sf_noBlockDelimiters = 0,         /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
       ZSTD_sf_explicitBlockDelimiters = 1    /* Representation of ZSTD_Sequence contains explicit block delimiters */
    -} ZSTD_sequenceFormat_e;
    +} ZSTD_SequenceFormat_e;
     

    ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize);
     

    `srcSize` : size of the input buffer diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 4f9f17447..5976a8e5c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -974,7 +974,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_blockDelimiters: BOUNDCHECK(ZSTD_c_blockDelimiters, value); - CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value; + CCtxParams->blockDelimiters = (ZSTD_SequenceFormat_e)value; return CCtxParams->blockDelimiters; case ZSTD_c_validateSequences: @@ -6815,10 +6815,10 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); -static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) +static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode) { ZSTD_sequenceCopier sequenceCopier = NULL; - assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode)); + assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode)); if (mode == ZSTD_sf_explicitBlockDelimiters) { return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; } else if (mode == ZSTD_sf_noBlockDelimiters) { @@ -6862,7 +6862,7 @@ static size_t blockSize_noDelimiter(size_t blockSize, size_t remaining) return lastBlock ? remaining : blockSize; } -static size_t determine_blockSize(ZSTD_sequenceFormat_e mode, +static size_t determine_blockSize(ZSTD_SequenceFormat_e mode, size_t blockSize, size_t remaining, const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_sequencePosition seqPos) { @@ -6941,11 +6941,13 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, } RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); - compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore, + compressedSeqsSize = ZSTD_entropyCompressSeqStore_wExtLitBuffer( + op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, + cctx->seqStore.litStart, (size_t)(cctx->seqStore.lit - cctx->seqStore.litStart), + blockSize, + &cctx->seqStore, &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, &cctx->appliedParams, - op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, - blockSize, cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */, cctx->bmi2); FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 3dcd52c95..2d7e0230d 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -404,7 +404,7 @@ struct ZSTD_CCtx_params_s { ZSTD_bufferMode_e outBufferMode; /* Sequence compression API */ - ZSTD_sequenceFormat_e blockDelimiters; + ZSTD_SequenceFormat_e blockDelimiters; int validateSequences; /* Block splitting diff --git a/lib/zstd.h b/lib/zstd.h index cfacd58d0..94058a1b2 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1562,7 +1562,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSi typedef enum { ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */ ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */ -} ZSTD_sequenceFormat_e; +} ZSTD_SequenceFormat_e; +#define ZSTD_sequenceFormat_e ZSTD_SequenceFormat_e /* old name */ /*! ZSTD_sequenceBound() : * `srcSize` : size of the input buffer diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index 3c60f42c6..5e5e1e604 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -76,7 +76,7 @@ static char* generatePseudoRandomString(char* str, size_t size, FUZZ_dataProduce static size_t decodeSequences(void* dst, size_t nbSequences, size_t literalsSize, const void* dict, size_t dictSize, - ZSTD_sequenceFormat_e mode) + ZSTD_SequenceFormat_e mode) { const uint8_t* litPtr = literalsBuffer; const uint8_t* const litBegin = literalsBuffer; @@ -141,7 +141,7 @@ static size_t decodeSequences(void* dst, size_t nbSequences, */ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, size_t literalsSizeLimit, size_t dictSize, - size_t windowLog, ZSTD_sequenceFormat_e mode) + size_t windowLog, ZSTD_SequenceFormat_e mode) { const uint32_t repCode = 0; /* not used by sequence ingestion api */ size_t windowSize = 1ULL << windowLog; @@ -232,7 +232,7 @@ static size_t roundTripTest(void* result, size_t resultCapacity, const void* src, size_t srcSize, const ZSTD_Sequence* seqs, size_t seqSize, unsigned hasDict, - ZSTD_sequenceFormat_e mode) + ZSTD_SequenceFormat_e mode) { size_t cSize; size_t dSize; @@ -276,7 +276,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) unsigned hasDict; unsigned wLog; int cLevel; - ZSTD_sequenceFormat_e mode; + ZSTD_SequenceFormat_e mode; FUZZ_dataProducer_t* const producer = FUZZ_dataProducer_create(src, size); FUZZ_ASSERT(producer); @@ -293,7 +293,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) /* Generate window log first so we don't generate offsets too large */ wLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); cLevel = FUZZ_dataProducer_int32Range(producer, -3, 22); - mode = (ZSTD_sequenceFormat_e)FUZZ_dataProducer_int32Range(producer, 0, 1); + mode = (ZSTD_SequenceFormat_e)FUZZ_dataProducer_int32Range(producer, 0, 1); ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4a6ebd69c..2180d1edb 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -310,7 +310,7 @@ static int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part) #endif static void FUZ_decodeSequences(BYTE* dst, ZSTD_Sequence* seqs, size_t seqsSize, - BYTE* src, size_t size, ZSTD_sequenceFormat_e format) + BYTE* src, size_t size, ZSTD_SequenceFormat_e format) { size_t i; size_t j; From 894ea312819e36084e0ce26922037ba8571cd65d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 14:00:09 -0800 Subject: [PATCH 210/405] codemod: ZSTD_sequenceCopier -> ZSTD_SequenceCopier_f --- lib/compress/zstd_compress.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 5976a8e5c..a8d317a8d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6812,12 +6812,12 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, return bytesAdjustment; } -typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, +typedef size_t (*ZSTD_SequenceCopier_f) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); -static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode) +static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode) { - ZSTD_sequenceCopier sequenceCopier = NULL; + ZSTD_SequenceCopier_f sequenceCopier = NULL; assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode)); if (mode == ZSTD_sf_explicitBlockDelimiters) { return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; @@ -6896,7 +6896,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, BYTE const* ip = (BYTE const*)src; BYTE* op = (BYTE*)dst; - ZSTD_sequenceCopier const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters); + ZSTD_SequenceCopier_f const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters); DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize); /* Special case: empty frame */ From 1ac79ba1b63f9e060d767380bca369051f6969be Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 14:02:53 -0800 Subject: [PATCH 211/405] minor: simplify ZSTD_selectSequenceCopier --- lib/compress/zstd_compress.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a8d317a8d..26af1581c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6817,15 +6817,12 @@ typedef size_t (*ZSTD_SequenceCopier_f) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode) { - ZSTD_SequenceCopier_f sequenceCopier = NULL; assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode)); if (mode == ZSTD_sf_explicitBlockDelimiters) { return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; - } else if (mode == ZSTD_sf_noBlockDelimiters) { - return ZSTD_copySequencesToSeqStoreNoBlockDelim; } - assert(sequenceCopier != NULL); - return sequenceCopier; + assert(mode == ZSTD_sf_noBlockDelimiters); + return ZSTD_copySequencesToSeqStoreNoBlockDelim; } /* Discover the size of next block by searching for the delimiter. From 76dd3a98c48445f5f586d2deca5a3aedfefbd49d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 14:11:51 -0800 Subject: [PATCH 212/405] scope: ZSTD_copySequencesToSeqStore*() are private to ZSTD_compress.c no need to publish them outside of this unit. --- lib/compress/zstd_compress.c | 41 +++++++++++++++++++++------ lib/compress/zstd_compress_internal.h | 27 ------------------ 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 26af1581c..3d926a991 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1203,13 +1203,13 @@ size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams) DEBUGLOG(4, "ZSTD_CCtx_setCParams"); /* only update if all parameters are valid */ FORWARD_IF_ERROR(ZSTD_checkCParams(cparams), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, cparams.windowLog), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, cparams.chainLog), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, cparams.hashLog), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, cparams.searchLog), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, cparams.minMatch), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, cparams.targetLength), ""); - FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, cparams.strategy), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)cparams.windowLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, (int)cparams.chainLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, (int)cparams.hashLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, (int)cparams.searchLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, (int)cparams.minMatch), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, (int)cparams.targetLength), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, (int)cparams.strategy), ""); return 0; } @@ -3239,6 +3239,13 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq return litLenSum + matchLenSum; } +static size_t +ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, + ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, + ZSTD_paramSwitch_e externalRepSearch); + typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e; static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) @@ -6601,7 +6608,11 @@ static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 return offBase; } -size_t +/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of + * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter. + * Note that the block delimiter must include the last literals of the block. + */ +static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, @@ -6687,7 +6698,19 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, return 0; } -size_t +/* Returns the number of bytes to move the current read position back by. + * Only non-zero if we ended up splitting a sequence. + * Otherwise, it may return a ZSTD error if something went wrong. + * + * This function will attempt to scan through blockSize bytes + * represented by the sequences in @inSeqs, + * storing any (partial) sequences. + * + * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to + * avoid splitting a match, or to avoid splitting a match such that it would produce a match + * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block. + */ +static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 2d7e0230d..737d1cc45 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1613,33 +1613,6 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat); */ void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize); -/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of - * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter. - * Note that the block delimiter must include the last literals of the block. - */ -size_t -ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, - ZSTD_sequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, - const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); - -/* Returns the number of bytes to move the current read position back by. - * Only non-zero if we ended up splitting a sequence. - * Otherwise, it may return a ZSTD error if something went wrong. - * - * This function will attempt to scan through blockSize bytes - * represented by the sequences in @inSeqs, - * storing any (partial) sequences. - * - * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to - * avoid splitting a match, or to avoid splitting a match such that it would produce a match - * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block. - */ -size_t -ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, - const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); - /* Returns 1 if an external sequence producer is registered, otherwise returns 0. */ MEM_STATIC int ZSTD_hasExtSeqProd(const ZSTD_CCtx_params* params) { return params->extSeqProdFunc != NULL; From 03d95f9d135a9009b15567acf6f85b6e23534224 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 14:14:07 -0800 Subject: [PATCH 213/405] fix proper type for .forceNonContiguous --- lib/compress/zstd_compress_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 737d1cc45..21e69650f 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -301,7 +301,7 @@ struct ZSTD_matchState_t { U32* hashTable3; U32* chainTable; - U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */ + int forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */ int dedicatedDictSearch; /* Indicates whether this matchState is using the * dedicated dictionary search structure. From 5359d16d8d646b2010b9d5ac07fbf747d432fdfe Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 14:18:39 -0800 Subject: [PATCH 214/405] enable proper type --- lib/compress/zstd_compress.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3d926a991..639b78cbb 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1661,7 +1661,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( static size_t ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, const ZSTD_paramSwitch_e useRowMatchFinder, - const U32 enableDedicatedDictSearch, + const int enableDedicatedDictSearch, const U32 forCCtx) { /* chain table size should be 0 for fast or row-hash strategies */ @@ -5052,7 +5052,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, { unsigned maxSymbolValue = 255; unsigned hasZeroWeights = 1; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, - dictEnd-dictPtr, &hasZeroWeights); + (size_t)(dictEnd-dictPtr), &hasZeroWeights); /* We only set the loaded table as valid if it contains all non-zero * weights. Otherwise, we set it to check */ @@ -5064,7 +5064,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, } { unsigned offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); /* fill all offset symbols to avoid garbage at end of table */ @@ -5093,7 +5093,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, { short litlengthNCount[MaxLL+1]; unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); + size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( @@ -5358,7 +5358,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) } cctx->stage = ZSTDcs_created; /* return to "created but no init" status */ - return op-ostart; + return (size_t)(op-ostart); } void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize) @@ -5586,7 +5586,7 @@ static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_compressionParameters cParams, ZSTD_paramSwitch_e useRowMatchFinder, - U32 enableDedicatedDictSearch, + int enableDedicatedDictSearch, ZSTD_customMem customMem) { if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; From 30671d77afeedbc70957ac8ce8e864d5219d97bb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 15:01:43 -0800 Subject: [PATCH 215/405] codemod: ZSTD_sequencePosition -> ZSTD_SequencePosition --- lib/compress/zstd_compress.c | 54 ++++++++++++++++----------- lib/compress/zstd_compress_internal.h | 6 --- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 639b78cbb..9f649dd6e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3239,9 +3239,15 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq return litLenSum + matchLenSum; } +typedef struct { + U32 idx; /* Index in array of ZSTD_Sequence */ + U32 posInSequence; /* Position within sequence at idx */ + size_t posInSrc; /* Number of bytes given by sequences provided so far */ +} ZSTD_SequencePosition; + static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, - ZSTD_sequencePosition* seqPos, + ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); @@ -3362,7 +3368,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) /* Return early if there is no error, since we don't need to worry about last literals */ if (!ZSTD_isError(nbPostProcessedSeqs)) { - ZSTD_sequencePosition seqPos = {0,0,0}; + ZSTD_SequencePosition seqPos = {0,0,0}; size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs); RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, "External sequences imply too large a block!"); FORWARD_IF_ERROR( @@ -5079,7 +5085,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, { short matchlengthNCount[MaxML+1]; unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); + size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( @@ -6123,12 +6129,13 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, case zcss_load: if ( (flushMode == ZSTD_e_end) - && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip) /* Enough output space */ + && ( (size_t)(oend-op) >= ZSTD_compressBound((size_t)(iend-ip)) /* Enough output space */ || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) /* OR we are allowed to return dstSizeTooSmall */ && (zcs->inBuffPos == 0) ) { /* shortcut to compression pass directly into output buffer */ size_t const cSize = ZSTD_compressEnd_public(zcs, - op, oend-op, ip, iend-ip); + op, (size_t)(oend-op), + ip, (size_t)(iend-ip)); DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize); FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed"); ip = iend; @@ -6142,7 +6149,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; size_t const loaded = ZSTD_limitCopy( zcs->inBuff + zcs->inBuffPos, toLoad, - ip, iend-ip); + ip, (size_t)(iend-ip)); zcs->inBuffPos += loaded; if (ip) ip += loaded; if ( (flushMode == ZSTD_e_continue) @@ -6175,7 +6182,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, { int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered); void* cDst; size_t cSize; - size_t oSize = oend-op; + size_t oSize = (size_t)(oend-op); size_t const iSize = inputBuffered ? zcs->inBuffPos - zcs->inToCompress : MIN((size_t)(iend - ip), zcs->blockSize); if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) @@ -6258,8 +6265,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, } } - input->pos = ip - istart; - output->pos = op - ostart; + input->pos = (size_t)(ip - istart); + output->pos = (size_t)(op - ostart); if (zcs->frameEnded) return 0; return ZSTD_nextInputSizeHint(zcs); } @@ -6608,16 +6615,17 @@ static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 return offBase; } -/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of - * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter. +/* This function scans through an array of ZSTD_Sequence, + * storing the sequences it reads, until it reaches a block delimiter. * Note that the block delimiter must include the last literals of the block. + * @returns 0 on success, and a ZSTD_error otherwise. */ static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, - ZSTD_sequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, - const void* src, size_t blockSize, - ZSTD_paramSwitch_e externalRepSearch) + ZSTD_SequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, + ZSTD_paramSwitch_e externalRepSearch) { U32 idx = seqPos->idx; U32 const startIdx = idx; @@ -6652,8 +6660,10 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); if (cctx->appliedParams.validateSequences) { seqPos->posInSrc += litLength + matchLength; - FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc, - cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), + FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, + seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, + ZSTD_hasExtSeqProd(&cctx->appliedParams)), "Sequence validation failed"); } RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, @@ -6712,7 +6722,7 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, */ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, - ZSTD_sequencePosition* seqPos, + ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch) @@ -6835,7 +6845,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, return bytesAdjustment; } -typedef size_t (*ZSTD_SequenceCopier_f) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, +typedef size_t (*ZSTD_SequenceCopier_f) (ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode) @@ -6853,7 +6863,7 @@ static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mod * otherwise it's an input error. * The block size retrieved will be later compared to ensure it remains within bounds */ static size_t -blockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_sequencePosition seqPos) +blockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_SequencePosition seqPos) { int end = 0; size_t blockSize = 0; @@ -6884,7 +6894,7 @@ static size_t blockSize_noDelimiter(size_t blockSize, size_t remaining) static size_t determine_blockSize(ZSTD_SequenceFormat_e mode, size_t blockSize, size_t remaining, - const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_sequencePosition seqPos) + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_SequencePosition seqPos) { DEBUGLOG(6, "determine_blockSize : remainingSize = %zu", remaining); if (mode == ZSTD_sf_noBlockDelimiters) @@ -6912,7 +6922,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, { size_t cSize = 0; size_t remaining = srcSize; - ZSTD_sequencePosition seqPos = {0, 0, 0}; + ZSTD_SequencePosition seqPos = {0, 0, 0}; BYTE const* ip = (BYTE const*)src; BYTE* op = (BYTE*)dst; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 21e69650f..d3aa1e234 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -215,12 +215,6 @@ typedef struct { size_t capacity; /* The capacity starting from `seq` pointer */ } rawSeqStore_t; -typedef struct { - U32 idx; /* Index in array of ZSTD_Sequence */ - U32 posInSequence; /* Position within sequence at idx */ - size_t posInSrc; /* Number of bytes given by sequences provided so far */ -} ZSTD_sequencePosition; - UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0}; typedef struct { From fa468944f2a999a10f6a823fe7252da3e0fdc129 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 15:04:56 -0800 Subject: [PATCH 216/405] codemod: ZSTD_buildSeqStore_e -> ZSTD_BuildSeqStore_e --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9f649dd6e..e068b48bd 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3252,7 +3252,7 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); -typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e; +typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_BuildSeqStore_e; static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) { From 5df80acedb6b352e949ef24446cb489b15524ce0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 15:35:11 -0800 Subject: [PATCH 217/405] codemod: ZSTD_matchState_t -> ZSTD_MatchState_t --- lib/compress/zstd_compress.c | 52 ++++++------- lib/compress/zstd_compress_internal.h | 20 ++--- lib/compress/zstd_double_fast.c | 22 +++--- lib/compress/zstd_double_fast.h | 8 +- lib/compress/zstd_fast.c | 22 +++--- lib/compress/zstd_fast.h | 8 +- lib/compress/zstd_lazy.c | 106 +++++++++++++------------- lib/compress/zstd_lazy.h | 60 +++++++-------- lib/compress/zstd_ldm.c | 6 +- lib/compress/zstd_ldm.h | 2 +- lib/compress/zstd_opt.c | 42 +++++----- lib/compress/zstd_opt.h | 16 ++-- 12 files changed, 182 insertions(+), 182 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e068b48bd..029928fb2 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -48,7 +48,7 @@ * in log format, aka 17 => 1 << 17 == 128Ki positions. * This structure is only used in zstd_opt. * Since allocation is centralized for all strategies, it has to be known here. - * The actual (selected) size of the hash table is then stored in ZSTD_matchState_t.hashLog3, + * The actual (selected) size of the hash table is then stored in ZSTD_MatchState_t.hashLog3, * so that zstd_opt.c doesn't need to know about this constant. */ #ifndef ZSTD_HASHLOG3_MAX @@ -82,7 +82,7 @@ struct ZSTD_CDict_s { ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */ U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ ZSTD_cwksp workspace; - ZSTD_matchState_t matchState; + ZSTD_MatchState_t matchState; ZSTD_compressedBlockState_t cBlockState; ZSTD_customMem customMem; U32 dictID; @@ -1938,7 +1938,7 @@ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) * Invalidate all the matches in the match finder tables. * Requires nextSrc and base to be set (can be NULL). */ -static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) +static void ZSTD_invalidateMatchState(ZSTD_MatchState_t* ms) { ZSTD_window_clear(&ms->window); @@ -1985,12 +1985,12 @@ static U64 ZSTD_bitmix(U64 val, U64 len) { } /* Mixes in the hashSalt and hashSaltEntropy to create a new hashSalt */ -static void ZSTD_advanceHashSalt(ZSTD_matchState_t* ms) { +static void ZSTD_advanceHashSalt(ZSTD_MatchState_t* ms) { ms->hashSalt = ZSTD_bitmix(ms->hashSalt, 8) ^ ZSTD_bitmix((U64) ms->hashSaltEntropy, 4); } static size_t -ZSTD_reset_matchState(ZSTD_matchState_t* ms, +ZSTD_reset_matchState(ZSTD_MatchState_t* ms, ZSTD_cwksp* ws, const ZSTD_compressionParameters* cParams, const ZSTD_paramSwitch_e useRowMatchFinder, @@ -2473,8 +2473,8 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, ZSTD_cwksp_mark_tables_clean(&cctx->workspace); /* copy dictionary offsets */ - { ZSTD_matchState_t const* srcMatchState = &cdict->matchState; - ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; + { ZSTD_MatchState_t const* srcMatchState = &cdict->matchState; + ZSTD_MatchState_t* dstMatchState = &cctx->blockState.matchState; dstMatchState->window = srcMatchState->window; dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; @@ -2576,8 +2576,8 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, /* copy dictionary offsets */ { - const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState; - ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState; + const ZSTD_MatchState_t* srcMatchState = &srcCCtx->blockState.matchState; + ZSTD_MatchState_t* dstMatchState = &dstCCtx->blockState.matchState; dstMatchState->window = srcMatchState->window; dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; @@ -2671,7 +2671,7 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const /*! ZSTD_reduceIndex() : * rescale all indexes to avoid future overflow (indexes are U32) */ -static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue) +static void ZSTD_reduceIndex (ZSTD_MatchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue) { { U32 const hSize = (U32)1 << params->cParams.hashLog; ZSTD_reduceTable(ms->hashTable, hSize, reducerValue); @@ -3246,17 +3246,17 @@ typedef struct { } ZSTD_SequencePosition; static size_t -ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, - const void* src, size_t blockSize, - ZSTD_paramSwitch_e externalRepSearch); +ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, + ZSTD_paramSwitch_e externalRepSearch); typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_BuildSeqStore_e; static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) { - ZSTD_matchState_t* const ms = &zc->blockState.matchState; + ZSTD_MatchState_t* const ms = &zc->blockState.matchState; DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize); assert(srcSize <= ZSTD_BLOCKSIZE_MAX); /* Assert that we have correctly flushed the ctx params into the ms's copy */ @@ -3372,7 +3372,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs); RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, "External sequences imply too large a block!"); FORWARD_IF_ERROR( - ZSTD_copySequencesToSeqStoreExplicitBlockDelim( + ZSTD_transferSequences_wBlockDelim( zc, &seqPos, zc->extSeqBuf, nbPostProcessedSeqs, src, srcSize, @@ -4515,7 +4515,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, return cSize; } -static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, +static void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms, ZSTD_cwksp* ws, ZSTD_CCtx_params const* params, void const* ip, @@ -4600,7 +4600,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, XXH64_update(&cctx->xxhState, src, srcSize); while (remaining) { - ZSTD_matchState_t* const ms = &cctx->blockState.matchState; + ZSTD_MatchState_t* const ms = &cctx->blockState.matchState; size_t const blockSize = ZSTD_optimalBlockSize(cctx, ip, remaining, blockSizeMax, @@ -4784,7 +4784,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, const void* src, size_t srcSize, U32 frame, U32 lastFrameChunk) { - ZSTD_matchState_t* const ms = &cctx->blockState.matchState; + ZSTD_MatchState_t* const ms = &cctx->blockState.matchState; size_t fhSize = 0; DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u", @@ -4888,7 +4888,7 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const /*! ZSTD_loadDictionaryContent() : * @return : 0, or an error code */ -static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, +static size_t ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, ldmState_t* ls, ZSTD_cwksp* ws, ZSTD_CCtx_params const* params, @@ -5146,7 +5146,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, * dictSize supposed >= 8 */ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, ZSTD_cwksp* ws, ZSTD_CCtx_params const* params, const void* dict, size_t dictSize, @@ -5179,7 +5179,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, * @return : dictID, or an error code */ static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, ldmState_t* ls, ZSTD_cwksp* ws, const ZSTD_CCtx_params* params, @@ -6621,7 +6621,7 @@ static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 * @returns 0 on success, and a ZSTD_error otherwise. */ static size_t -ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, +ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, const void* src, size_t blockSize, @@ -6634,7 +6634,7 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, repcodes_t updatedRepcodes; U32 dictSize; - DEBUGLOG(5, "ZSTD_copySequencesToSeqStoreExplicitBlockDelim (blockSize = %zu)", blockSize); + DEBUGLOG(5, "ZSTD_transferSequences_wBlockDelim (blockSize = %zu)", blockSize); if (cctx->cdict) { dictSize = (U32)cctx->cdict->dictContentSize; @@ -6852,7 +6852,7 @@ static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mod { assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode)); if (mode == ZSTD_sf_explicitBlockDelimiters) { - return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; + return ZSTD_transferSequences_wBlockDelim; } assert(mode == ZSTD_sf_noBlockDelimiters); return ZSTD_copySequencesToSeqStoreNoBlockDelim; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index d3aa1e234..91066a4be 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -269,11 +269,11 @@ typedef struct { #define ZSTD_WINDOW_START_INDEX 2 -typedef struct ZSTD_matchState_t ZSTD_matchState_t; +typedef struct ZSTD_MatchState_t ZSTD_MatchState_t; #define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */ -struct ZSTD_matchState_t { +struct ZSTD_MatchState_t { ZSTD_window_t window; /* State for window round buffer management */ U32 loadedDictEnd; /* index of end of dictionary, within context's referential. * When loadedDictEnd != 0, a dictionary is in use, and still valid. @@ -301,7 +301,7 @@ struct ZSTD_matchState_t { * dedicated dictionary search structure. */ optState_t opt; /* optimal parser state */ - const ZSTD_matchState_t* dictMatchState; + const ZSTD_MatchState_t* dictMatchState; ZSTD_compressionParameters cParams; const rawSeqStore_t* ldmSeqStore; @@ -321,7 +321,7 @@ struct ZSTD_matchState_t { typedef struct { ZSTD_compressedBlockState_t* prevCBlock; ZSTD_compressedBlockState_t* nextCBlock; - ZSTD_matchState_t matchState; + ZSTD_MatchState_t matchState; } ZSTD_blockState_t; typedef struct { @@ -580,7 +580,7 @@ typedef enum { } ZSTD_cParamMode_e; typedef size_t (*ZSTD_blockCompressor) ( - ZSTD_matchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); @@ -1081,7 +1081,7 @@ MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window) * Inspects the provided matchState and figures out what dictMode should be * passed to the compressor. */ -MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms) +MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) { return ZSTD_window_hasExtDict(ms->window) ? ZSTD_extDict : @@ -1270,7 +1270,7 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window, const void* blockEnd, U32 maxDist, U32* loadedDictEndPtr, - const ZSTD_matchState_t** dictMatchStatePtr) + const ZSTD_MatchState_t** dictMatchStatePtr) { U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base); U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0; @@ -1315,7 +1315,7 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window, const void* blockEnd, U32 maxDist, U32* loadedDictEndPtr, - const ZSTD_matchState_t** dictMatchStatePtr) + const ZSTD_MatchState_t** dictMatchStatePtr) { assert(loadedDictEndPtr != NULL); assert(dictMatchStatePtr != NULL); @@ -1405,7 +1405,7 @@ U32 ZSTD_window_update(ZSTD_window_t* window, /** * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix. */ -MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.lowLimit; @@ -1422,7 +1422,7 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, u /** * Returns the lowest allowed match index in the prefix. */ -MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.dictLimit; diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 1406c2d50..1a266e7d9 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -15,7 +15,7 @@ static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms, +void ZSTD_fillDoubleHashTableForCDict(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -53,7 +53,7 @@ void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms, static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_fillDoubleHashTableForCCtx(ZSTD_matchState_t* ms, +void ZSTD_fillDoubleHashTableForCCtx(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -87,7 +87,7 @@ void ZSTD_fillDoubleHashTableForCCtx(ZSTD_matchState_t* ms, } } } -void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, +void ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm, ZSTD_tableFillPurpose_e tfp) @@ -103,7 +103,7 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_doubleFast_noDict_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { ZSTD_compressionParameters const* cParams = &ms->cParams; @@ -326,7 +326,7 @@ _match_stored: FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { @@ -347,7 +347,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( const BYTE* const ilimit = iend - HASH_READ_SIZE; U32 offset_1=rep[0], offset_2=rep[1]; - const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_MatchState_t* const dms = ms->dictMatchState; const ZSTD_compressionParameters* const dictCParams = &dms->cParams; const U32* const dictHashLong = dms->hashTable; const U32* const dictHashSmall = dms->chainTable; @@ -548,7 +548,7 @@ _match_stored: #define ZSTD_GEN_DFAST_FN(dictMode, mls) \ static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls( \ - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ void const* src, size_t srcSize) \ { \ return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \ @@ -566,7 +566,7 @@ ZSTD_GEN_DFAST_FN(dictMatchState, 7) size_t ZSTD_compressBlock_doubleFast( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { const U32 mls = ms->cParams.minMatch; @@ -586,7 +586,7 @@ size_t ZSTD_compressBlock_doubleFast( size_t ZSTD_compressBlock_doubleFast_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { const U32 mls = ms->cParams.minMatch; @@ -608,7 +608,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState( static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_doubleFast_extDict_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls /* template */) { @@ -757,7 +757,7 @@ ZSTD_GEN_DFAST_FN(extDict, 6) ZSTD_GEN_DFAST_FN(extDict, 7) size_t ZSTD_compressBlock_doubleFast_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h index 1a746fab9..c58697ad2 100644 --- a/lib/compress/zstd_double_fast.h +++ b/lib/compress/zstd_double_fast.h @@ -20,18 +20,18 @@ extern "C" { #ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR -void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, +void ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm, ZSTD_tableFillPurpose_e tfp); size_t ZSTD_compressBlock_doubleFast( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_doubleFast_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_doubleFast_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_DOUBLEFAST ZSTD_compressBlock_doubleFast diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 3c8d5b527..ee25bcbac 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -13,7 +13,7 @@ static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms, +void ZSTD_fillHashTableForCDict(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { @@ -50,7 +50,7 @@ void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms, static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_fillHashTableForCCtx(ZSTD_matchState_t* ms, +void ZSTD_fillHashTableForCCtx(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm) { @@ -84,7 +84,7 @@ void ZSTD_fillHashTableForCCtx(ZSTD_matchState_t* ms, } } } } } -void ZSTD_fillHashTable(ZSTD_matchState_t* ms, +void ZSTD_fillHashTable(ZSTD_MatchState_t* ms, const void* const end, ZSTD_dictTableLoadMethod_e dtlm, ZSTD_tableFillPurpose_e tfp) @@ -190,7 +190,7 @@ ZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 ma FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_noDict_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, int useCmov) { @@ -424,7 +424,7 @@ _match: /* Requires: ip0, match0, offcode */ #define ZSTD_GEN_FAST_FN(dictMode, mml, cmov) \ static size_t ZSTD_compressBlock_fast_##dictMode##_##mml##_##cmov( \ - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ void const* src, size_t srcSize) \ { \ return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mml, cmov); \ @@ -441,7 +441,7 @@ ZSTD_GEN_FAST_FN(noDict, 6, 0) ZSTD_GEN_FAST_FN(noDict, 7, 0) size_t ZSTD_compressBlock_fast( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mml = ms->cParams.minMatch; @@ -481,7 +481,7 @@ size_t ZSTD_compressBlock_fast( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_dictMatchState_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -500,7 +500,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( const BYTE* const ilimit = iend - HASH_READ_SIZE; U32 offset_1=rep[0], offset_2=rep[1]; - const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_MatchState_t* const dms = ms->dictMatchState; const ZSTD_compressionParameters* const dictCParams = &dms->cParams ; const U32* const dictHashTable = dms->hashTable; const U32 dictStartIndex = dms->window.dictLimit; @@ -684,7 +684,7 @@ ZSTD_GEN_FAST_FN(dictMatchState, 6, 0) ZSTD_GEN_FAST_FN(dictMatchState, 7, 0) size_t ZSTD_compressBlock_fast_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; @@ -707,7 +707,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState( static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_fast_extDict_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize, U32 const mls, U32 const hasStep) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -965,7 +965,7 @@ ZSTD_GEN_FAST_FN(extDict, 6, 0) ZSTD_GEN_FAST_FN(extDict, 7, 0) size_t ZSTD_compressBlock_fast_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { U32 const mls = ms->cParams.minMatch; diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h index 5a971cf32..f7fbf4f68 100644 --- a/lib/compress/zstd_fast.h +++ b/lib/compress/zstd_fast.h @@ -18,17 +18,17 @@ extern "C" { #include "../common/mem.h" /* U32 */ #include "zstd_compress_internal.h" -void ZSTD_fillHashTable(ZSTD_matchState_t* ms, +void ZSTD_fillHashTable(ZSTD_MatchState_t* ms, void const* end, ZSTD_dictTableLoadMethod_e dtlm, ZSTD_tableFillPurpose_e tfp); size_t ZSTD_compressBlock_fast( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_fast_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_fast_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #if defined (__cplusplus) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 9fe56c76b..272ebe0ec 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -26,7 +26,7 @@ static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_updateDUBT(ZSTD_matchState_t* ms, +void ZSTD_updateDUBT(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend, U32 mls) { @@ -71,7 +71,7 @@ void ZSTD_updateDUBT(ZSTD_matchState_t* ms, * doesn't fail */ static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_insertDUBT1(const ZSTD_matchState_t* ms, +void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 curr, const BYTE* inputEnd, U32 nbCompares, U32 btLow, const ZSTD_dictMode_e dictMode) @@ -162,7 +162,7 @@ void ZSTD_insertDUBT1(const ZSTD_matchState_t* ms, static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_DUBT_findBetterDictMatch ( - const ZSTD_matchState_t* ms, + const ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, size_t* offsetPtr, size_t bestLength, @@ -170,7 +170,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( U32 const mls, const ZSTD_dictMode_e dictMode) { - const ZSTD_matchState_t * const dms = ms->dictMatchState; + const ZSTD_MatchState_t * const dms = ms->dictMatchState; const ZSTD_compressionParameters* const dmsCParams = &dms->cParams; const U32 * const dictHashTable = dms->hashTable; U32 const hashLog = dmsCParams->hashLog; @@ -240,7 +240,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -size_t ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, +size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, size_t* offBasePtr, U32 const mls, @@ -392,7 +392,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, /** ZSTD_BtFindBestMatch() : Tree updater, providing best match */ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -size_t ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms, +size_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offBasePtr, const U32 mls /* template */, @@ -408,7 +408,7 @@ size_t ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms, * Dedicated dict search ***********************************/ -void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip) +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip) { const BYTE* const base = ms->window.base; U32 const target = (U32)(ip - base); @@ -527,7 +527,7 @@ void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const B */ FORCE_INLINE_TEMPLATE size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nbAttempts, - const ZSTD_matchState_t* const dms, + const ZSTD_MatchState_t* const dms, const BYTE* const ip, const BYTE* const iLimit, const BYTE* const prefixStart, const U32 curr, const U32 dictLimit, const size_t ddsIdx) { @@ -630,7 +630,7 @@ size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nb FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_insertAndFindFirstIndex_internal( - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, const ZSTD_compressionParameters* const cParams, const BYTE* ip, U32 const mls, U32 const lazySkipping) { @@ -656,7 +656,7 @@ U32 ZSTD_insertAndFindFirstIndex_internal( return hashTable[ZSTD_hashPtr(ip, hashLog, mls)]; } -U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) { +U32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip) { const ZSTD_compressionParameters* const cParams = &ms->cParams; return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch, /* lazySkipping*/ 0); } @@ -665,7 +665,7 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) { FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_HcFindBestMatch( - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offsetPtr, const U32 mls, const ZSTD_dictMode_e dictMode) @@ -689,7 +689,7 @@ size_t ZSTD_HcFindBestMatch( U32 nbAttempts = 1U << cParams->searchLog; size_t ml=4-1; - const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_MatchState_t* const dms = ms->dictMatchState; const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0; const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch @@ -834,7 +834,7 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, BYTE const* t */ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base, +void ZSTD_row_fillHashCache(ZSTD_MatchState_t* ms, const BYTE* base, U32 const rowLog, U32 const mls, U32 idx, const BYTE* const iLimit) { @@ -882,7 +882,7 @@ U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable, */ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms, +void ZSTD_row_update_internalImpl(ZSTD_MatchState_t* ms, U32 updateStartIdx, U32 const updateEndIdx, U32 const mls, U32 const rowLog, U32 const rowMask, U32 const useCache) @@ -913,7 +913,7 @@ void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms, */ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip, +void ZSTD_row_update_internal(ZSTD_MatchState_t* ms, const BYTE* ip, U32 const mls, U32 const rowLog, U32 const rowMask, U32 const useCache) { @@ -946,7 +946,7 @@ void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip, * External wrapper for ZSTD_row_update_internal(). Used for filling the hashtable during dictionary * processing. */ -void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) { +void ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip) { const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); const U32 rowMask = (1u << rowLog) - 1; const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */); @@ -1139,7 +1139,7 @@ ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 headGr FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_RowFindBestMatch( - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offsetPtr, const U32 mls, const ZSTD_dictMode_e dictMode, @@ -1171,7 +1171,7 @@ size_t ZSTD_RowFindBestMatch( U32 hash; /* DMS/DDS variables that may be referenced laster */ - const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_MatchState_t* const dms = ms->dictMatchState; /* Initialize the following variables to satisfy static analyzer */ size_t ddsIdx = 0; @@ -1340,7 +1340,7 @@ size_t ZSTD_RowFindBestMatch( * ZSTD_searchMax() dispatches to the correct implementation function. * * TODO: The start of the search function involves loading and calculating a - * bunch of constants from the ZSTD_matchState_t. These computations could be + * bunch of constants from the ZSTD_MatchState_t. These computations could be * done in an initialization function, and saved somewhere in the match state. * Then we could pass a pointer to the saved state instead of the match state, * and avoid duplicate computations. @@ -1364,7 +1364,7 @@ size_t ZSTD_RowFindBestMatch( #define GEN_ZSTD_BT_SEARCH_FN(dictMode, mls) \ ZSTD_SEARCH_FN_ATTRS size_t ZSTD_BT_SEARCH_FN(dictMode, mls)( \ - ZSTD_matchState_t* ms, \ + ZSTD_MatchState_t* ms, \ const BYTE* ip, const BYTE* const iLimit, \ size_t* offBasePtr) \ { \ @@ -1374,7 +1374,7 @@ size_t ZSTD_RowFindBestMatch( #define GEN_ZSTD_HC_SEARCH_FN(dictMode, mls) \ ZSTD_SEARCH_FN_ATTRS size_t ZSTD_HC_SEARCH_FN(dictMode, mls)( \ - ZSTD_matchState_t* ms, \ + ZSTD_MatchState_t* ms, \ const BYTE* ip, const BYTE* const iLimit, \ size_t* offsetPtr) \ { \ @@ -1384,7 +1384,7 @@ size_t ZSTD_RowFindBestMatch( #define GEN_ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog) \ ZSTD_SEARCH_FN_ATTRS size_t ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)( \ - ZSTD_matchState_t* ms, \ + ZSTD_MatchState_t* ms, \ const BYTE* ip, const BYTE* const iLimit, \ size_t* offsetPtr) \ { \ @@ -1485,7 +1485,7 @@ typedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searc * If a match is found its offset is stored in @p offsetPtr. */ FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax( - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend, size_t* offsetPtr, @@ -1514,7 +1514,7 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_lazy_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const searchMethod_e searchMethod, const U32 depth, @@ -1537,7 +1537,7 @@ size_t ZSTD_compressBlock_lazy_generic( const int isDMS = dictMode == ZSTD_dictMatchState; const int isDDS = dictMode == ZSTD_dedicatedDictSearch; const int isDxS = isDMS || isDDS; - const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_MatchState_t* const dms = ms->dictMatchState; const U32 dictLowestIndex = isDxS ? dms->window.dictLimit : 0; const BYTE* const dictBase = isDxS ? dms->window.base : NULL; const BYTE* const dictLowest = isDxS ? dictBase + dictLowestIndex : NULL; @@ -1782,42 +1782,42 @@ _storeSequence: #ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_greedy( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_noDict); } size_t ZSTD_compressBlock_greedy_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch); } size_t ZSTD_compressBlock_greedy_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict); } size_t ZSTD_compressBlock_greedy_dictMatchState_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch); @@ -1826,42 +1826,42 @@ size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( #ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch); } size_t ZSTD_compressBlock_lazy_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy_dictMatchState_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch); @@ -1870,42 +1870,42 @@ size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( #ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy2_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch); } size_t ZSTD_compressBlock_lazy2_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict); } size_t ZSTD_compressBlock_lazy2_dictMatchState_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch); @@ -1914,14 +1914,14 @@ size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( #ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btlazy2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_noDict); } size_t ZSTD_compressBlock_btlazy2_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_dictMatchState); @@ -1935,7 +1935,7 @@ size_t ZSTD_compressBlock_btlazy2_dictMatchState( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_compressBlock_lazy_extDict_generic( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const searchMethod_e searchMethod, const U32 depth) @@ -2139,14 +2139,14 @@ _storeSequence: #ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_greedy_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0); } size_t ZSTD_compressBlock_greedy_extDict_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0); @@ -2155,7 +2155,7 @@ size_t ZSTD_compressBlock_greedy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { @@ -2163,7 +2163,7 @@ size_t ZSTD_compressBlock_lazy_extDict( } size_t ZSTD_compressBlock_lazy_extDict_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { @@ -2173,7 +2173,7 @@ size_t ZSTD_compressBlock_lazy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy2_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { @@ -2181,7 +2181,7 @@ size_t ZSTD_compressBlock_lazy2_extDict( } size_t ZSTD_compressBlock_lazy2_extDict_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2); @@ -2190,7 +2190,7 @@ size_t ZSTD_compressBlock_lazy2_extDict_row( #ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btlazy2_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) { diff --git a/lib/compress/zstd_lazy.h b/lib/compress/zstd_lazy.h index 21258145e..6da51e4ec 100644 --- a/lib/compress/zstd_lazy.h +++ b/lib/compress/zstd_lazy.h @@ -31,38 +31,38 @@ extern "C" { || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \ || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \ || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) -U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip); -void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip); +U32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip); +void ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip); -void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip); +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip); void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */ #endif #ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_greedy( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dictMatchState_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_extDict_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_GREEDY ZSTD_compressBlock_greedy @@ -86,28 +86,28 @@ size_t ZSTD_compressBlock_greedy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dictMatchState_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy_extDict_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_LAZY ZSTD_compressBlock_lazy @@ -131,28 +131,28 @@ size_t ZSTD_compressBlock_lazy_extDict_row( #ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_lazy2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dictMatchState_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_lazy2_extDict_row( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_LAZY2 ZSTD_compressBlock_lazy2 @@ -176,13 +176,13 @@ size_t ZSTD_compressBlock_lazy2_extDict_row( #ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btlazy2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btlazy2_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btlazy2_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_BTLAZY2 ZSTD_compressBlock_btlazy2 diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index e636a42c0..8812b72a2 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -234,7 +234,7 @@ static size_t ZSTD_ldm_countBackwardsMatch_2segments( * * The tables for the other strategies are filled within their * block compressors. */ -static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms, +static size_t ZSTD_ldm_fillFastTables(ZSTD_MatchState_t* ms, void const* end) { const BYTE* const iend = (const BYTE*)end; @@ -314,7 +314,7 @@ void ZSTD_ldm_fillHashTable( * Sets cctx->nextToUpdate to a position corresponding closer to anchor * if it is far way * (after a long match, only update tables a limited amount). */ -static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor) +static void ZSTD_ldm_limitTableUpdate(ZSTD_MatchState_t* ms, const BYTE* anchor) { U32 const curr = (U32)(anchor - ms->window.base); if (curr > ms->nextToUpdate + 1024) { @@ -665,7 +665,7 @@ void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { } size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize) { diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index 624caf937..9bdf90cda 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -65,7 +65,7 @@ size_t ZSTD_ldm_generateSequences( * NOTE: This function does not return any errors. */ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 1045cdd2c..1aee5017b 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -408,7 +408,7 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length) Assumption : always within prefix (i.e. not within extDict) */ static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_matchState_t* ms, +U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_MatchState_t* ms, U32* nextToUpdate3, const BYTE* const ip) { @@ -440,7 +440,7 @@ U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_matchState_t* ms, static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_insertBt1( - const ZSTD_matchState_t* ms, + const ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, U32 const target, U32 const mls, const int extDict) @@ -560,7 +560,7 @@ U32 ZSTD_insertBt1( FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_updateTree_internal( - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, const U32 mls, const ZSTD_dictMode_e dictMode) { @@ -580,7 +580,7 @@ void ZSTD_updateTree_internal( ms->nextToUpdate = target; } -void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) { +void ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend) { ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict); } @@ -589,7 +589,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_insertBtAndGetAllMatches ( ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */ - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, U32* nextToUpdate3, const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode, @@ -625,7 +625,7 @@ ZSTD_insertBtAndGetAllMatches ( U32 mnum = 0; U32 nbCompares = 1U << cParams->searchLog; - const ZSTD_matchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL; + const ZSTD_MatchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL; const ZSTD_compressionParameters* const dmsCParams = dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL; const BYTE* const dmsBase = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL; @@ -819,7 +819,7 @@ ZSTD_insertBtAndGetAllMatches ( typedef U32 (*ZSTD_getAllMatchesFn)( ZSTD_match_t*, - ZSTD_matchState_t*, + ZSTD_MatchState_t*, U32*, const BYTE*, const BYTE*, @@ -831,7 +831,7 @@ FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR U32 ZSTD_btGetAllMatches_internal( ZSTD_match_t* matches, - ZSTD_matchState_t* ms, + ZSTD_MatchState_t* ms, U32* nextToUpdate3, const BYTE* ip, const BYTE* const iHighLimit, @@ -854,7 +854,7 @@ U32 ZSTD_btGetAllMatches_internal( #define GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, mls) \ static U32 ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls)( \ ZSTD_match_t* matches, \ - ZSTD_matchState_t* ms, \ + ZSTD_MatchState_t* ms, \ U32* nextToUpdate3, \ const BYTE* ip, \ const BYTE* const iHighLimit, \ @@ -886,7 +886,7 @@ GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState) } static ZSTD_getAllMatchesFn -ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const* ms, ZSTD_dictMode_e const dictMode) +ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const dictMode) { ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = { ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict), @@ -1072,7 +1072,7 @@ listStats(const U32* table, int lastEltID) FORCE_INLINE_TEMPLATE ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t -ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, +ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, @@ -1440,7 +1440,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt0( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode); @@ -1449,7 +1449,7 @@ static size_t ZSTD_compressBlock_opt0( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode); @@ -1458,7 +1458,7 @@ static size_t ZSTD_compressBlock_opt2( #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock_btopt"); @@ -1477,7 +1477,7 @@ size_t ZSTD_compressBlock_btopt( */ static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR -void ZSTD_initStats_ultra(ZSTD_matchState_t* ms, +void ZSTD_initStats_ultra(ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) @@ -1503,7 +1503,7 @@ void ZSTD_initStats_ultra(ZSTD_matchState_t* ms, } size_t ZSTD_compressBlock_btultra( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize); @@ -1511,7 +1511,7 @@ size_t ZSTD_compressBlock_btultra( } size_t ZSTD_compressBlock_btultra2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { U32 const curr = (U32)((const BYTE*)src - ms->window.base); @@ -1541,14 +1541,14 @@ size_t ZSTD_compressBlock_btultra2( #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_btopt_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict); @@ -1557,14 +1557,14 @@ size_t ZSTD_compressBlock_btopt_extDict( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btultra_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_btultra_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict); diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h index 9e1cff91a..247c9ee65 100644 --- a/lib/compress/zstd_opt.h +++ b/lib/compress/zstd_opt.h @@ -21,18 +21,18 @@ extern "C" { || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \ || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR) /* used in ZSTD_loadDictionaryContent() */ -void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend); +void ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend); #endif #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btopt_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btopt_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_BTOPT ZSTD_compressBlock_btopt @@ -46,20 +46,20 @@ size_t ZSTD_compressBlock_btopt_extDict( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btultra( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btultra_dictMatchState( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btultra_extDict( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); /* note : no btultra2 variant for extDict nor dictMatchState, * because btultra2 is not meant to work with dictionaries * and is only specific for the first block (no prefix) */ size_t ZSTD_compressBlock_btultra2( - ZSTD_matchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); #define ZSTD_COMPRESSBLOCK_BTULTRA ZSTD_compressBlock_btultra From 41c667c0fdfa653f52809975bce8306b21099810 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:00:20 -0800 Subject: [PATCH 218/405] codemod: repcodes_t -> Repcodes_t --- lib/compress/zstd_compress.c | 66 +++++++++++++------------ lib/compress/zstd_compress_internal.h | 6 +-- lib/compress/zstd_compress_superblock.c | 2 +- lib/compress/zstd_opt.c | 16 +++--- 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 029928fb2..03806c234 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3427,7 +3427,7 @@ static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const SeqStore ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex; const size_t nbOutSequences = nbInSequences + 1; size_t nbOutLiterals = 0; - repcodes_t repcodes; + Repcodes_t repcodes; size_t i; /* Bounds check that we have enough space for every input sequence @@ -4059,7 +4059,7 @@ ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, c * 4+ : real_offset+3 */ static void -ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes, +ZSTD_seqStore_resolveOffCodes(Repcodes_t* const dRepcodes, Repcodes_t* const cRepcodes, const SeqStore_t* const seqStore, U32 const nbSeq) { U32 idx = 0; @@ -4096,7 +4096,7 @@ ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRe static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, const SeqStore_t* const seqStore, - repcodes_t* const dRep, repcodes_t* const cRep, + Repcodes_t* const dRep, Repcodes_t* const cRep, void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock, U32 isPartition) @@ -4108,7 +4108,7 @@ ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, size_t cSeqsSize; /* In case of an RLE or raw block, the simulated decompression repcode history must be reset */ - repcodes_t const dRepOriginal = *dRep; + Repcodes_t const dRepOriginal = *dRep; DEBUGLOG(5, "ZSTD_compressSeqStore_singleBlock"); if (isPartition) ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart)); @@ -4279,10 +4279,10 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, * * See ZSTD_seqStore_resolveOffCodes() for more details. */ - repcodes_t dRep; - repcodes_t cRep; - ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); - ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + Repcodes_t dRep; + Repcodes_t cRep; + ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(Repcodes_t)); + ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(Repcodes_t)); ZSTD_memset(nextSeqStore, 0, sizeof(SeqStore_t)); DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", @@ -4338,7 +4338,7 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, /* cRep and dRep may have diverged during the compression. * If so, we use the dRep repcodes for the next block. */ - ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(repcodes_t)); + ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(Repcodes_t)); return cSize; } @@ -6617,21 +6617,22 @@ static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 /* This function scans through an array of ZSTD_Sequence, * storing the sequences it reads, until it reaches a block delimiter. - * Note that the block delimiter must include the last literals of the block. + * Note that the block delimiter includes the last literals of the block. + * @blockSize must be == sum(sequence_lengths). * @returns 0 on success, and a ZSTD_error otherwise. */ static size_t ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, - const void* src, size_t blockSize, - ZSTD_paramSwitch_e externalRepSearch) + ZSTD_SequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, + ZSTD_paramSwitch_e externalRepSearch) { U32 idx = seqPos->idx; U32 const startIdx = idx; BYTE const* ip = (BYTE const*)(src); const BYTE* const iend = ip + blockSize; - repcodes_t updatedRepcodes; + Repcodes_t updatedRepcodes; U32 dictSize; DEBUGLOG(5, "ZSTD_transferSequences_wBlockDelim (blockSize = %zu)", blockSize); @@ -6643,7 +6644,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, } else { dictSize = 0; } - ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t)); for (; idx < inSeqsSize && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) { U32 const litLength = inSeqs[idx].litLength; U32 const matchLength = inSeqs[idx].matchLength; @@ -6695,7 +6696,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, } } - ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); if (inSeqs[idx].litLength) { DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength); @@ -6708,24 +6709,25 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, return 0; } -/* Returns the number of bytes to move the current read position back by. - * Only non-zero if we ended up splitting a sequence. - * Otherwise, it may return a ZSTD error if something went wrong. - * - * This function will attempt to scan through blockSize bytes +/* + * This function attempts to scan through blockSize bytes * represented by the sequences in @inSeqs, * storing any (partial) sequences. * + * @returns the number of bytes to move the current read position back by. + * Only non-zero if we ended up splitting a sequence. + * Otherwise, it may return a ZSTD error if something went wrong. + * * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to * avoid splitting a match, or to avoid splitting a match such that it would produce a match * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block. */ static size_t -ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, - const void* src, size_t blockSize, - ZSTD_paramSwitch_e externalRepSearch) +ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, + ZSTD_paramSwitch_e externalRepSearch) { U32 idx = seqPos->idx; U32 startPosInSequence = seqPos->posInSequence; @@ -6733,7 +6735,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, size_t dictSize; BYTE const* ip = (BYTE const*)(src); BYTE const* iend = ip + blockSize; /* May be adjusted if we decide to process fewer than blockSize bytes */ - repcodes_t updatedRepcodes; + Repcodes_t updatedRepcodes; U32 bytesAdjustment = 0; U32 finalMatchSplit = 0; @@ -6747,9 +6749,9 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, } else { dictSize = 0; } - DEBUGLOG(5, "ZSTD_copySequencesToSeqStoreNoBlockDelim: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize); + DEBUGLOG(5, "ZSTD_transferSequences_noDelim: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize); DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); - ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t)); while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) { const ZSTD_Sequence currSeq = inSeqs[idx]; U32 litLength = currSeq.litLength; @@ -6830,7 +6832,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength); seqPos->idx = idx; seqPos->posInSequence = endPosInSequence; - ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); iend -= bytesAdjustment; if (ip != iend) { @@ -6855,7 +6857,7 @@ static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mod return ZSTD_transferSequences_wBlockDelim; } assert(mode == ZSTD_sf_noBlockDelimiters); - return ZSTD_copySequencesToSeqStoreNoBlockDelim; + return ZSTD_transferSequences_noDelim; } /* Discover the size of next block by searching for the delimiter. diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 91066a4be..2387d9c28 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -849,12 +849,12 @@ ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0) typedef struct repcodes_s { U32 rep[3]; -} repcodes_t; +} Repcodes_t; -MEM_STATIC repcodes_t +MEM_STATIC Repcodes_t ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0) { - repcodes_t newReps; + Repcodes_t newReps; ZSTD_memcpy(&newReps, rep, sizeof(newReps)); ZSTD_updateRep(newReps.rep, offBase, ll0); return newReps; diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 672af2d32..6f57345be 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -648,7 +648,7 @@ static size_t ZSTD_compressSubBlock_multi(const SeqStore_t* seqStorePtr, /* We have to regenerate the repcodes because we've skipped some sequences */ if (sp < send) { const SeqDef* seq; - repcodes_t rep; + Repcodes_t rep; ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep)); for (seq = sstart; seq < sp; ++seq) { ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 1aee5017b..8f3b4d100 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1227,13 +1227,13 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, && (with1literal < opt[cur+1].price) ) { /* update offset history - before it disappears */ U32 const prev = cur - prevMatch.mlen; - repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, prevMatch.off, opt[prev].litlen==0); + Repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, prevMatch.off, opt[prev].litlen==0); assert(cur >= prevMatch.mlen); DEBUGLOG(7, "==> match+1lit is cheaper (%.2f < %.2f) (hist:%u,%u,%u) !", ZSTD_fCost(with1literal), ZSTD_fCost(withMoreLiterals), newReps.rep[0], newReps.rep[1], newReps.rep[2] ); opt[cur+1] = prevMatch; /* mlen & offbase */ - ZSTD_memcpy(opt[cur+1].rep, &newReps, sizeof(repcodes_t)); + ZSTD_memcpy(opt[cur+1].rep, &newReps, sizeof(Repcodes_t)); opt[cur+1].litlen = 1; opt[cur+1].price = with1literal; if (last_pos < cur+1) last_pos = cur+1; @@ -1248,13 +1248,13 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, /* Offset history is not updated during match comparison. * Do it here, now that the match is selected and confirmed. */ - ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t)); + ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(Repcodes_t)); assert(cur >= opt[cur].mlen); if (opt[cur].litlen == 0) { /* just finished a match => alter offset history */ U32 const prev = cur - opt[cur].mlen; - repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[prev].litlen==0); - ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); + Repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[prev].litlen==0); + ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(Repcodes_t)); } /* last match must start at a minimum distance of 8 from oend */ @@ -1353,10 +1353,10 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ /* Update offset history */ if (lastStretch.litlen == 0) { /* finishing on a match : update offset history */ - repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastStretch.off, opt[cur].litlen==0); - ZSTD_memcpy(rep, &reps, sizeof(repcodes_t)); + Repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastStretch.off, opt[cur].litlen==0); + ZSTD_memcpy(rep, &reps, sizeof(Repcodes_t)); } else { - ZSTD_memcpy(rep, lastStretch.rep, sizeof(repcodes_t)); + ZSTD_memcpy(rep, lastStretch.rep, sizeof(Repcodes_t)); assert(cur >= lastStretch.litlen); cur -= lastStretch.litlen; } From 25bef24c5cf47fe9841edb4b2b6708e206833d31 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:04:01 -0800 Subject: [PATCH 219/405] codemod: rawSeqStore_t -> RawSeqStore_t --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_compress_internal.h | 8 ++++---- lib/compress/zstd_ldm.c | 12 ++++++------ lib/compress/zstd_ldm.h | 8 ++++---- lib/compress/zstd_opt.c | 4 ++-- lib/compress/zstdmt_compress.c | 16 ++++++++-------- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 03806c234..7ad630735 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3317,7 +3317,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) src, srcSize); assert(zc->externSeqStore.pos <= zc->externSeqStore.size); } else if (zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) { - rawSeqStore_t ldmSeqStore = kNullRawSeqStore; + RawSeqStore_t ldmSeqStore = kNullRawSeqStore; /* External matchfinder + LDM is technically possible, just not implemented yet. * We need to revisit soon and implement it. */ diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 2387d9c28..9fb35de48 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -213,9 +213,9 @@ typedef struct { stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */ size_t size; /* The number of sequences. <= capacity. */ size_t capacity; /* The capacity starting from `seq` pointer */ -} rawSeqStore_t; +} RawSeqStore_t; -UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0}; +UNUSED_ATTR static const RawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0}; typedef struct { int price; /* price from beginning of segment to this position */ @@ -303,7 +303,7 @@ struct ZSTD_MatchState_t { optState_t opt; /* optimal parser state */ const ZSTD_MatchState_t* dictMatchState; ZSTD_compressionParameters cParams; - const rawSeqStore_t* ldmSeqStore; + const RawSeqStore_t* ldmSeqStore; /* Controls prefetching in some dictMatchState matchfinders. * This behavior is controlled from the cctx ms. @@ -500,7 +500,7 @@ struct ZSTD_CCtx_s { ldmState_t ldmState; /* long distance matching state */ rawSeq* ldmSequences; /* Storage for the ldm output sequences */ size_t maxNbLdmSequences; - rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ + RawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ ZSTD_blockState_t blockState; void* tmpWorkspace; /* used as substitute of stack space - must be aligned for S64 type */ size_t tmpWkspSize; diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 8812b72a2..30caeb1a8 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -326,7 +326,7 @@ static void ZSTD_ldm_limitTableUpdate(ZSTD_MatchState_t* ms, const BYTE* anchor) static ZSTD_ALLOW_POINTER_OVERFLOW_ATTR size_t ZSTD_ldm_generateSequences_internal( - ldmState_t* ldmState, rawSeqStore_t* rawSeqStore, + ldmState_t* ldmState, RawSeqStore_t* rawSeqStore, ldmParams_t const* params, void const* src, size_t srcSize) { /* LDM parameters */ @@ -510,7 +510,7 @@ static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size, } size_t ZSTD_ldm_generateSequences( - ldmState_t* ldmState, rawSeqStore_t* sequences, + ldmState_t* ldmState, RawSeqStore_t* sequences, ldmParams_t const* params, void const* src, size_t srcSize) { U32 const maxDist = 1U << params->windowLog; @@ -587,7 +587,7 @@ size_t ZSTD_ldm_generateSequences( } void -ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) +ZSTD_ldm_skipSequences(RawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) { while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) { rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos; @@ -623,7 +623,7 @@ ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const min * Returns the current sequence to handle, or if the rest of the block should * be literals, it returns a sequence with offset == 0. */ -static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore, +static rawSeq maybeSplitSequence(RawSeqStore_t* rawSeqStore, U32 const remaining, U32 const minMatch) { rawSeq sequence = rawSeqStore->seq[rawSeqStore->pos]; @@ -647,7 +647,7 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore, return sequence; } -void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { +void ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes) { U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); while (currPos && rawSeqStore->pos < rawSeqStore->size) { rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; @@ -664,7 +664,7 @@ void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { } } -size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, +size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore, ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize) diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index 9bdf90cda..e43ab4e78 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -43,7 +43,7 @@ void ZSTD_ldm_fillHashTable( * sequences. */ size_t ZSTD_ldm_generateSequences( - ldmState_t* ldms, rawSeqStore_t* sequences, + ldmState_t* ldms, RawSeqStore_t* sequences, ldmParams_t const* params, void const* src, size_t srcSize); /** @@ -64,7 +64,7 @@ size_t ZSTD_ldm_generateSequences( * two. We handle that case correctly, and update `rawSeqStore` appropriately. * NOTE: This function does not return any errors. */ -size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, +size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore, ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize); @@ -76,7 +76,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, * Avoids emitting matches less than `minMatch` bytes. * Must be called for data that is not passed to ZSTD_ldm_blockCompress(). */ -void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, +void ZSTD_ldm_skipSequences(RawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch); /* ZSTD_ldm_skipRawSeqStoreBytes(): @@ -84,7 +84,7 @@ void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, * Not to be used in conjunction with ZSTD_ldm_skipSequences(). * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). */ -void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes); +void ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes); /** ZSTD_ldm_getTableSize() : * Estimate the space needed for long distance matching tables or 0 if LDM is diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 8f3b4d100..0ab33d56e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -905,7 +905,7 @@ ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const di /* Struct containing info needed to make decision about ldm inclusion */ typedef struct { - rawSeqStore_t seqStore; /* External match candidates store for this block */ + RawSeqStore_t seqStore; /* External match candidates store for this block */ U32 startPosInBlock; /* Start position of the current match candidate */ U32 endPosInBlock; /* End position of the current match candidate */ U32 offset; /* Offset of the match candidate */ @@ -915,7 +915,7 @@ typedef struct { * Moves forward in @rawSeqStore by @nbBytes, * which will update the fields 'pos' and 'posInSequence'. */ -static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) +static void ZSTD_optLdm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes) { U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); while (currPos && rawSeqStore->pos < rawSeqStore->size) { diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 86ccce318..e8fef5144 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -290,15 +290,15 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) return ZSTDMT_sizeof_bufferPool(seqPool); } -static rawSeqStore_t bufferToSeq(buffer_t buffer) +static RawSeqStore_t bufferToSeq(buffer_t buffer) { - rawSeqStore_t seq = kNullRawSeqStore; + RawSeqStore_t seq = kNullRawSeqStore; seq.seq = (rawSeq*)buffer.start; seq.capacity = buffer.capacity / sizeof(rawSeq); return seq; } -static buffer_t seqToBuffer(rawSeqStore_t seq) +static buffer_t seqToBuffer(RawSeqStore_t seq) { buffer_t buffer; buffer.start = seq.seq; @@ -306,7 +306,7 @@ static buffer_t seqToBuffer(rawSeqStore_t seq) return buffer; } -static rawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool) +static RawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool) { if (seqPool->bufferSize == 0) { return kNullRawSeqStore; @@ -315,13 +315,13 @@ static rawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool) } #if ZSTD_RESIZE_SEQPOOL -static rawSeqStore_t ZSTDMT_resizeSeq(ZSTDMT_seqPool* seqPool, rawSeqStore_t seq) +static RawSeqStore_t ZSTDMT_resizeSeq(ZSTDMT_seqPool* seqPool, RawSeqStore_t seq) { return bufferToSeq(ZSTDMT_resizeBuffer(seqPool, seqToBuffer(seq))); } #endif -static void ZSTDMT_releaseSeq(ZSTDMT_seqPool* seqPool, rawSeqStore_t seq) +static void ZSTDMT_releaseSeq(ZSTDMT_seqPool* seqPool, RawSeqStore_t seq) { ZSTDMT_releaseBuffer(seqPool, seqToBuffer(seq)); } @@ -578,7 +578,7 @@ static void ZSTDMT_serialState_free(serialState_t* serialState) } static void ZSTDMT_serialState_update(serialState_t* serialState, - ZSTD_CCtx* jobCCtx, rawSeqStore_t seqStore, + ZSTD_CCtx* jobCCtx, RawSeqStore_t seqStore, range_t src, unsigned jobID) { /* Wait for our turn */ @@ -685,7 +685,7 @@ static void ZSTDMT_compressionJob(void* jobDescription) ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription; ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */ ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool); - rawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool); + RawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool); buffer_t dstBuff = job->dstBuff; size_t lastCBlockSize = 0; From 08edecb78c0b95db74aa9747cc06206d74027b0f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:08:44 -0800 Subject: [PATCH 220/405] codemod: ZSTD_blockCompressor -> ZSTD_BlockCompressor_f --- lib/compress/zstd_compress.c | 12 ++++++------ lib/compress/zstd_compress_internal.h | 4 ++-- lib/compress/zstd_ldm.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 7ad630735..0c094dabc 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3074,9 +3074,9 @@ ZSTD_entropyCompressSeqStore( /* ZSTD_selectBlockCompressor() : * Not static, but internal use only (used by long distance matcher) * assumption : strat is a valid strategy */ -ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode) +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode) { - static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { + static const ZSTD_BlockCompressor_f blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { { ZSTD_compressBlock_fast /* default for 0 */, ZSTD_compressBlock_fast, ZSTD_COMPRESSBLOCK_DOUBLEFAST, @@ -3121,13 +3121,13 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramS NULL, NULL } }; - ZSTD_blockCompressor selectedCompressor; + ZSTD_BlockCompressor_f selectedCompressor; ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat)); DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder); if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) { - static const ZSTD_blockCompressor rowBasedBlockCompressors[4][3] = { + static const ZSTD_BlockCompressor_f rowBasedBlockCompressors[4][3] = { { ZSTD_COMPRESSBLOCK_GREEDY_ROW, ZSTD_COMPRESSBLOCK_LAZY_ROW, @@ -3391,7 +3391,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) } /* Fallback to software matchfinder */ - { ZSTD_blockCompressor const blockCompressor = + { ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor( zc->appliedParams.cParams.strategy, zc->appliedParams.useRowMatchFinder, @@ -3405,7 +3405,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); } } } else { /* not long range mode and no external matchfinder */ - ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor( + ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor( zc->appliedParams.cParams.strategy, zc->appliedParams.useRowMatchFinder, dictMode); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 9fb35de48..8257607e0 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -579,10 +579,10 @@ typedef enum { */ } ZSTD_cParamMode_e; -typedef size_t (*ZSTD_blockCompressor) ( +typedef size_t (*ZSTD_BlockCompressor_f) ( ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); MEM_STATIC U32 ZSTD_LLcode(U32 litLength) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 30caeb1a8..2b84c3027 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -671,7 +671,7 @@ size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore, { const ZSTD_compressionParameters* const cParams = &ms->cParams; unsigned const minMatch = cParams->minMatch; - ZSTD_blockCompressor const blockCompressor = + ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms)); /* Input bounds */ BYTE const* const istart = (BYTE const*)src; From e0f3aaee467bbcb7e1653756eb426a9b7adde5d8 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:17:41 -0800 Subject: [PATCH 221/405] doc: add mention of frame checksum incompatibility for new prototype ZSTD_compressSequencesAndLiterals() --- lib/zstd.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/zstd.h b/lib/zstd.h index 94058a1b2..b3c82e174 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1660,10 +1660,11 @@ ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize, /*! ZSTD_compressSequencesAndLiterals() : * This is a variant of ZSTD_compressSequences() which, * instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), - * aka all literals already extracted and grouped into a single continuous buffer. + * aka all literals already extracted and laid out into a single continuous buffer. * This can be useful if the process generating the sequences also happens to generate the buffer of literals, * thus skipping an extraction + caching stage. - * To be valid, `litSize` must be equal to the sum of all @.litLength fields in @inSeqs. + * To be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. + * Important: Employing this prototype is incompatible with frame checksum. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t From 2503b64345b22d3f1729c2c380bc98500c8024aa Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:21:47 -0800 Subject: [PATCH 222/405] fix minor artifact error in single_file_lib --- build/single_file_libs/.gitignore | 1 + build/single_file_libs/examples/zstd_errors.h | 106 ------------------ 2 files changed, 1 insertion(+), 106 deletions(-) delete mode 100644 build/single_file_libs/examples/zstd_errors.h diff --git a/build/single_file_libs/.gitignore b/build/single_file_libs/.gitignore index 8c1bc71ed..b769e1089 100644 --- a/build/single_file_libs/.gitignore +++ b/build/single_file_libs/.gitignore @@ -4,6 +4,7 @@ zstddeclib.c zstdenclib.c zstd.c zstd.h +zstd_errors.h # test artifacts temp* diff --git a/build/single_file_libs/examples/zstd_errors.h b/build/single_file_libs/examples/zstd_errors.h deleted file mode 100644 index 20e488f15..000000000 --- a/build/single_file_libs/examples/zstd_errors.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#ifndef ZSTD_ERRORS_H_398273423 -#define ZSTD_ERRORS_H_398273423 - -#if defined (__cplusplus) -extern "C" { -#endif - -/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */ -#ifndef ZSTDERRORLIB_VISIBLE - /* Backwards compatibility with old macro name */ -# ifdef ZSTDERRORLIB_VISIBILITY -# define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY -# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) -# define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility ("default"))) -# else -# define ZSTDERRORLIB_VISIBLE -# endif -#endif - -#ifndef ZSTDERRORLIB_HIDDEN -# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) -# define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility ("hidden"))) -# else -# define ZSTDERRORLIB_HIDDEN -# endif -#endif - -#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) -# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE -#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) -# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ -#else -# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE -#endif - -/*-********************************************* - * Error codes list - *-********************************************* - * Error codes _values_ are pinned down since v1.3.1 only. - * Therefore, don't rely on values if you may link to any version < v1.3.1. - * - * Only values < 100 are considered stable. - * - * note 1 : this API shall be used with static linking only. - * dynamic linking is not yet officially supported. - * note 2 : Prefer relying on the enum than on its value whenever possible - * This is the only supported way to use the error list < v1.3.1 - * note 3 : ZSTD_isError() is always correct, whatever the library version. - **********************************************/ -typedef enum { - ZSTD_error_no_error = 0, - ZSTD_error_GENERIC = 1, - ZSTD_error_prefix_unknown = 10, - ZSTD_error_version_unsupported = 12, - ZSTD_error_frameParameter_unsupported = 14, - ZSTD_error_frameParameter_windowTooLarge = 16, - ZSTD_error_corruption_detected = 20, - ZSTD_error_checksum_wrong = 22, - ZSTD_error_literals_headerWrong = 24, - ZSTD_error_dictionary_corrupted = 30, - ZSTD_error_dictionary_wrong = 32, - ZSTD_error_dictionaryCreation_failed = 34, - ZSTD_error_parameter_unsupported = 40, - ZSTD_error_parameter_combination_unsupported = 41, - ZSTD_error_parameter_outOfBound = 42, - ZSTD_error_tableLog_tooLarge = 44, - ZSTD_error_maxSymbolValue_tooLarge = 46, - ZSTD_error_maxSymbolValue_tooSmall = 48, - ZSTD_error_stabilityCondition_notRespected = 50, - ZSTD_error_stage_wrong = 60, - ZSTD_error_init_missing = 62, - ZSTD_error_memory_allocation = 64, - ZSTD_error_workSpace_tooSmall= 66, - ZSTD_error_dstSize_tooSmall = 70, - ZSTD_error_srcSize_wrong = 72, - ZSTD_error_dstBuffer_null = 74, - ZSTD_error_noForwardProgress_destFull = 80, - ZSTD_error_noForwardProgress_inputEmpty = 82, - /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */ - ZSTD_error_frameIndex_tooLarge = 100, - ZSTD_error_seekableIO = 102, - ZSTD_error_dstBuffer_wrong = 104, - ZSTD_error_srcBuffer_wrong = 105, - ZSTD_error_sequenceProducer_failed = 106, - ZSTD_error_externalSequences_invalid = 107, - ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ -} ZSTD_ErrorCode; - -ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */ - - -#if defined (__cplusplus) -} -#endif - -#endif /* ZSTD_ERRORS_H_398273423 */ From 13b9296d79094185565f42b55a19fa88b43aa19d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:38:51 -0800 Subject: [PATCH 223/405] minor simplification --- doc/zstd_manual.html | 27 +++++++++++++++------------ lib/compress/zstd_compress.c | 17 +++++++---------- lib/zstd.h | 22 ++++++++++++---------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index e6f8fc504..a780e97d9 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1376,13 +1376,14 @@ ZSTD_generateSequences(ZSTD_CCtx* zc,


    ZSTDLIB_STATIC_API size_t
    -ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
    -            const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    -            const void* src, size_t srcSize);
    +ZSTD_compressSequences(ZSTD_CCtx* cctx,
    +           void* dst, size_t dstCapacity,
    +     const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    +     const void* src, size_t srcSize);
     

    Compress an array of ZSTD_Sequence, associated with @src buffer, into dst. @src contains the entire input (not just the literals). If @srcSize > sum(sequence.length), the remaining bytes are considered all literals - If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.) + If a dictionary is included, then the cctx should reference the dict (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.). The entire source is compressed into a single frame. The compression behavior changes based on cctx params. In particular: @@ -1403,23 +1404,25 @@ ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize, - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md - Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused. - Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly, - and cannot emit an RLE block that disagrees with the repcode history + Note: Repcodes are, as of now, always re-calculated within this function, ZSTD_Sequence.rep is effectively unused. + Dev Note: Once ability to ingest repcodes become available, the explicit block delims mode must respect those repcodes exactly, + and cannot emit an RLE block that disagrees with the repcode history. @return : final compressed size, or a ZSTD error code.


    ZSTDLIB_STATIC_API size_t
    -ZSTD_compressSequencesAndLiterals( ZSTD_CCtx* cctx, void* dst, size_t dstSize,
    -            const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    -            const void* literals, size_t litSize);
    +ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
    +                      void* dst, size_t dstCapacity,
    +                const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    +                const void* literals, size_t litSize);
     

    This is a variant of ZSTD_compressSequences() which, instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), - aka all literals already extracted and grouped into a single continuous buffer. + aka all literals already extracted and laid out into a single continuous buffer. This can be useful if the process generating the sequences also happens to generate the buffer of literals, thus skipping an extraction + caching stage. - To be valid, `litSize` must be equal to the sum of all @.litLength fields in @inSeqs. + To be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. + Important: Employing this prototype is incompatible with frame checksum. @return : final compressed size, or a ZSTD error code.


    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 0c094dabc..92f757b1b 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6887,20 +6887,17 @@ blockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD return blockSize; } -/* More a "target" block size */ -static size_t blockSize_noDelimiter(size_t blockSize, size_t remaining) -{ - int const lastBlock = (remaining <= blockSize); - return lastBlock ? remaining : blockSize; -} - static size_t determine_blockSize(ZSTD_SequenceFormat_e mode, size_t blockSize, size_t remaining, - const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_SequencePosition seqPos) + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + ZSTD_SequencePosition seqPos) { DEBUGLOG(6, "determine_blockSize : remainingSize = %zu", remaining); - if (mode == ZSTD_sf_noBlockDelimiters) - return blockSize_noDelimiter(blockSize, remaining); + if (mode == ZSTD_sf_noBlockDelimiters) { + /* Note: more a "target" block size */ + return MIN(remaining, blockSize); + } + assert(mode == ZSTD_sf_explicitBlockDelimiters); { size_t const explicitBlockSize = blockSize_explicitDelimiter(inSeqs, inSeqsSize, seqPos); FORWARD_IF_ERROR(explicitBlockSize, "Error while determining block size with explicit delimiters"); if (explicitBlockSize > blockSize) diff --git a/lib/zstd.h b/lib/zstd.h index b3c82e174..08feed9a6 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1625,7 +1625,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, si * Compress an array of ZSTD_Sequence, associated with @src buffer, into dst. * @src contains the entire input (not just the literals). * If @srcSize > sum(sequence.length), the remaining bytes are considered all literals - * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.) + * If a dictionary is included, then the cctx should reference the dict (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.). * The entire source is compressed into a single frame. * * The compression behavior changes based on cctx params. In particular: @@ -1646,15 +1646,16 @@ ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, si * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md * - * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused. - * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly, - * and cannot emit an RLE block that disagrees with the repcode history + * Note: Repcodes are, as of now, always re-calculated within this function, ZSTD_Sequence.rep is effectively unused. + * Dev Note: Once ability to ingest repcodes become available, the explicit block delims mode must respect those repcodes exactly, + * and cannot emit an RLE block that disagrees with the repcode history. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t -ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize, - const ZSTD_Sequence* inSeqs, size_t inSeqsSize, - const void* src, size_t srcSize); +ZSTD_compressSequences(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize); /*! ZSTD_compressSequencesAndLiterals() : @@ -1668,9 +1669,10 @@ ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize, * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t -ZSTD_compressSequencesAndLiterals( ZSTD_CCtx* cctx, void* dst, size_t dstSize, - const ZSTD_Sequence* inSeqs, size_t inSeqsSize, - const void* literals, size_t litSize); +ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* literals, size_t litSize); /*! ZSTD_writeSkippableFrame() : From 56cfb7816a5a627b39c03405e967cf67691974c4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 10 Dec 2024 16:54:53 -0800 Subject: [PATCH 224/405] codemod: ZSTD_paramSwitch_e -> ZSTD_ParamSwitch_e --- contrib/largeNbDicts/largeNbDicts.c | 2 +- doc/zstd_manual.html | 2 +- lib/compress/zstd_compress.c | 73 +++++++++++++++------------ lib/compress/zstd_compress_internal.h | 16 +++--- lib/compress/zstd_ldm.c | 2 +- lib/compress/zstd_ldm.h | 2 +- lib/zstd.h | 15 +++--- programs/benchzstd.h | 2 +- programs/fileio.c | 4 +- programs/fileio.h | 4 +- programs/fileio_types.h | 4 +- programs/zstdcli.c | 6 +-- 12 files changed, 71 insertions(+), 61 deletions(-) diff --git a/contrib/largeNbDicts/largeNbDicts.c b/contrib/largeNbDicts/largeNbDicts.c index eeaaf7182..6502f1227 100644 --- a/contrib/largeNbDicts/largeNbDicts.c +++ b/contrib/largeNbDicts/largeNbDicts.c @@ -1025,7 +1025,7 @@ int main (int argc, const char** argv) unsigned nbBlocks = 0; /* determine nbBlocks automatically, from source and blockSize */ ZSTD_dictContentType_e dictContentType = ZSTD_dct_auto; ZSTD_dictAttachPref_e dictAttachPref = ZSTD_dictDefaultAttach; - ZSTD_paramSwitch_e prefetchCDictTables = ZSTD_ps_auto; + ZSTD_ParamSwitch_e prefetchCDictTables = ZSTD_ps_auto; metricAggregatePref_e metricAggregatePref = fastest; for (int argNb = 1; argNb < argc ; argNb++) { diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index a780e97d9..f3fb75264 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1196,7 +1196,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); ZSTD_ps_auto = 0,
    /* Let the library automatically determine whether the feature shall be enabled */ ZSTD_ps_enable = 1, /* Force-enable the feature */ ZSTD_ps_disable = 2 /* Do not use the feature */ -} ZSTD_paramSwitch_e; +} ZSTD_ParamSwitch_e;

    Frame header and size functions

    
     
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 92f757b1b..2290fd869 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -87,7 +87,7 @@ struct ZSTD_CDict_s {
         ZSTD_customMem customMem;
         U32 dictID;
         int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
    -    ZSTD_paramSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use
    +    ZSTD_ParamSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use
                                                * row-based matchfinder. Unless the cdict is reloaded, we will use
                                                * the same greedy/lazy matchfinder at compression time.
                                                */
    @@ -228,13 +228,13 @@ static int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) {
     /* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder
      * for this compression.
      */
    -static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_paramSwitch_e mode) {
    +static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_ParamSwitch_e mode) {
         assert(mode != ZSTD_ps_auto);
         return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_ps_enable);
     }
     
     /* Returns row matchfinder usage given an initial mode and cParams */
    -static ZSTD_paramSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_paramSwitch_e mode,
    +static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode,
                                                              const ZSTD_compressionParameters* const cParams) {
     #if defined(ZSTD_ARCH_X86_SSE2) || defined(ZSTD_ARCH_ARM_NEON)
         int const kHasSIMD128 = 1;
    @@ -253,7 +253,7 @@ static ZSTD_paramSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_paramSwitch_e mode
     }
     
     /* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */
    -static ZSTD_paramSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_paramSwitch_e mode,
    +static ZSTD_ParamSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_ParamSwitch_e mode,
                                                             const ZSTD_compressionParameters* const cParams) {
         if (mode != ZSTD_ps_auto) return mode;
         return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable;
    @@ -261,7 +261,7 @@ static ZSTD_paramSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_paramSwitch_e mode,
     
     /* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */
     static int ZSTD_allocateChainTable(const ZSTD_strategy strategy,
    -                                   const ZSTD_paramSwitch_e useRowMatchFinder,
    +                                   const ZSTD_ParamSwitch_e useRowMatchFinder,
                                        const U32 forDDSDict) {
         assert(useRowMatchFinder != ZSTD_ps_auto);
         /* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate.
    @@ -274,7 +274,7 @@ static int ZSTD_allocateChainTable(const ZSTD_strategy strategy,
      * enable long distance matching (wlog >= 27, strategy >= btopt).
      * Returns ZSTD_ps_disable otherwise.
      */
    -static ZSTD_paramSwitch_e ZSTD_resolveEnableLdm(ZSTD_paramSwitch_e mode,
    +static ZSTD_ParamSwitch_e ZSTD_resolveEnableLdm(ZSTD_ParamSwitch_e mode,
                                      const ZSTD_compressionParameters* const cParams) {
         if (mode != ZSTD_ps_auto) return mode;
         return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable;
    @@ -293,7 +293,7 @@ static size_t ZSTD_resolveMaxBlockSize(size_t maxBlockSize) {
         }
     }
     
    -static ZSTD_paramSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_paramSwitch_e value, int cLevel) {
    +static ZSTD_ParamSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_ParamSwitch_e value, int cLevel) {
         if (value != ZSTD_ps_auto) return value;
         if (cLevel < 10) {
             return ZSTD_ps_disable;
    @@ -865,7 +865,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
         }
     
         case ZSTD_c_literalCompressionMode : {
    -        const ZSTD_paramSwitch_e lcm = (ZSTD_paramSwitch_e)value;
    +        const ZSTD_ParamSwitch_e lcm = (ZSTD_ParamSwitch_e)value;
             BOUNDCHECK(ZSTD_c_literalCompressionMode, (int)lcm);
             CCtxParams->literalCompressionMode = lcm;
             return CCtxParams->literalCompressionMode;
    @@ -921,7 +921,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
     
         case ZSTD_c_enableLongDistanceMatching :
             BOUNDCHECK(ZSTD_c_enableLongDistanceMatching, value);
    -        CCtxParams->ldmParams.enableLdm = (ZSTD_paramSwitch_e)value;
    +        CCtxParams->ldmParams.enableLdm = (ZSTD_ParamSwitch_e)value;
             return CCtxParams->ldmParams.enableLdm;
     
         case ZSTD_c_ldmHashLog :
    @@ -984,7 +984,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
     
         case ZSTD_c_splitAfterSequences:
             BOUNDCHECK(ZSTD_c_splitAfterSequences, value);
    -        CCtxParams->postBlockSplitter = (ZSTD_paramSwitch_e)value;
    +        CCtxParams->postBlockSplitter = (ZSTD_ParamSwitch_e)value;
             return CCtxParams->postBlockSplitter;
     
         case ZSTD_c_blockSplitterLevel:
    @@ -994,7 +994,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
     
         case ZSTD_c_useRowMatchFinder:
             BOUNDCHECK(ZSTD_c_useRowMatchFinder, value);
    -        CCtxParams->useRowMatchFinder = (ZSTD_paramSwitch_e)value;
    +        CCtxParams->useRowMatchFinder = (ZSTD_ParamSwitch_e)value;
             return CCtxParams->useRowMatchFinder;
     
         case ZSTD_c_deterministicRefPrefix:
    @@ -1004,7 +1004,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
     
         case ZSTD_c_prefetchCDictTables:
             BOUNDCHECK(ZSTD_c_prefetchCDictTables, value);
    -        CCtxParams->prefetchCDictTables = (ZSTD_paramSwitch_e)value;
    +        CCtxParams->prefetchCDictTables = (ZSTD_ParamSwitch_e)value;
             return CCtxParams->prefetchCDictTables;
     
         case ZSTD_c_enableSeqProducerFallback:
    @@ -1021,7 +1021,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
     
         case ZSTD_c_searchForExternalRepcodes:
             BOUNDCHECK(ZSTD_c_searchForExternalRepcodes, value);
    -        CCtxParams->searchForExternalRepcodes = (ZSTD_paramSwitch_e)value;
    +        CCtxParams->searchForExternalRepcodes = (ZSTD_ParamSwitch_e)value;
             return CCtxParams->searchForExternalRepcodes;
     
         default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
    @@ -1482,7 +1482,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
                                 unsigned long long srcSize,
                                 size_t dictSize,
                                 ZSTD_cParamMode_e mode,
    -                            ZSTD_paramSwitch_e useRowMatchFinder)
    +                            ZSTD_ParamSwitch_e useRowMatchFinder)
     {
         const U64 minSrcSize = 513; /* (1<<9) + 1 */
         const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
    @@ -1660,7 +1660,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
     
     static size_t
     ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
    -                       const ZSTD_paramSwitch_e useRowMatchFinder,
    +                       const ZSTD_ParamSwitch_e useRowMatchFinder,
                            const int enableDedicatedDictSearch,
                            const U32 forCCtx)
     {
    @@ -1711,7 +1711,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
             const ZSTD_compressionParameters* cParams,
             const ldmParams_t* ldmParams,
             const int isStatic,
    -        const ZSTD_paramSwitch_e useRowMatchFinder,
    +        const ZSTD_ParamSwitch_e useRowMatchFinder,
             const size_t buffInSize,
             const size_t buffOutSize,
             const U64 pledgedSrcSize,
    @@ -1763,7 +1763,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
     {
         ZSTD_compressionParameters const cParams =
                     ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
    -    ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,
    +    ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,
                                                                                    &cParams);
     
         RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
    @@ -1828,7 +1828,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
             size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)
                     ? ZSTD_compressBound(blockSize) + 1
                     : 0;
    -        ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, ¶ms->cParams);
    +        ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, ¶ms->cParams);
     
             return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
                 &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
    @@ -1993,7 +1993,7 @@ static size_t
     ZSTD_reset_matchState(ZSTD_MatchState_t* ms,
                           ZSTD_cwksp* ws,
                     const ZSTD_compressionParameters* cParams,
    -                const ZSTD_paramSwitch_e useRowMatchFinder,
    +                const ZSTD_ParamSwitch_e useRowMatchFinder,
                     const ZSTD_compResetPolicy_e crp,
                     const ZSTD_indexResetPolicy_e forceResetIndex,
                     const ZSTD_resetTarget_e forWho)
    @@ -3074,7 +3074,7 @@ ZSTD_entropyCompressSeqStore(
     /* ZSTD_selectBlockCompressor() :
      * Not static, but internal use only (used by long distance matcher)
      * assumption : strat is a valid strategy */
    -ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode)
    +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode)
     {
         static const ZSTD_BlockCompressor_f blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
             { ZSTD_compressBlock_fast  /* default for 0 */,
    @@ -3250,7 +3250,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,
                                        ZSTD_SequencePosition* seqPos,
                                  const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
                                  const void* src, size_t blockSize,
    -                                   ZSTD_paramSwitch_e externalRepSearch);
    +                                   ZSTD_ParamSwitch_e externalRepSearch);
     
     typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_BuildSeqStore_e;
     
    @@ -5591,7 +5591,7 @@ static size_t ZSTD_initCDict_internal(
     static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize,
                                           ZSTD_dictLoadMethod_e dictLoadMethod,
                                           ZSTD_compressionParameters cParams,
    -                                      ZSTD_paramSwitch_e useRowMatchFinder,
    +                                      ZSTD_ParamSwitch_e useRowMatchFinder,
                                           int enableDedicatedDictSearch,
                                           ZSTD_customMem customMem)
     {
    @@ -5746,7 +5746,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
                                      ZSTD_dictContentType_e dictContentType,
                                      ZSTD_compressionParameters cParams)
     {
    -    ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams);
    +    ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams);
         /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */
         size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0);
         size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
    @@ -6626,7 +6626,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,
                                        ZSTD_SequencePosition* seqPos,
                                  const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
                                  const void* src, size_t blockSize,
    -                                   ZSTD_paramSwitch_e externalRepSearch)
    +                                   ZSTD_ParamSwitch_e externalRepSearch)
     {
         U32 idx = seqPos->idx;
         U32 const startIdx = idx;
    @@ -6727,7 +6727,7 @@ ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,
                                    ZSTD_SequencePosition* seqPos,
                              const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
                              const void* src, size_t blockSize,
    -                               ZSTD_paramSwitch_e externalRepSearch)
    +                               ZSTD_ParamSwitch_e externalRepSearch)
     {
         U32 idx = seqPos->idx;
         U32 startPosInSequence = seqPos->posInSequence;
    @@ -6847,9 +6847,18 @@ ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,
         return bytesAdjustment;
     }
     
    -typedef size_t (*ZSTD_SequenceCopier_f) (ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos,
    -                                       const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
    -                                       const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
    +/* @seqPos represents a position within @inSeqs,
    + * it is read and updated by this function,
    + * once the goal to produce a block of size @blockSize is reached.
    + * @return: nb of bytes missing to reach @blockSize goal.
    + * so (@blockSize - @return) represents the nb of bytes ingested from @src.
    + */
    +typedef size_t (*ZSTD_SequenceCopier_f)(ZSTD_CCtx* cctx,
    +                                        ZSTD_SequencePosition* seqPos,
    +                                  const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
    +                                  const void* src, size_t blockSize,
    +                                        ZSTD_ParamSwitch_e externalRepSearch);
    +
     static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode)
     {
         assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode));
    @@ -6941,7 +6950,6 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
         while (remaining) {
             size_t compressedSeqsSize;
             size_t cBlockSize;
    -        size_t additionalByteAdjustment;
             size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters,
                                             cctx->blockSize, remaining,
                                             inSeqs, inSeqsSize, seqPos);
    @@ -6950,9 +6958,10 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
             assert(blockSize <= remaining);
             ZSTD_resetSeqStore(&cctx->seqStore);
     
    -        additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize, cctx->appliedParams.searchForExternalRepcodes);
    -        FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
    -        blockSize -= additionalByteAdjustment;
    +        {   size_t adjust = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize, cctx->appliedParams.searchForExternalRepcodes);
    +            FORWARD_IF_ERROR(adjust, "Bad sequence copy");
    +            blockSize -= adjust;
    +        }
     
             /* If blocks are too small, emit as a nocompress block */
             /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding
    diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
    index 8257607e0..dd43d597c 100644
    --- a/lib/compress/zstd_compress_internal.h
    +++ b/lib/compress/zstd_compress_internal.h
    @@ -247,7 +247,7 @@ typedef struct {
         U32  offCodeSumBasePrice;    /* to compare to log2(offreq)  */
         ZSTD_OptPrice_e priceType;   /* prices can be determined dynamically, or follow a pre-defined cost structure */
         const ZSTD_entropyCTables_t* symbolCosts;  /* pre-calculated dictionary statistics */
    -    ZSTD_paramSwitch_e literalCompressionMode;
    +    ZSTD_ParamSwitch_e literalCompressionMode;
     } optState_t;
     
     typedef struct {
    @@ -348,7 +348,7 @@ typedef struct {
     } ldmState_t;
     
     typedef struct {
    -    ZSTD_paramSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */
    +    ZSTD_ParamSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */
         U32 hashLog;            /* Log size of hashTable */
         U32 bucketSizeLog;      /* Log bucket size for collision resolution, at most 8 */
         U32 minMatchLength;     /* Minimum match length */
    @@ -379,7 +379,7 @@ struct ZSTD_CCtx_params_s {
                                     * There is no guarantee that hint is close to actual source size */
     
         ZSTD_dictAttachPref_e attachDictPref;
    -    ZSTD_paramSwitch_e literalCompressionMode;
    +    ZSTD_ParamSwitch_e literalCompressionMode;
     
         /* Multithreading: used to pass parameters to mtctx */
         int nbWorkers;
    @@ -411,14 +411,14 @@ struct ZSTD_CCtx_params_s {
          * then levels are sorted in increasing cpu budget, from 2 (fastest) to 6 (slowest).
          * Highest @preBlockSplitter_level combines well with @postBlockSplitter.
          */
    -    ZSTD_paramSwitch_e postBlockSplitter;
    +    ZSTD_ParamSwitch_e postBlockSplitter;
         int preBlockSplitter_level;
     
         /* Adjust the max block size*/
         size_t maxBlockSize;
     
         /* Param for deciding whether to use row-based matchfinder */
    -    ZSTD_paramSwitch_e useRowMatchFinder;
    +    ZSTD_ParamSwitch_e useRowMatchFinder;
     
         /* Always load a dictionary in ext-dict mode (not prefix mode)? */
         int deterministicRefPrefix;
    @@ -427,7 +427,7 @@ struct ZSTD_CCtx_params_s {
         ZSTD_customMem customMem;
     
         /* Controls prefetching in some dictMatchState matchfinders */
    -    ZSTD_paramSwitch_e prefetchCDictTables;
    +    ZSTD_ParamSwitch_e prefetchCDictTables;
     
         /* Controls whether zstd will fall back to an internal matchfinder
          * if the external matchfinder returns an error code. */
    @@ -440,7 +440,7 @@ struct ZSTD_CCtx_params_s {
         ZSTD_sequenceProducer_F extSeqProdFunc;
     
         /* Controls repcode search in external sequence parsing */
    -    ZSTD_paramSwitch_e searchForExternalRepcodes;
    +    ZSTD_ParamSwitch_e searchForExternalRepcodes;
     };  /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
     
     #define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
    @@ -582,7 +582,7 @@ typedef enum {
     typedef size_t (*ZSTD_BlockCompressor_f) (
             ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
             void const* src, size_t srcSize);
    -ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
    +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
     
     
     MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
    diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
    index 2b84c3027..42b38c0d0 100644
    --- a/lib/compress/zstd_ldm.c
    +++ b/lib/compress/zstd_ldm.c
    @@ -666,7 +666,7 @@ void ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes) {
     
     size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore,
         ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
    -    ZSTD_paramSwitch_e useRowMatchFinder,
    +    ZSTD_ParamSwitch_e useRowMatchFinder,
         void const* src, size_t srcSize)
     {
         const ZSTD_compressionParameters* const cParams = &ms->cParams;
    diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h
    index e43ab4e78..8efa7c4f0 100644
    --- a/lib/compress/zstd_ldm.h
    +++ b/lib/compress/zstd_ldm.h
    @@ -66,7 +66,7 @@ size_t ZSTD_ldm_generateSequences(
      */
     size_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore,
                 ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
    -            ZSTD_paramSwitch_e useRowMatchFinder,
    +            ZSTD_ParamSwitch_e useRowMatchFinder,
                 void const* src, size_t srcSize);
     
     /**
    diff --git a/lib/zstd.h b/lib/zstd.h
    index 08feed9a6..978f8cebd 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -1433,14 +1433,15 @@ typedef enum {
     } ZSTD_literalCompressionMode_e;
     
     typedef enum {
    -  /* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final
    -   * decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable
    -   * or ZSTD_ps_disable allow for a force enable/disable the feature.
    +  /* Note: This enum controls features which are conditionally beneficial.
    +   * Zstd can take a decision on whether or not to enable the feature (ZSTD_ps_auto),
    +   * but setting the switch to ZSTD_ps_enable or ZSTD_ps_disable force enable/disable the feature.
        */
       ZSTD_ps_auto = 0,         /* Let the library automatically determine whether the feature shall be enabled */
       ZSTD_ps_enable = 1,       /* Force-enable the feature */
       ZSTD_ps_disable = 2       /* Do not use the feature */
    -} ZSTD_paramSwitch_e;
    +} ZSTD_ParamSwitch_e;
    +#define ZSTD_paramSwitch_e ZSTD_ParamSwitch_e  /* old name */
     
     /***************************************
     *  Frame header and size functions
    @@ -2024,7 +2025,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
      * See the comments on that enum for an explanation of the feature. */
     #define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
     
    -/* Controlled with ZSTD_paramSwitch_e enum.
    +/* Controlled with ZSTD_ParamSwitch_e enum.
      * Default is ZSTD_ps_auto.
      * Set to ZSTD_ps_disable to never compress literals.
      * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals
    @@ -2215,7 +2216,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
     #define ZSTD_c_splitAfterSequences ZSTD_c_experimentalParam13
     
     /* ZSTD_c_useRowMatchFinder
    - * Controlled with ZSTD_paramSwitch_e enum.
    + * Controlled with ZSTD_ParamSwitch_e enum.
      * Default is ZSTD_ps_auto.
      * Set to ZSTD_ps_disable to never use row-based matchfinder.
      * Set to ZSTD_ps_enable to force usage of row-based matchfinder.
    @@ -2247,7 +2248,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
     #define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15
     
     /* ZSTD_c_prefetchCDictTables
    - * Controlled with ZSTD_paramSwitch_e enum. Default is ZSTD_ps_auto.
    + * Controlled with ZSTD_ParamSwitch_e enum. Default is ZSTD_ps_auto.
      *
      * In some situations, zstd uses CDict tables in-place rather than copying them
      * into the working context. (See docs on ZSTD_dictAttachPref_e above for details).
    diff --git a/programs/benchzstd.h b/programs/benchzstd.h
    index 6388d4d58..6ff62d43e 100644
    --- a/programs/benchzstd.h
    +++ b/programs/benchzstd.h
    @@ -109,7 +109,7 @@ typedef struct {
         int ldmHashLog;
         int ldmBucketSizeLog;
         int ldmHashRateLog;
    -    ZSTD_paramSwitch_e literalCompressionMode;
    +    ZSTD_ParamSwitch_e literalCompressionMode;
         int useRowMatchFinder;  /* use row-based matchfinder if possible */
     } BMK_advancedParams_t;
     
    diff --git a/programs/fileio.c b/programs/fileio.c
    index c6af36fbd..c2036b83c 100644
    --- a/programs/fileio.c
    +++ b/programs/fileio.c
    @@ -423,7 +423,7 @@ void FIO_setTestMode(FIO_prefs_t* const prefs, int testMode) {
     
     void FIO_setLiteralCompressionMode(
             FIO_prefs_t* const prefs,
    -        ZSTD_paramSwitch_e mode) {
    +        ZSTD_ParamSwitch_e mode) {
         prefs->literalCompressionMode = mode;
     }
     
    @@ -485,7 +485,7 @@ void FIO_setPassThroughFlag(FIO_prefs_t* const prefs, int value) {
         prefs->passThrough = (value != 0);
     }
     
    -void FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_paramSwitch_e value)
    +void FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_ParamSwitch_e value)
     {
         prefs->mmapDict = value;
     }
    diff --git a/programs/fileio.h b/programs/fileio.h
    index 224d89525..e8cb2e6ab 100644
    --- a/programs/fileio.h
    +++ b/programs/fileio.h
    @@ -95,7 +95,7 @@ void FIO_setSrcSizeHint(FIO_prefs_t* const prefs, size_t srcSizeHint);
     void FIO_setTestMode(FIO_prefs_t* const prefs, int testMode);
     void FIO_setLiteralCompressionMode(
             FIO_prefs_t* const prefs,
    -        ZSTD_paramSwitch_e mode);
    +        ZSTD_ParamSwitch_e mode);
     
     void FIO_setProgressSetting(FIO_progressSetting_e progressSetting);
     void FIO_setNotificationLevel(int level);
    @@ -106,7 +106,7 @@ void FIO_setContentSize(FIO_prefs_t* const prefs, int value);
     void FIO_displayCompressionParameters(const FIO_prefs_t* prefs);
     void FIO_setAsyncIOFlag(FIO_prefs_t* const prefs, int value);
     void FIO_setPassThroughFlag(FIO_prefs_t* const prefs, int value);
    -void FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_paramSwitch_e value);
    +void FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_ParamSwitch_e value);
     
     /* FIO_ctx_t functions */
     void FIO_setNbFilesTotal(FIO_ctx_t* const fCtx, int value);
    diff --git a/programs/fileio_types.h b/programs/fileio_types.h
    index 2994a6092..23bda4168 100644
    --- a/programs/fileio_types.h
    +++ b/programs/fileio_types.h
    @@ -53,7 +53,7 @@ typedef struct FIO_prefs_s {
         size_t targetCBlockSize;
         int srcSizeHint;
         int testMode;
    -    ZSTD_paramSwitch_e literalCompressionMode;
    +    ZSTD_ParamSwitch_e literalCompressionMode;
     
         /* IO preferences */
         int removeSrcFile;
    @@ -69,7 +69,7 @@ typedef struct FIO_prefs_s {
         int contentSize;
         int allowBlockDevices;
         int passThrough;
    -    ZSTD_paramSwitch_e mmapDict;
    +    ZSTD_ParamSwitch_e mmapDict;
     } FIO_prefs_t;
     
     typedef enum {FIO_mallocDict, FIO_mmapDict} FIO_dictBufferType_t;
    diff --git a/programs/zstdcli.c b/programs/zstdcli.c
    index 2a9a77624..9fa7e2275 100644
    --- a/programs/zstdcli.c
    +++ b/programs/zstdcli.c
    @@ -849,8 +849,8 @@ int main(int argCount, const char* argv[])
             ultra=0,
             contentSize=1,
             removeSrcFile=0;
    -    ZSTD_paramSwitch_e mmapDict=ZSTD_ps_auto;
    -    ZSTD_paramSwitch_e useRowMatchFinder = ZSTD_ps_auto;
    +    ZSTD_ParamSwitch_e mmapDict=ZSTD_ps_auto;
    +    ZSTD_ParamSwitch_e useRowMatchFinder = ZSTD_ps_auto;
         FIO_compressionType_t cType = FIO_zstdCompression;
         int nbWorkers = -1; /* -1 means unset */
         double compressibility = -1.0;  /* lorem ipsum generator */
    @@ -891,7 +891,7 @@ int main(int argCount, const char* argv[])
     #ifndef ZSTD_NOBENCH
         BMK_advancedParams_t benchParams = BMK_initAdvancedParams();
     #endif
    -    ZSTD_paramSwitch_e literalCompressionMode = ZSTD_ps_auto;
    +    ZSTD_ParamSwitch_e literalCompressionMode = ZSTD_ps_auto;
     
         /* init */
         checkLibVersion();
    
    From 4ef9d7d585e8892dacd3f954848b91cd5e773ff7 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Tue, 10 Dec 2024 17:07:19 -0800
    Subject: [PATCH 225/405] codemod: ZSTD_cParamMode_e -> ZSTD_CParamMode_e
    
    ---
     doc/zstd_manual.html                  |  6 ++--
     lib/compress/zstd_compress.c          | 40 ++++++++++++++++-----------
     lib/compress/zstd_compress_internal.h |  4 +--
     3 files changed, 29 insertions(+), 21 deletions(-)
    
    diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
    index f3fb75264..4cf72cb91 100644
    --- a/doc/zstd_manual.html
    +++ b/doc/zstd_manual.html
    @@ -1189,9 +1189,9 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
     } ZSTD_literalCompressionMode_e;
     

    typedef enum {
    -  /* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final
    -   * decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable
    -   * or ZSTD_ps_disable allow for a force enable/disable the feature.
    +  /* Note: This enum controls features which are conditionally beneficial.
    +   * Zstd can take a decision on whether or not to enable the feature (ZSTD_ps_auto),
    +   * but setting the switch to ZSTD_ps_enable or ZSTD_ps_disable force enable/disable the feature.
        */
       ZSTD_ps_auto = 0,         /* Let the library automatically determine whether the feature shall be enabled */
       ZSTD_ps_enable = 1,       /* Force-enable the feature */
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 2290fd869..4fcf32cfa 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -1474,14 +1474,14 @@ static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)
      *  optimize `cPar` for a specified input (`srcSize` and `dictSize`).
      *  mostly downsize to reduce memory consumption and initialization latency.
      * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
    - * `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`.
    + * `mode` is the mode for parameter adjustment. See docs for `ZSTD_CParamMode_e`.
      *  note : `srcSize==0` means 0!
      *  condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
     static ZSTD_compressionParameters
     ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
                                 unsigned long long srcSize,
                                 size_t dictSize,
    -                            ZSTD_cParamMode_e mode,
    +                            ZSTD_CParamMode_e mode,
                                 ZSTD_ParamSwitch_e useRowMatchFinder)
     {
         const U64 minSrcSize = 513; /* (1<<9) + 1 */
    @@ -1626,8 +1626,8 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
         return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto);
     }
     
    -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
    -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
    +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);
    +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);
     
     static void ZSTD_overrideCParams(
                   ZSTD_compressionParameters* cParams,
    @@ -1643,7 +1643,7 @@ static void ZSTD_overrideCParams(
     }
     
     ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
    -        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
    +        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)
     {
         ZSTD_compressionParameters cParams;
         if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
    @@ -5941,7 +5941,7 @@ size_t ZSTD_CStreamOutSize(void)
         return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
     }
     
    -static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)
    +static ZSTD_CParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)
     {
         if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))
             return ZSTD_cpm_attachDict;
    @@ -6326,6 +6326,11 @@ static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
         return 0;
     }
     
    +/*
    + * If @endOp == ZSTD_e_end, @inSize becomes pledgedSrcSize.
    + * Otherwise, it's ignored.
    + * @return: 0 on success, or a ZSTD_error code otherwise.
    + */
     static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
                                                  ZSTD_EndDirective endOp,
                                                  size_t inSize)
    @@ -6348,7 +6353,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
         {   size_t const dictSize = prefixDict.dict
                     ? prefixDict.dictSize
                     : (cctx->cdict ? cctx->cdict->dictContentSize : 0);
    -        ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1);
    +        ZSTD_CParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1);
             params.cParams = ZSTD_getCParamsFromCCtxParams(
                     ¶ms, cctx->pledgedSrcSizePlusOne-1,
                     dictSize, mode);
    @@ -7184,7 +7189,7 @@ static void ZSTD_dedicatedDictSearch_revertCParams(
         }
     }
     
    -static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
    +static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)
     {
         switch (mode) {
         case ZSTD_cpm_unknown:
    @@ -7208,8 +7213,8 @@ static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMo
      * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
      *  Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.
      *        Use dictSize == 0 for unknown or unused.
    - *  Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */
    -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
    + *  Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_CParamMode_e`. */
    +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)
     {
         U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);
         U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
    @@ -7247,7 +7252,9 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
      *  same idea as ZSTD_getCParams()
      * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
      *  Fields of `ZSTD_frameParameters` are set to default values */
    -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) {
    +static ZSTD_parameters
    +ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)
    +{
         ZSTD_parameters params;
         ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);
         DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
    @@ -7261,7 +7268,8 @@ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned lo
      *  same idea as ZSTD_getCParams()
      * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
      *  Fields of `ZSTD_frameParameters` are set to default values */
    -ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
    +ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
    +{
         if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
         return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
     }
    @@ -7269,8 +7277,8 @@ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeH
     void ZSTD_registerSequenceProducer(
         ZSTD_CCtx* zc,
         void* extSeqProdState,
    -    ZSTD_sequenceProducer_F extSeqProdFunc
    -) {
    +    ZSTD_sequenceProducer_F extSeqProdFunc)
    +{
         assert(zc != NULL);
         ZSTD_CCtxParams_registerSequenceProducer(
             &zc->requestedParams, extSeqProdState, extSeqProdFunc
    @@ -7280,8 +7288,8 @@ void ZSTD_registerSequenceProducer(
     void ZSTD_CCtxParams_registerSequenceProducer(
       ZSTD_CCtx_params* params,
       void* extSeqProdState,
    -  ZSTD_sequenceProducer_F extSeqProdFunc
    -) {
    +  ZSTD_sequenceProducer_F extSeqProdFunc)
    +{
         assert(params != NULL);
         if (extSeqProdFunc != NULL) {
             params->extSeqProdFunc = extSeqProdFunc;
    diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
    index dd43d597c..90d462fd2 100644
    --- a/lib/compress/zstd_compress_internal.h
    +++ b/lib/compress/zstd_compress_internal.h
    @@ -577,7 +577,7 @@ typedef enum {
                                      * behavior of taking both the source size and the dict size into account
                                      * when selecting and adjusting parameters.
                                      */
    -} ZSTD_cParamMode_e;
    +} ZSTD_CParamMode_e;
     
     typedef size_t (*ZSTD_BlockCompressor_f) (
             ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
    @@ -1542,7 +1542,7 @@ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);
      * Note: srcSizeHint == 0 means 0!
      */
     ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
    -        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
    +        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);
     
     /*! ZSTD_initCStream_internal() :
      *  Private use only. Init streaming operation.
    
    From 047db4f1f8e9d340e24b752323af17df1f0bb782 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Tue, 10 Dec 2024 17:51:20 -0800
    Subject: [PATCH 226/405] ZSTD_SequenceCopier_f no returns the nb of bytes
     consumed from input
    
    which feels much more natural
    ---
     doc/zstd_manual.html         |  4 +--
     lib/compress/zstd_compress.c | 51 ++++++++++++++++++------------------
     lib/zstd.h                   |  4 +--
     3 files changed, 30 insertions(+), 29 deletions(-)
    
    diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
    index 4cf72cb91..10546e938 100644
    --- a/doc/zstd_manual.html
    +++ b/doc/zstd_manual.html
    @@ -1315,8 +1315,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr,
     


    typedef enum {
    -  ZSTD_sf_noBlockDelimiters = 0,         /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
    -  ZSTD_sf_explicitBlockDelimiters = 1    /* Representation of ZSTD_Sequence contains explicit block delimiters */
    +  ZSTD_sf_noBlockDelimiters = 0,         /* ZSTD_Sequence[] has no block delimiters, just sequences */
    +  ZSTD_sf_explicitBlockDelimiters = 1    /* ZSTD_Sequence[] contains explicit block delimiters */
     } ZSTD_SequenceFormat_e;
     

    ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize);
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 4fcf32cfa..28ab04703 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -6624,7 +6624,7 @@ static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32
      * storing the sequences it reads, until it reaches a block delimiter.
      * Note that the block delimiter includes the last literals of the block.
      * @blockSize must be == sum(sequence_lengths).
    - * @returns 0 on success, and a ZSTD_error otherwise.
    + * @returns @blockSize on success, and a ZSTD_error otherwise.
      */
     static size_t
     ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,
    @@ -6711,21 +6711,19 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,
         }
         RETURN_ERROR_IF(ip != iend, externalSequences_invalid, "Blocksize doesn't agree with block delimiter!");
         seqPos->idx = idx+1;
    -    return 0;
    +    return blockSize;
     }
     
     /*
    - * This function attempts to scan through blockSize bytes
    + * This function attempts to scan through @blockSize bytes in @src
      * represented by the sequences in @inSeqs,
      * storing any (partial) sequences.
      *
    - * @returns the number of bytes to move the current read position back by.
    - * Only non-zero if we ended up splitting a sequence.
    - * Otherwise, it may return a ZSTD error if something went wrong.
    + * Occasionally, we may want to reduce the actual number of bytes consumed from @src
    + * to avoid splitting a match, notably if it would produce a match smaller than MINMATCH.
      *
    - * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
    - * avoid splitting a match, or to avoid splitting a match such that it would produce a match
    - * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
    + * @returns the number of bytes consumed from @src, necessarily <= @blockSize.
    + * Otherwise, it may return a ZSTD error if something went wrong.
      */
     static size_t
     ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,
    @@ -6738,8 +6736,9 @@ ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,
         U32 startPosInSequence = seqPos->posInSequence;
         U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
         size_t dictSize;
    -    BYTE const* ip = (BYTE const*)(src);
    -    BYTE const* iend = ip + blockSize;  /* May be adjusted if we decide to process fewer than blockSize bytes */
    +    const BYTE* const istart = (const BYTE*)(src);
    +    const BYTE* ip = istart;
    +    const BYTE* iend = istart + blockSize;  /* May be adjusted if we decide to process fewer than blockSize bytes */
         Repcodes_t updatedRepcodes;
         U32 bytesAdjustment = 0;
         U32 finalMatchSplit = 0;
    @@ -6842,21 +6841,20 @@ ZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,
         iend -= bytesAdjustment;
         if (ip != iend) {
             /* Store any last literals */
    -        U32 lastLLSize = (U32)(iend - ip);
    +        U32 const lastLLSize = (U32)(iend - ip);
             assert(ip <= iend);
             DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize);
             ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);
             seqPos->posInSrc += lastLLSize;
         }
     
    -    return bytesAdjustment;
    +    return (size_t)(iend-istart);
     }
     
     /* @seqPos represents a position within @inSeqs,
      * it is read and updated by this function,
      * once the goal to produce a block of size @blockSize is reached.
    - * @return: nb of bytes missing to reach @blockSize goal.
    - * so (@blockSize - @return) represents the nb of bytes ingested from @src.
    + * @return: nb of bytes consumed from @src, necessarily <= @blockSize.
      */
     typedef size_t (*ZSTD_SequenceCopier_f)(ZSTD_CCtx* cctx,
                                             ZSTD_SequencePosition* seqPos,
    @@ -6963,10 +6961,11 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
             assert(blockSize <= remaining);
             ZSTD_resetSeqStore(&cctx->seqStore);
     
    -        {   size_t adjust = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize, cctx->appliedParams.searchForExternalRepcodes);
    -            FORWARD_IF_ERROR(adjust, "Bad sequence copy");
    -            blockSize -= adjust;
    -        }
    +        blockSize = sequenceCopier(cctx,
    +                                   &seqPos, inSeqs, inSeqsSize,
    +                                   ip, blockSize,
    +                                   cctx->appliedParams.searchForExternalRepcodes);
    +        FORWARD_IF_ERROR(blockSize, "Bad sequence copy");
     
             /* If blocks are too small, emit as a nocompress block */
             /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding
    @@ -7054,13 +7053,13 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
     {
         BYTE* op = (BYTE*)dst;
         size_t cSize = 0;
    -    size_t compressedBlocksSize = 0;
         size_t frameHeaderSize = 0;
     
         /* Transparent initialization stage, same as compressStream2() */
         DEBUGLOG(4, "ZSTD_compressSequences (dstCapacity=%zu)", dstCapacity);
         assert(cctx != NULL);
         FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed");
    +
         /* Begin writing output, starting with frame header */
         frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID);
         op += frameHeaderSize;
    @@ -7069,14 +7068,16 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
         if (cctx->appliedParams.fParams.checksumFlag && srcSize) {
             XXH64_update(&cctx->xxhState, src, srcSize);
         }
    -    /* cSize includes block header size and compressed sequences size */
    -    compressedBlocksSize = ZSTD_compressSequences_internal(cctx,
    +
    +    {   size_t const cBlocksSize = ZSTD_compressSequences_internal(cctx,
                                                                op, dstCapacity,
                                                                inSeqs, inSeqsSize,
                                                                src, srcSize);
    -    FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!");
    -    cSize += compressedBlocksSize;
    -    dstCapacity -= compressedBlocksSize;
    +        FORWARD_IF_ERROR(cBlocksSize, "Compressing blocks failed!");
    +        cSize += cBlocksSize;
    +        assert(cBlocksSize <= dstCapacity);
    +        dstCapacity -= cBlocksSize;
    +    }
     
         if (cctx->appliedParams.fParams.checksumFlag) {
             U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
    diff --git a/lib/zstd.h b/lib/zstd.h
    index 978f8cebd..0318e6f9a 100644
    --- a/lib/zstd.h
    +++ b/lib/zstd.h
    @@ -1561,8 +1561,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSi
         ))
     
     typedef enum {
    -  ZSTD_sf_noBlockDelimiters = 0,         /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
    -  ZSTD_sf_explicitBlockDelimiters = 1    /* Representation of ZSTD_Sequence contains explicit block delimiters */
    +  ZSTD_sf_noBlockDelimiters = 0,         /* ZSTD_Sequence[] has no block delimiters, just sequences */
    +  ZSTD_sf_explicitBlockDelimiters = 1    /* ZSTD_Sequence[] contains explicit block delimiters */
     } ZSTD_SequenceFormat_e;
     #define ZSTD_sequenceFormat_e ZSTD_SequenceFormat_e /* old name */
     
    
    From bcb15091aa7edc7d945a002d2d947577d999d7ea Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Tue, 10 Dec 2024 18:24:18 -0800
    Subject: [PATCH 227/405] minor: more accurate variable scope
    
    ---
     lib/compress/zstd_compress.c | 18 +++++++++++-------
     1 file changed, 11 insertions(+), 7 deletions(-)
    
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 28ab04703..9675c75c0 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -6935,7 +6935,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
         size_t remaining = srcSize;
         ZSTD_SequencePosition seqPos = {0, 0, 0};
     
    -    BYTE const* ip = (BYTE const*)src;
    +    const BYTE* ip = (BYTE const*)src;
         BYTE* op = (BYTE*)dst;
         ZSTD_SequenceCopier_f const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
     
    @@ -6998,7 +6998,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
             if (!cctx->isFirstBlock &&
                 ZSTD_maybeRLE(&cctx->seqStore) &&
                 ZSTD_isRLE(ip, blockSize)) {
    -            /* We don't want to emit our first block as RLE even if it qualifies because
    +            /* Note: don't emit the first block as RLE even if it qualifies because
                  * doing so will cause the decoder (cli <= v1.4.3 only) to throw an (invalid) error
                  * "should consume all input error."
                  */
    @@ -7053,7 +7053,6 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
     {
         BYTE* op = (BYTE*)dst;
         size_t cSize = 0;
    -    size_t frameHeaderSize = 0;
     
         /* Transparent initialization stage, same as compressStream2() */
         DEBUGLOG(4, "ZSTD_compressSequences (dstCapacity=%zu)", dstCapacity);
    @@ -7061,14 +7060,18 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
         FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed");
     
         /* Begin writing output, starting with frame header */
    -    frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID);
    -    op += frameHeaderSize;
    -    dstCapacity -= frameHeaderSize;
    -    cSize += frameHeaderSize;
    +    {   size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity,
    +                    &cctx->appliedParams, srcSize, cctx->dictID);
    +        op += frameHeaderSize;
    +        assert(frameHeaderSize <= dstCapacity);
    +        dstCapacity -= frameHeaderSize;
    +        cSize += frameHeaderSize;
    +    }
         if (cctx->appliedParams.fParams.checksumFlag && srcSize) {
             XXH64_update(&cctx->xxhState, src, srcSize);
         }
     
    +    /* Now generate compressed blocks */
         {   size_t const cBlocksSize = ZSTD_compressSequences_internal(cctx,
                                                                op, dstCapacity,
                                                                inSeqs, inSeqsSize,
    @@ -7079,6 +7082,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx,
             dstCapacity -= cBlocksSize;
         }
     
    +    /* Complete with frame checksum, if needed */
         if (cctx->appliedParams.fParams.checksumFlag) {
             U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
             RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
    
    From 14a21e43b31042b8cd67d4a757920735a8d33d94 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Wed, 11 Dec 2024 14:31:09 -0800
    Subject: [PATCH 228/405] produced ZSTD_compressSequencesAndLiterals() as a
     separate pipeline
    
    only supports explicit delimiter mode, at least for the time being
    ---
     doc/zstd_manual.html         |  10 +-
     lib/compress/zstd_compress.c | 242 ++++++++++++++++++++++++++++++++++-
     lib/zstd.h                   |  10 +-
     3 files changed, 254 insertions(+), 8 deletions(-)
    
    diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
    index 10546e938..eed24a7a1 100644
    --- a/doc/zstd_manual.html
    +++ b/doc/zstd_manual.html
    @@ -1415,14 +1415,18 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx,
     ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
                           void* dst, size_t dstCapacity,
                     const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    -                const void* literals, size_t litSize);
    +                const void* literals, size_t litSize, size_t srcSize);
     

    This is a variant of ZSTD_compressSequences() which, instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), aka all literals already extracted and laid out into a single continuous buffer. This can be useful if the process generating the sequences also happens to generate the buffer of literals, thus skipping an extraction + caching stage. - To be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. - Important: Employing this prototype is incompatible with frame checksum. + It's essentially a speed optimization when the right conditions are met, + but it also includes so following limitations: + - Only supports explicit delimiter mode + - Not compatible with frame checksum, which must disabled + - Can fail when unable to compress sufficiently + Also, to be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. @return : final compressed size, or a ZSTD error code.


    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9675c75c0..d7ee68060 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -14,6 +14,7 @@ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */ #include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */ #include "../common/mem.h" +#include "../common/error_private.h" #include "hist.h" /* HIST_countFast_wksp */ #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ #include "../common/fse.h" @@ -4685,8 +4686,10 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, - const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID) -{ BYTE* const op = (BYTE*)dst; + const ZSTD_CCtx_params* params, + U64 pledgedSrcSize, U32 dictID) +{ + BYTE* const op = (BYTE*)dst; U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */ U32 const checksumFlag = params->fParams.checksumFlag>0; @@ -7095,6 +7098,241 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, return cSize; } +/* + * seqPos must end on an explicit block delimiter + * @blockSize must be exactly correct. + */ +static size_t +ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + size_t blockSize, + ZSTD_ParamSwitch_e externalRepSearch) +{ + U32 idx = seqPos->idx; + U32 const startIdx = idx; + Repcodes_t updatedRepcodes; + U32 dictSize; + size_t startPosInSrc = seqPos->posInSrc; + + DEBUGLOG(5, "ZSTD_transferSequencesOnly_wBlockDelim (blockSize = %zu)", blockSize); + + if (cctx->cdict) { + dictSize = (U32)cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = (U32)cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t)); + for (; idx < nbSequences && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) { + U32 const litLength = inSeqs[idx].litLength; + U32 const matchLength = inSeqs[idx].matchLength; + U32 offBase; + + if (externalRepSearch == ZSTD_ps_disable) { + offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset); + } else { + U32 const ll0 = (litLength == 0); + offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0); + ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); + } + + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); + seqPos->posInSrc += litLength + matchLength; + if (cctx->appliedParams.validateSequences) { + FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, + seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, + ZSTD_hasExtSeqProd(&cctx->appliedParams)), + "Sequence validation failed"); + } + RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); + } + + /* last sequence (only literals) */ + seqPos->posInSrc += inSeqs[idx].litLength; + + /* blockSize must be exactly correct (checked before calling this function) */ + assert((seqPos->posInSrc - startPosInSrc) == blockSize); (void)startPosInSrc; + + /* If we skipped repcode search while parsing, we need to update repcodes now */ + assert(externalRepSearch != ZSTD_ps_auto); + assert(idx >= startIdx); + if (externalRepSearch == ZSTD_ps_disable && idx != startIdx) { + U32* const rep = updatedRepcodes.rep; + U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */ + + if (lastSeqIdx >= startIdx + 2) { + rep[2] = inSeqs[lastSeqIdx - 2].offset; + rep[1] = inSeqs[lastSeqIdx - 1].offset; + rep[0] = inSeqs[lastSeqIdx].offset; + } else if (lastSeqIdx == startIdx + 1) { + rep[2] = rep[0]; + rep[1] = inSeqs[lastSeqIdx - 1].offset; + rep[0] = inSeqs[lastSeqIdx].offset; + } else { + assert(lastSeqIdx == startIdx); + rep[2] = rep[1]; + rep[1] = rep[0]; + rep[0] = inSeqs[lastSeqIdx].offset; + } + } + + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); + + seqPos->idx = idx+1; + return blockSize; +} + +static size_t +ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t nbSequences, + const void* literals, size_t litSize, size_t srcSize) +{ + size_t cSize = 0; + size_t remaining = srcSize; + ZSTD_SequencePosition seqPos = {0, 0, 0}; + BYTE* op = (BYTE*)dst; + + DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu", nbSequences, litSize); + if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { + RETURN_ERROR(GENERIC, "This mode is only compatible with explicit delimiters"); + } + + /* Special case: empty frame */ + if (remaining == 0) { + U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header"); + MEM_writeLE32(op, cBlockHeader24); + op += ZSTD_blockHeaderSize; + dstCapacity -= ZSTD_blockHeaderSize; + cSize += ZSTD_blockHeaderSize; + } + + while (remaining) { + size_t compressedSeqsSize; + size_t cBlockSize; + size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters, + cctx->blockSize, remaining, + inSeqs, nbSequences, seqPos); + U32 const lastBlock = (blockSize == remaining); + FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); + assert(blockSize <= remaining); + ZSTD_resetSeqStore(&cctx->seqStore); + + blockSize = ZSTD_transferSequencesOnly_wBlockDelim(cctx, + &seqPos, + inSeqs, nbSequences, + blockSize, + cctx->appliedParams.searchForExternalRepcodes); + FORWARD_IF_ERROR(blockSize, "Bad sequence copy"); + + /* Note: when blockSize is very small, other variant send it uncompressed. + * Here, we still send the sequences, because we don't have the source to send it uncompressed. + * In theory, it would be possible to reproduce the source from the sequences, + * but that's pretty complex and memory intensive, which goes against the principles of this variant. */ + + RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); + compressedSeqsSize = ZSTD_entropyCompressSeqStore_wExtLitBuffer( + op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, + literals, litSize, + blockSize, + &cctx->seqStore, + &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, + &cctx->appliedParams, + cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */, + cctx->bmi2); + FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); + DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); + + /* Note: difficult to check source for RLE block when only Literals are provided, + * but it could be considered from analyzing the sequence directly */ + + if (compressedSeqsSize == 0) { + /* Sending uncompressed blocks is difficult, because we don't have the source. + * In theory, we could use the sequences to regenerate the source, like a decompressor, + * but it's complex and likely overkill. + * Current outcome: generate an error code. + */ + RETURN_ERROR(dstSize_tooSmall, "Data is not compressible"); /* note: error code might be misleading */ + } else { + U32 cBlockHeader; + assert(compressedSeqsSize > 1); /* no RLE */ + /* Error checking and repcodes update */ + ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState); + if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + /* Write block header into beginning of block*/ + cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3); + MEM_writeLE24(op, cBlockHeader); + cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize; + DEBUGLOG(5, "Writing out compressed block, size: %zu", cBlockSize); + } + + cSize += cBlockSize; + + if (lastBlock) { + break; + } else { + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + cctx->isFirstBlock = 0; + } + DEBUGLOG(5, "cSize running total: %zu (remaining dstCapacity=%zu)", cSize, dstCapacity); + } + + DEBUGLOG(4, "cSize final total: %zu", cSize); + return cSize; +} + +size_t +ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* literals, size_t litSize, size_t srcSize) +{ + BYTE* op = (BYTE*)dst; + size_t cSize = 0; + + /* Transparent initialization stage, same as compressStream2() */ + DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)", dstCapacity); + assert(cctx != NULL); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); + + if (cctx->appliedParams.fParams.checksumFlag) { + RETURN_ERROR(frameParameter_unsupported, "this mode is incompatible with frame checksum"); + } + + /* Begin writing output, starting with frame header */ + { size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, + &cctx->appliedParams, srcSize, cctx->dictID); + op += frameHeaderSize; + assert(frameHeaderSize <= dstCapacity); + dstCapacity -= frameHeaderSize; + cSize += frameHeaderSize; + } + + /* Now generate compressed blocks */ + { size_t const cBlocksSize = ZSTD_compressSequencesAndLiterals_internal(cctx, + op, dstCapacity, + inSeqs, inSeqsSize, + literals, litSize, srcSize); + FORWARD_IF_ERROR(cBlocksSize, "Compressing blocks failed!"); + cSize += cBlocksSize; + assert(cBlocksSize <= dstCapacity); + dstCapacity -= cBlocksSize; + } + + DEBUGLOG(4, "Final compressed size: %zu", cSize); + return cSize; +} + /*====== Finalize ======*/ static ZSTD_inBuffer inBuffer_forEndFlush(const ZSTD_CStream* zcs) diff --git a/lib/zstd.h b/lib/zstd.h index 0318e6f9a..67cb4d987 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1665,15 +1665,19 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * aka all literals already extracted and laid out into a single continuous buffer. * This can be useful if the process generating the sequences also happens to generate the buffer of literals, * thus skipping an extraction + caching stage. - * To be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. - * Important: Employing this prototype is incompatible with frame checksum. + * It's essentially a speed optimization when the right conditions are met, + * but it also is restricted by the following limitations: + * - Only supports explicit delimiter mode + * - Not compatible with frame checksum, which must disabled + * - Can fail when unable to compress sufficiently + * Also, to be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t inSeqsSize, - const void* literals, size_t litSize); + const void* literals, size_t litSize, size_t srcSize); /*! ZSTD_writeSkippableFrame() : From 0b013b26884bb25149eedc6d78a5d8f5dc38739a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 11 Dec 2024 16:13:22 -0800 Subject: [PATCH 229/405] added unit tests to ZSTD_compressSequencesAndLiterals() seems to work as expected, correctly control that `litSize` and `srcSize` are exactly correct. --- doc/zstd_manual.html | 2 +- lib/compress/zstd_compress.c | 19 +++++-- lib/zstd.h | 7 ++- tests/fuzzer.c | 105 ++++++++++++++++++++++++++++++++++- 4 files changed, 122 insertions(+), 11 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index eed24a7a1..7cfeda22d 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1422,7 +1422,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, This can be useful if the process generating the sequences also happens to generate the buffer of literals, thus skipping an extraction + caching stage. It's essentially a speed optimization when the right conditions are met, - but it also includes so following limitations: + but it also is restricted by the following limitations: - Only supports explicit delimiter mode - Not compatible with frame checksum, which must disabled - Can fail when unable to compress sufficiently diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d7ee68060..bb92bd1ff 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7104,7 +7104,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, */ static size_t ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, + ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, ZSTD_ParamSwitch_e externalRepSearch) @@ -7114,6 +7114,7 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, Repcodes_t updatedRepcodes; U32 dictSize; size_t startPosInSrc = seqPos->posInSrc; + size_t litConsumed = 0; DEBUGLOG(5, "ZSTD_transferSequencesOnly_wBlockDelim (blockSize = %zu)", blockSize); @@ -7150,10 +7151,15 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); + litConsumed += litLength; } /* last sequence (only literals) */ - seqPos->posInSrc += inSeqs[idx].litLength; + { size_t const lastLitLength = inSeqs[idx].litLength; + seqPos->posInSrc += lastLitLength; + cctx->seqStore.lit += lastLitLength; /* register proper length */ + litConsumed += lastLitLength; + } /* blockSize must be exactly correct (checked before calling this function) */ assert((seqPos->posInSrc - startPosInSrc) == blockSize); (void)startPosInSrc; @@ -7184,6 +7190,7 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); seqPos->idx = idx+1; + *litConsumedPtr = litConsumed; return blockSize; } @@ -7214,21 +7221,23 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, } while (remaining) { - size_t compressedSeqsSize; - size_t cBlockSize; + size_t compressedSeqsSize, cBlockSize, litConsumed; size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters, cctx->blockSize, remaining, inSeqs, nbSequences, seqPos); U32 const lastBlock = (blockSize == remaining); FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); + RETURN_ERROR_IF(!lastBlock, GENERIC, "Only supports single block"); assert(blockSize <= remaining); ZSTD_resetSeqStore(&cctx->seqStore); blockSize = ZSTD_transferSequencesOnly_wBlockDelim(cctx, - &seqPos, + &seqPos, &litConsumed, inSeqs, nbSequences, blockSize, cctx->appliedParams.searchForExternalRepcodes); + RETURN_ERROR_IF(blockSize != remaining, GENERIC, "Must consume the entire block"); + RETURN_ERROR_IF(litConsumed != litSize, GENERIC, "Must consume the exact amount of literals provided"); FORWARD_IF_ERROR(blockSize, "Bad sequence copy"); /* Note: when blockSize is very small, other variant send it uncompressed. diff --git a/lib/zstd.h b/lib/zstd.h index 67cb4d987..3c0e836c9 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1666,17 +1666,18 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * This can be useful if the process generating the sequences also happens to generate the buffer of literals, * thus skipping an extraction + caching stage. * It's essentially a speed optimization when the right conditions are met, - * but it also is restricted by the following limitations: + * but it also features the following limitations: * - Only supports explicit delimiter mode + * - Supports 1 block only (max input 128 KB) * - Not compatible with frame checksum, which must disabled - * - Can fail when unable to compress sufficiently + * - Can fail (return an error) when input data cannot be compress sufficiently * Also, to be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, - const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const ZSTD_Sequence* inSeqs, size_t nbSequences, const void* literals, size_t litSize, size_t srcSize); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 2180d1edb..3063ec2d1 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -40,7 +40,6 @@ #include "datagen.h" /* RDG_genBuffer */ #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ #include "xxhash.h" /* XXH64 */ -#include "util.h" #include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */ /* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */ #include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */ @@ -339,6 +338,35 @@ static void FUZ_decodeSequences(BYTE* dst, ZSTD_Sequence* seqs, size_t seqsSize, } } +static size_t FUZ_getLitSize(const ZSTD_Sequence* seqs, size_t nbSeqs) +{ + size_t n, litSize = 0; + assert(seqs != NULL); + for (n=0; n Date: Thu, 12 Dec 2024 17:29:11 -0800 Subject: [PATCH 230/405] prepare fullbench for a refactor --- tests/Makefile | 3 +- tests/fullbench.c | 271 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 190 insertions(+), 84 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 5c0607d10..74e05774c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -148,6 +148,7 @@ fullbench32: CPPFLAGS += -m32 $(FULLBENCHS) : CPPFLAGS += $(MULTITHREAD_CPP) -Wno-deprecated-declarations $(FULLBENCHS) : LDFLAGS += $(MULTITHREAD_LD) $(FULLBENCHS) : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements +$(FULLBENCHS) : DEBUGLEVEL = 0 # turn off assert() for speed measurements $(FULLBENCHS) : $(ZSTD_FILES) $(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c $(LINK.c) $^ -o $@$(EXT) @@ -271,7 +272,7 @@ clean: #---------------------------------------------------------------------------------- # valgrind tests validated only for some posix platforms #---------------------------------------------------------------------------------- -UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname') +UNAME := $(shell sh -c 'MSYSTEM="MSYS" uname') ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS AIX CYGWIN_NT%,$(UNAME))) HOST_OS = POSIX diff --git a/tests/fullbench.c b/tests/fullbench.c index 250359e92..abc0a881d 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -18,7 +18,6 @@ #include /* fprintf, fopen, ftello64 */ #include -#include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */ #include "mem.h" /* U32 */ #ifndef ZSTD_DLL_IMPORT #include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, ZSTD_getcBlockSize, blockType_e, KB, MB */ @@ -36,7 +35,6 @@ #include "benchfn.h" /* CustomBench */ #include "benchzstd.h" /* MB_UNIT */ - /*_************************************ * Constants **************************************/ @@ -64,6 +62,7 @@ static const size_t kSampleSizeDefault = 10000000; #define CONTROL(c) { if (!(c)) { abort(); } } /* like assert(), but cannot be disabled */ + /*_************************************ * Benchmark Parameters **************************************/ @@ -97,7 +96,6 @@ static size_t BMK_findMaxMem(U64 requiredMem) *********************************************************/ static ZSTD_CCtx* g_zcc = NULL; - static size_t local_ZSTD_compress(const void* src, size_t srcSize, void* dst, size_t dstSize, @@ -129,40 +127,73 @@ local_ZSTD_compress_freshCCtx(const void* src, size_t srcSize, } } -static size_t g_cSize = 0; +typedef struct { + size_t prepSize; + size_t fixedOrigSize; +} PrepResult; + +static PrepResult prepDecompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +{ + size_t cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); + PrepResult r; + r.prepSize = cSize; + r.fixedOrigSize = srcSize; + return r; +} + static size_t local_ZSTD_decompress(const void* src, size_t srcSize, void* dst, size_t dstSize, - void* buff2) + void* unused) { - (void)src; (void)srcSize; - return ZSTD_decompress(dst, dstSize, buff2, g_cSize); + (void)unused; + return ZSTD_decompress(dst, dstSize, src, srcSize); } static ZSTD_DCtx* g_zdc = NULL; /* will be initialized within benchMem */ static size_t local_ZSTD_decompressDCtx(const void* src, size_t srcSize, void* dst, size_t dstSize, - void* buff2) + void* unused) { - (void)src; (void)srcSize; - return ZSTD_decompressDCtx(g_zdc, dst, dstSize, buff2, g_cSize); + (void)unused; + return ZSTD_decompressDCtx(g_zdc, dst, dstSize, src, srcSize); } #ifndef ZSTD_DLL_IMPORT +static PrepResult prepLiterals(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +{ + size_t frameHeaderSize; + size_t prepSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); + frameHeaderSize = ZSTD_frameHeaderSize(dst, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); + CONTROL(!ZSTD_isError(frameHeaderSize)); + /* check block is compressible, hence contains a literals section */ + { blockProperties_t bp; + ZSTD_getcBlockSize((char*)dst+frameHeaderSize, dstCapacity, &bp); /* Get 1st block type */ + if (bp.blockType != bt_compressed) { + const PrepResult r = {0,0}; + DISPLAY("no compressed literals\n"); + return r; + } } + { size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; + prepSize -= skippedSize; + memmove(dst, (char*)dst+skippedSize, prepSize); + } + ZSTD_decompressBegin(g_zdc); + { PrepResult r; + r.prepSize = prepSize; + r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + return r; + } +} + extern size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx, const void* src, size_t srcSize, void* dst, size_t dstCapacity); -static size_t local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) +static size_t +local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* unused) { - (void)src; (void)srcSize; (void)dst; (void)dstSize; - return ZSTD_decodeLiteralsBlock_wrapper(g_zdc, buff2, g_cSize, dst, dstSize); -} - -static size_t local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) -{ - int nbSeq; - (void)src; (void)srcSize; (void)dst; (void)dstSize; - return ZSTD_decodeSeqHeaders(g_zdc, &nbSeq, buff2, g_cSize); + (void)unused; + return ZSTD_decodeLiteralsBlock_wrapper(g_zdc, src, srcSize, dst, dstCapacity); } FORCE_NOINLINE size_t ZSTD_decodeLiteralsHeader(ZSTD_DCtx* dctx, void const* src, size_t srcSize) @@ -219,11 +250,55 @@ FORCE_NOINLINE size_t ZSTD_decodeLiteralsHeader(ZSTD_DCtx* dctx, void const* src return 0; } -static size_t local_ZSTD_decodeLiteralsHeader(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) +static size_t +local_ZSTD_decodeLiteralsHeader(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* unused) { - (void)dst, (void)dstSize, (void)src, (void)srcSize; - return ZSTD_decodeLiteralsHeader(g_zdc, buff2, g_cSize); + (void)dst; (void)dstCapacity; (void)unused; + return ZSTD_decodeLiteralsHeader(g_zdc, src, srcSize); } + +static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +{ + const BYTE* ip = dst; + const BYTE* iend; + { size_t const cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); + CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); + } + /* Skip frame Header */ + { size_t const frameHeaderSize = ZSTD_frameHeaderSize(dst, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); + CONTROL(!ZSTD_isError(frameHeaderSize)); + ip += frameHeaderSize; + } + /* Find end of block */ + { blockProperties_t bp; + size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstCapacity, &bp); /* Get 1st block type */ + if (bp.blockType != bt_compressed) { + const PrepResult r = {0,0}; + DISPLAY("No compressed sequences\n"); + return r; + } + iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ + } + ip += ZSTD_blockHeaderSize; /* skip block header */ + ZSTD_decompressBegin(g_zdc); + CONTROL(iend > ip); + ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dst, dstCapacity); /* skip literal segment */ + { PrepResult r; + r.prepSize = (size_t)(iend-ip); + r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + memmove(dst, ip, r.prepSize); /* copy rest of block (it starts by SeqHeader) */ + return r; + } +} + +static size_t +local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* unused) +{ + int nbSeq; + (void)unused; (void)dst; (void)dstCapacity; + return ZSTD_decodeSeqHeaders(g_zdc, &nbSeq, src, srcSize); +} + #endif static ZSTD_CStream* g_cstream= NULL; @@ -346,17 +421,17 @@ static ZSTD_DStream* g_dstream= NULL; static size_t local_ZSTD_decompressStream(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* unused) { ZSTD_outBuffer buffOut; ZSTD_inBuffer buffIn; - (void)src; (void)srcSize; + (void)unused; ZSTD_initDStream(g_dstream); buffOut.dst = dst; buffOut.size = dstCapacity; buffOut.pos = 0; - buffIn.src = buff2; - buffIn.size = g_cSize; + buffIn.src = src; + buffIn.size = srcSize; buffIn.pos = 0; ZSTD_decompressStream(g_dstream, &buffOut, &buffIn); return buffOut.pos; @@ -408,15 +483,15 @@ local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize, static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* unused) { size_t regeneratedSize = 0; - const BYTE* ip = (const BYTE*)buff2; - const BYTE* const iend = ip + g_cSize; + const BYTE* ip = (const BYTE*)src; + const BYTE* const iend = ip + srcSize; BYTE* op = (BYTE*)dst; size_t remainingCapacity = dstCapacity; - (void)src; (void)srcSize; /* unused */ + (void)unused; ZSTD_decompressBegin(g_zdc); while (ip < iend) { size_t const iSize = ZSTD_nextSrcSizeToDecompress(g_zdc); @@ -431,17 +506,61 @@ static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize, } #endif +static PrepResult prepCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +{ + const PrepResult r = { srcSize, srcSize}; + (void)cLevel; + assert(dstCapacity >= srcSize); + memcpy(dst, src, srcSize); + return r; +} + +/* if PrepFunction_f returns 0, benchmarking is cancelled */ +typedef PrepResult (*PrepFunction_f)(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel); +typedef size_t (*BenchedFunction_f)(const void* src, size_t srcSize, void* dst, size_t dstSize, void* opaque); + +typedef struct { + const char* name; + PrepFunction_f preparation_f; + BenchedFunction_f benchedFunction; +} BenchScenario; + +static BenchScenario kScenarios[] = { + { "compress", NULL, local_ZSTD_compress }, + { "decompress", prepDecompress, local_ZSTD_decompress }, + { "compress_freshCCtx", NULL, local_ZSTD_compress_freshCCtx }, + { "decompressDCtx", prepDecompress, local_ZSTD_decompressDCtx }, +#ifndef ZSTD_DLL_IMPORT + { "compressContinue", NULL, local_ZSTD_compressContinue }, + { "compressContinue_extDict", NULL, local_ZSTD_compressContinue_extDict }, + { "decompressContinue", prepDecompress, local_ZSTD_decompressContinue }, + { "decodeLiteralsHeader", NULL, local_ZSTD_decodeLiteralsHeader }, + { "decodeLiteralsBlock", NULL, local_ZSTD_decodeLiteralsBlock }, + { "decodeSeqHeaders", NULL, local_ZSTD_decodeSeqHeaders }, +#endif + { "compressStream", NULL, local_ZSTD_compressStream }, + { "decompressStream", prepDecompress, local_ZSTD_decompressStream }, + { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx }, + { "compress2", NULL, local_ZSTD_compress2 }, + { "compressStream2, end", NULL, local_ZSTD_compressStream2_end }, + { "compressStream2, end & short", NULL, local_ZSTD_compressStream2_end }, + { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue }, + { "compress_generic, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue }, + { "compress_generic, -T2, end", NULL, local_ZSTD_compress_generic_T2_end }, +}; +#define NB_SCENARIOS (sizeof(kScenarios) / sizeof(kScenarios[0])) /*_******************************************************* * Bench functions *********************************************************/ static int benchMem(unsigned benchNb, - const void* src, size_t srcSize, + const void* origSrc, size_t origSrcSize, int cLevel, ZSTD_compressionParameters cparams) { - size_t dstBuffSize = ZSTD_compressBound(srcSize); - BYTE* dstBuff; - void* dstBuff2; + size_t dstBuffCapacity = ZSTD_compressBound(origSrcSize); + void* dstBuff; + void* prepBuff; + size_t prepBuffCapacity=dstBuffCapacity, prepBuffSize; void* payload; const char* benchName; BMK_benchFn_t benchFunction; @@ -514,14 +633,14 @@ static int benchMem(unsigned benchNb, } /* Allocation */ - dstBuff = (BYTE*)malloc(dstBuffSize); - dstBuff2 = malloc(dstBuffSize); - if ((!dstBuff) || (!dstBuff2)) { + dstBuff = malloc(dstBuffCapacity); + prepBuff = malloc(prepBuffCapacity); + if ((!dstBuff) || (!prepBuff)) { DISPLAY("\nError: not enough memory!\n"); - free(dstBuff); free(dstBuff2); + free(dstBuff); free(prepBuff); return 12; } - payload = dstBuff2; + memcpy(prepBuff, origSrc, origSrcSize); prepBuffSize = origSrcSize; if (g_zcc==NULL) g_zcc = ZSTD_createCCtx(); if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); if (g_cstream==NULL) g_cstream = ZSTD_createCStream(); @@ -538,7 +657,7 @@ static int benchMem(unsigned benchNb, ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, (int)cparams.searchLog); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, (int)cparams.minMatch); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, (int)cparams.targetLength); - ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, cparams.strategy); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, (int)cparams.strategy); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, (int)cparams.windowLog); @@ -547,51 +666,42 @@ static int benchMem(unsigned benchNb, ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, (int)cparams.searchLog); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, (int)cparams.minMatch); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, (int)cparams.targetLength); - ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, cparams.strategy); + ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, (int)cparams.strategy); + /* Preparation */ + payload = &cparams; switch(benchNb) { - case 1: - payload = &cparams; - break; case 2: - g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); - break; - case 3: - payload = &cparams; + prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); break; case 4: - g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); + prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); break; #ifndef ZSTD_DLL_IMPORT - case 11: - payload = &cparams; - break; - case 12: - payload = &cparams; - break; case 13 : - g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); + prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); break; case 30: /* ZSTD_decodeLiteralsHeader */ /* fall-through */ - case 31: /* ZSTD_decodeLiteralsBlock : starts literals block in dstBuff2 */ + case 31: /* ZSTD_decodeLiteralsBlock : starts literals block in prepBuff */ { size_t frameHeaderSize; - g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); + prepBuffSize = ZSTD_compress(dstBuff, dstBuffCapacity, origSrc, origSrcSize, cLevel); frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); CONTROL(!ZSTD_isError(frameHeaderSize)); /* check block is compressible, hence contains a literals section */ { blockProperties_t bp; - ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */ + ZSTD_getcBlockSize((char*)dstBuff+frameHeaderSize, dstBuffCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n"); + DISPLAY("no compressed literals\n"); goto _cleanOut; } } { size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; - memcpy(dstBuff2, dstBuff+skippedSize, g_cSize-skippedSize); + prepBuffSize -= skippedSize; + memcpy(prepBuff, (char*)dstBuff+skippedSize, prepBuffSize); } - srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + origSrcSize = origSrcSize > 128 KB ? 128 KB : origSrcSize; /* speed relative to block */ ZSTD_decompressBegin(g_zdc); break; } @@ -599,7 +709,7 @@ static int benchMem(unsigned benchNb, { blockProperties_t bp; const BYTE* ip = dstBuff; const BYTE* iend; - { size_t const cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); + { size_t const cSize = ZSTD_compress(dstBuff, dstBuffCapacity, origSrc, origSrcSize, cLevel); CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); } /* Skip frame Header */ @@ -608,7 +718,7 @@ static int benchMem(unsigned benchNb, ip += frameHeaderSize; } /* Find end of block */ - { size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */ + { size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstBuffCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n"); goto _cleanOut; @@ -618,29 +728,23 @@ static int benchMem(unsigned benchNb, ip += ZSTD_blockHeaderSize; /* skip block header */ ZSTD_decompressBegin(g_zdc); CONTROL(iend > ip); - ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dstBuff, dstBuffSize); /* skip literal segment */ - g_cSize = (size_t)(iend-ip); - memcpy(dstBuff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */ - srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dstBuff, dstBuffCapacity); /* skip literal segment */ + prepBuffSize = (size_t)(iend-ip); + memcpy(prepBuff, ip, prepBuffSize); /* copy rest of block (it starts by SeqHeader) */ + origSrcSize = origSrcSize > 128 KB ? 128 KB : origSrcSize; /* speed relative to block */ break; } #else case 31: goto _cleanOut; #endif - case 41 : - payload = &cparams; - break; case 42 : - g_cSize = ZSTD_compress(payload, dstBuffSize, src, srcSize, cLevel); - break; - case 43 : - payload = &cparams; + prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); break; case 52 : /* compressStream2, short dstCapacity */ - dstBuffSize--; + dstBuffCapacity--; break; /* test functions */ @@ -650,11 +754,12 @@ static int benchMem(unsigned benchNb, } /* warming up dstBuff */ - { size_t i; for (i=0; i Date: Thu, 12 Dec 2024 17:50:14 -0800 Subject: [PATCH 231/405] refactor fullbench to make it easier to add new scenarios --- tests/fullbench.c | 186 ++++++++-------------------------------------- 1 file changed, 32 insertions(+), 154 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index abc0a881d..7f2e67b38 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -130,6 +130,7 @@ local_ZSTD_compress_freshCCtx(const void* src, size_t srcSize, typedef struct { size_t prepSize; size_t fixedOrigSize; + size_t moddedDstCapacity; /* if ==0, no modification */ } PrepResult; static PrepResult prepDecompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) @@ -138,6 +139,7 @@ static PrepResult prepDecompress(void* dst, size_t dstCapacity, const void* src, PrepResult r; r.prepSize = cSize; r.fixedOrigSize = srcSize; + r.moddedDstCapacity = 0; return r; } @@ -170,7 +172,7 @@ static PrepResult prepLiterals(void* dst, size_t dstCapacity, const void* src, s { blockProperties_t bp; ZSTD_getcBlockSize((char*)dst+frameHeaderSize, dstCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - const PrepResult r = {0,0}; + const PrepResult r = {0,0, 0}; DISPLAY("no compressed literals\n"); return r; } } @@ -182,6 +184,7 @@ static PrepResult prepLiterals(void* dst, size_t dstCapacity, const void* src, s { PrepResult r; r.prepSize = prepSize; r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + r.moddedDstCapacity = 0; return r; } } @@ -273,8 +276,8 @@ static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, { blockProperties_t bp; size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - const PrepResult r = {0,0}; - DISPLAY("No compressed sequences\n"); + const PrepResult r = {0,0, 0}; + DISPLAY("no compressed sequences\n"); return r; } iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ @@ -286,6 +289,7 @@ static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, { PrepResult r; r.prepSize = (size_t)(iend-ip); r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + r.moddedDstCapacity = 0; memmove(dst, ip, r.prepSize); /* copy rest of block (it starts by SeqHeader) */ return r; } @@ -508,7 +512,16 @@ static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize, static PrepResult prepCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) { - const PrepResult r = { srcSize, srcSize}; + const PrepResult r = { srcSize, srcSize, 0}; + (void)cLevel; + assert(dstCapacity >= srcSize); + memcpy(dst, src, srcSize); + return r; +} + +static PrepResult prepShorterDstCapacity(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +{ + const PrepResult r = { srcSize, srcSize, dstCapacity-1}; (void)cLevel; assert(dstCapacity >= srcSize); memcpy(dst, src, srcSize); @@ -534,16 +547,16 @@ static BenchScenario kScenarios[] = { { "compressContinue", NULL, local_ZSTD_compressContinue }, { "compressContinue_extDict", NULL, local_ZSTD_compressContinue_extDict }, { "decompressContinue", prepDecompress, local_ZSTD_decompressContinue }, - { "decodeLiteralsHeader", NULL, local_ZSTD_decodeLiteralsHeader }, - { "decodeLiteralsBlock", NULL, local_ZSTD_decodeLiteralsBlock }, - { "decodeSeqHeaders", NULL, local_ZSTD_decodeSeqHeaders }, + { "decodeLiteralsHeader", prepLiterals, local_ZSTD_decodeLiteralsHeader }, + { "decodeLiteralsBlock", prepLiterals, local_ZSTD_decodeLiteralsBlock }, + { "decodeSeqHeaders", prepSequences, local_ZSTD_decodeSeqHeaders }, #endif { "compressStream", NULL, local_ZSTD_compressStream }, { "decompressStream", prepDecompress, local_ZSTD_decompressStream }, { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx }, { "compress2", NULL, local_ZSTD_compress2 }, { "compressStream2, end", NULL, local_ZSTD_compressStream2_end }, - { "compressStream2, end & short", NULL, local_ZSTD_compressStream2_end }, + { "compressStream2, end & short", prepShorterDstCapacity, local_ZSTD_compressStream2_end }, { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue }, { "compress_generic, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue }, { "compress_generic, -T2, end", NULL, local_ZSTD_compress_generic_T2_end }, @@ -564,73 +577,15 @@ static int benchMem(unsigned benchNb, void* payload; const char* benchName; BMK_benchFn_t benchFunction; + PrepFunction_f prep_f; int errorcode = 0; - /* Selection */ - switch(benchNb) - { - case 1: - benchFunction = local_ZSTD_compress; benchName = "compress"; - break; - case 2: - benchFunction = local_ZSTD_decompress; benchName = "decompress"; - break; - case 3: - benchFunction = local_ZSTD_compress_freshCCtx; benchName = "compress_freshCCtx"; - break; - case 4: - benchFunction = local_ZSTD_decompressDCtx; benchName = "decompressDCtx"; - break; -#ifndef ZSTD_DLL_IMPORT - case 11: - benchFunction = local_ZSTD_compressContinue; benchName = "compressContinue"; - break; - case 12: - benchFunction = local_ZSTD_compressContinue_extDict; benchName = "compressContinue_extDict"; - break; - case 13: - benchFunction = local_ZSTD_decompressContinue; benchName = "decompressContinue"; - break; - case 30: - benchFunction = local_ZSTD_decodeLiteralsHeader; benchName = "decodeLiteralsHeader"; - break; - case 31: - benchFunction = local_ZSTD_decodeLiteralsBlock; benchName = "decodeLiteralsBlock"; - break; - case 32: - benchFunction = local_ZSTD_decodeSeqHeaders; benchName = "decodeSeqHeaders"; - break; -#endif - case 41: - benchFunction = local_ZSTD_compressStream; benchName = "compressStream"; - break; - case 42: - benchFunction = local_ZSTD_decompressStream; benchName = "decompressStream"; - break; - case 43: - benchFunction = local_ZSTD_compressStream_freshCCtx; benchName = "compressStream_freshCCtx"; - break; - case 50: - benchFunction = local_ZSTD_compress2; benchName = "compress2"; - break; - case 51: - benchFunction = local_ZSTD_compressStream2_end; benchName = "compressStream2, end"; - break; - case 52: - benchFunction = local_ZSTD_compressStream2_end; benchName = "compressStream2, end & short"; - break; - case 53: - benchFunction = local_ZSTD_compressStream2_continue; benchName = "compressStream2, continue"; - break; - case 61: - benchFunction = local_ZSTD_compress_generic_T2_continue; benchName = "compress_generic, -T2, continue"; - break; - case 62: - benchFunction = local_ZSTD_compress_generic_T2_end; benchName = "compress_generic, -T2, end"; - break; - default : - return 0; - } + if (benchNb >= NB_SCENARIOS) return 0; /* scenario doesn't exist */ + + benchName = kScenarios[benchNb].name; + benchFunction = kScenarios[benchNb].benchedFunction; + prep_f = kScenarios[benchNb].preparation_f; + if (prep_f == NULL) prep_f = prepCopy; /* default */ /* Allocation */ dstBuff = malloc(dstBuffCapacity); @@ -640,7 +595,6 @@ static int benchMem(unsigned benchNb, free(dstBuff); free(prepBuff); return 12; } - memcpy(prepBuff, origSrc, origSrcSize); prepBuffSize = origSrcSize; if (g_zcc==NULL) g_zcc = ZSTD_createCCtx(); if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); if (g_cstream==NULL) g_cstream = ZSTD_createCStream(); @@ -671,87 +625,11 @@ static int benchMem(unsigned benchNb, /* Preparation */ payload = &cparams; - switch(benchNb) - { - case 2: - prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); - break; - case 4: - prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); - break; -#ifndef ZSTD_DLL_IMPORT - case 13 : - prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); - break; - case 30: /* ZSTD_decodeLiteralsHeader */ - /* fall-through */ - case 31: /* ZSTD_decodeLiteralsBlock : starts literals block in prepBuff */ - { size_t frameHeaderSize; - prepBuffSize = ZSTD_compress(dstBuff, dstBuffCapacity, origSrc, origSrcSize, cLevel); - frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); - CONTROL(!ZSTD_isError(frameHeaderSize)); - /* check block is compressible, hence contains a literals section */ - { blockProperties_t bp; - ZSTD_getcBlockSize((char*)dstBuff+frameHeaderSize, dstBuffCapacity, &bp); /* Get 1st block type */ - if (bp.blockType != bt_compressed) { - DISPLAY("no compressed literals\n"); - goto _cleanOut; - } } - { size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; - prepBuffSize -= skippedSize; - memcpy(prepBuff, (char*)dstBuff+skippedSize, prepBuffSize); - } - origSrcSize = origSrcSize > 128 KB ? 128 KB : origSrcSize; /* speed relative to block */ - ZSTD_decompressBegin(g_zdc); - break; - } - case 32: /* ZSTD_decodeSeqHeaders */ - { blockProperties_t bp; - const BYTE* ip = dstBuff; - const BYTE* iend; - { size_t const cSize = ZSTD_compress(dstBuff, dstBuffCapacity, origSrc, origSrcSize, cLevel); - CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); - } - /* Skip frame Header */ - { size_t const frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); - CONTROL(!ZSTD_isError(frameHeaderSize)); - ip += frameHeaderSize; - } - /* Find end of block */ - { size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstBuffCapacity, &bp); /* Get 1st block type */ - if (bp.blockType != bt_compressed) { - DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n"); - goto _cleanOut; - } - iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ - } - ip += ZSTD_blockHeaderSize; /* skip block header */ - ZSTD_decompressBegin(g_zdc); - CONTROL(iend > ip); - ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dstBuff, dstBuffCapacity); /* skip literal segment */ - prepBuffSize = (size_t)(iend-ip); - memcpy(prepBuff, ip, prepBuffSize); /* copy rest of block (it starts by SeqHeader) */ - origSrcSize = origSrcSize > 128 KB ? 128 KB : origSrcSize; /* speed relative to block */ - break; - } -#else - case 31: - goto _cleanOut; -#endif - case 42 : - prepBuffSize = ZSTD_compress(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); - break; - - case 52 : - /* compressStream2, short dstCapacity */ - dstBuffCapacity--; - break; - - /* test functions */ - /* convention: test functions have ID > 100 */ - - default : ; + { PrepResult pr = prep_f(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); + prepBuffSize = pr.prepSize; + origSrcSize = pr.fixedOrigSize; } + if (prepBuffSize==0) goto _cleanOut; /* failed preparation */ /* warming up dstBuff */ { size_t i; for (i=0; i Date: Fri, 13 Dec 2024 00:14:24 -0800 Subject: [PATCH 232/405] minor: test reordering --- tests/fullbench.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 7f2e67b38..d64258977 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -132,14 +132,14 @@ typedef struct { size_t fixedOrigSize; size_t moddedDstCapacity; /* if ==0, no modification */ } PrepResult; +#define PREPRESULT_INIT { 0,0,0 } static PrepResult prepDecompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) { size_t cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); - PrepResult r; + PrepResult r = PREPRESULT_INIT; r.prepSize = cSize; r.fixedOrigSize = srcSize; - r.moddedDstCapacity = 0; return r; } @@ -172,7 +172,7 @@ static PrepResult prepLiterals(void* dst, size_t dstCapacity, const void* src, s { blockProperties_t bp; ZSTD_getcBlockSize((char*)dst+frameHeaderSize, dstCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - const PrepResult r = {0,0, 0}; + const PrepResult r = PREPRESULT_INIT; DISPLAY("no compressed literals\n"); return r; } } @@ -181,10 +181,9 @@ static PrepResult prepLiterals(void* dst, size_t dstCapacity, const void* src, s memmove(dst, (char*)dst+skippedSize, prepSize); } ZSTD_decompressBegin(g_zdc); - { PrepResult r; + { PrepResult r = PREPRESULT_INIT; r.prepSize = prepSize; r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ - r.moddedDstCapacity = 0; return r; } } @@ -276,7 +275,7 @@ static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, { blockProperties_t bp; size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - const PrepResult r = {0,0, 0}; + const PrepResult r = PREPRESULT_INIT; DISPLAY("no compressed sequences\n"); return r; } @@ -286,10 +285,9 @@ static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, ZSTD_decompressBegin(g_zdc); CONTROL(iend > ip); ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dst, dstCapacity); /* skip literal segment */ - { PrepResult r; + { PrepResult r = PREPRESULT_INIT; r.prepSize = (size_t)(iend-ip); r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ - r.moddedDstCapacity = 0; memmove(dst, ip, r.prepSize); /* copy rest of block (it starts by SeqHeader) */ return r; } @@ -543,23 +541,23 @@ static BenchScenario kScenarios[] = { { "decompress", prepDecompress, local_ZSTD_decompress }, { "compress_freshCCtx", NULL, local_ZSTD_compress_freshCCtx }, { "decompressDCtx", prepDecompress, local_ZSTD_decompressDCtx }, -#ifndef ZSTD_DLL_IMPORT { "compressContinue", NULL, local_ZSTD_compressContinue }, { "compressContinue_extDict", NULL, local_ZSTD_compressContinue_extDict }, { "decompressContinue", prepDecompress, local_ZSTD_decompressContinue }, - { "decodeLiteralsHeader", prepLiterals, local_ZSTD_decodeLiteralsHeader }, - { "decodeLiteralsBlock", prepLiterals, local_ZSTD_decodeLiteralsBlock }, - { "decodeSeqHeaders", prepSequences, local_ZSTD_decodeSeqHeaders }, -#endif { "compressStream", NULL, local_ZSTD_compressStream }, - { "decompressStream", prepDecompress, local_ZSTD_decompressStream }, { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx }, + { "decompressStream", prepDecompress, local_ZSTD_decompressStream }, { "compress2", NULL, local_ZSTD_compress2 }, { "compressStream2, end", NULL, local_ZSTD_compressStream2_end }, { "compressStream2, end & short", prepShorterDstCapacity, local_ZSTD_compressStream2_end }, { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue }, - { "compress_generic, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue }, - { "compress_generic, -T2, end", NULL, local_ZSTD_compress_generic_T2_end }, + { "compressStream2, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue }, + { "compressStream2, -T2, end", NULL, local_ZSTD_compress_generic_T2_end }, +#ifndef ZSTD_DLL_IMPORT + { "decodeLiteralsHeader (1st block)", prepLiterals, local_ZSTD_decodeLiteralsHeader }, + { "decodeLiteralsBlock (1st block)", prepLiterals, local_ZSTD_decodeLiteralsBlock }, + { "decodeSeqHeaders (1st block)", prepSequences, local_ZSTD_decodeSeqHeaders }, +#endif }; #define NB_SCENARIOS (sizeof(kScenarios) / sizeof(kScenarios[0])) @@ -622,12 +620,12 @@ static int benchMem(unsigned benchNb, ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, (int)cparams.targetLength); ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, (int)cparams.strategy); - /* Preparation */ payload = &cparams; { PrepResult pr = prep_f(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); prepBuffSize = pr.prepSize; origSrcSize = pr.fixedOrigSize; + if (pr.moddedDstCapacity) dstBuffCapacity = pr.moddedDstCapacity; } if (prepBuffSize==0) goto _cleanOut; /* failed preparation */ @@ -669,7 +667,7 @@ static int benchMem(unsigned benchNb, { BMK_runTime_t const newResult = BMK_extract_runTime(bOutcome); if (newResult.nanoSecPerRun < bestResult.nanoSecPerRun ) bestResult.nanoSecPerRun = newResult.nanoSecPerRun; - DISPLAY("\r%2u#%-29.29s:%8.1f MB/s (%8u) ", + DISPLAY("\r%2u#%-31.31s:%8.1f MB/s (%8u) ", benchNb, benchName, (double)origSrcSize * TIMELOOP_NANOSEC / bestResult.nanoSecPerRun / MB_UNIT, (unsigned)newResult.sumOfReturn ); From 8b7e1b795d50b69f44b5306511116251f60d1dda Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 13 Dec 2024 09:56:41 -0800 Subject: [PATCH 233/405] minor variable renaming --- tests/fullbench.c | 77 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index d64258977..3cc53713b 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -519,10 +519,8 @@ static PrepResult prepCopy(void* dst, size_t dstCapacity, const void* src, size_ static PrepResult prepShorterDstCapacity(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) { - const PrepResult r = { srcSize, srcSize, dstCapacity-1}; - (void)cLevel; - assert(dstCapacity >= srcSize); - memcpy(dst, src, srcSize); + PrepResult r = prepCopy(dst, dstCapacity, src, srcSize, cLevel); + r.moddedDstCapacity = dstCapacity - 1; return r; } @@ -564,33 +562,33 @@ static BenchScenario kScenarios[] = { /*_******************************************************* * Bench functions *********************************************************/ -static int benchMem(unsigned benchNb, +static int benchMem(unsigned scenarioID, const void* origSrc, size_t origSrcSize, int cLevel, ZSTD_compressionParameters cparams) { - size_t dstBuffCapacity = ZSTD_compressBound(origSrcSize); - void* dstBuff; + size_t dstCapacity = ZSTD_compressBound(origSrcSize); + void* dst; void* prepBuff; - size_t prepBuffCapacity=dstBuffCapacity, prepBuffSize; + size_t prepBuffCapacity=dstCapacity, prepBuffSize; void* payload; const char* benchName; BMK_benchFn_t benchFunction; PrepFunction_f prep_f; int errorcode = 0; - if (benchNb >= NB_SCENARIOS) return 0; /* scenario doesn't exist */ + if (scenarioID >= NB_SCENARIOS) return 0; /* scenario doesn't exist */ - benchName = kScenarios[benchNb].name; - benchFunction = kScenarios[benchNb].benchedFunction; - prep_f = kScenarios[benchNb].preparation_f; + benchName = kScenarios[scenarioID].name; + benchFunction = kScenarios[scenarioID].benchedFunction; + prep_f = kScenarios[scenarioID].preparation_f; if (prep_f == NULL) prep_f = prepCopy; /* default */ /* Allocation */ - dstBuff = malloc(dstBuffCapacity); + dst = malloc(dstCapacity); prepBuff = malloc(prepBuffCapacity); - if ((!dstBuff) || (!prepBuff)) { + if ((!dst) || (!prepBuff)) { DISPLAY("\nError: not enough memory!\n"); - free(dstBuff); free(prepBuff); + free(dst); free(prepBuff); return 12; } if (g_zcc==NULL) g_zcc = ZSTD_createCCtx(); @@ -625,16 +623,16 @@ static int benchMem(unsigned benchNb, { PrepResult pr = prep_f(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); prepBuffSize = pr.prepSize; origSrcSize = pr.fixedOrigSize; - if (pr.moddedDstCapacity) dstBuffCapacity = pr.moddedDstCapacity; + if (pr.moddedDstCapacity) dstCapacity = pr.moddedDstCapacity; } if (prepBuffSize==0) goto _cleanOut; /* failed preparation */ /* warming up dstBuff */ - { size_t i; for (i=0; i Date: Fri, 13 Dec 2024 16:23:54 -0800 Subject: [PATCH 234/405] fullbench: preparation functions are now in charge of allocating buffers --- tests/fullbench.c | 119 +++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 49 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 3cc53713b..7218bd6e6 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -128,18 +128,26 @@ local_ZSTD_compress_freshCCtx(const void* src, size_t srcSize, } typedef struct { + void* prepBuffer; size_t prepSize; - size_t fixedOrigSize; - size_t moddedDstCapacity; /* if ==0, no modification */ + void* dst; + size_t dstCapacity; + size_t fixedOrigSize; /* optional, 0 means "no modification" */ } PrepResult; -#define PREPRESULT_INIT { 0,0,0 } +#define PREPRESULT_INIT { NULL, 0, NULL, 0, 0 } -static PrepResult prepDecompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +static PrepResult prepDecompress(const void* src, size_t srcSize, int cLevel) { - size_t cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); + size_t prepCapacity = ZSTD_compressBound(srcSize); + void* prepBuffer = malloc(prepCapacity); + size_t cSize = ZSTD_compress(prepBuffer, prepCapacity, src, srcSize, cLevel); + void* dst = malloc(srcSize); PrepResult r = PREPRESULT_INIT; + assert(dst != NULL); + r.prepBuffer = prepBuffer; r.prepSize = cSize; - r.fixedOrigSize = srcSize; + r.dst = dst; + r.dstCapacity = srcSize; return r; } @@ -162,30 +170,35 @@ static size_t local_ZSTD_decompressDCtx(const void* src, size_t srcSize, #ifndef ZSTD_DLL_IMPORT -static PrepResult prepLiterals(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +static PrepResult prepLiterals(const void* src, size_t srcSize, int cLevel) { - size_t frameHeaderSize; + PrepResult r = PREPRESULT_INIT; + size_t dstCapacity = srcSize; + void* dst = malloc(dstCapacity); + void* prepBuffer; size_t prepSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); - frameHeaderSize = ZSTD_frameHeaderSize(dst, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); + size_t frameHeaderSize = ZSTD_frameHeaderSize(dst, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); CONTROL(!ZSTD_isError(frameHeaderSize)); /* check block is compressible, hence contains a literals section */ { blockProperties_t bp; ZSTD_getcBlockSize((char*)dst+frameHeaderSize, dstCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - const PrepResult r = PREPRESULT_INIT; DISPLAY("no compressed literals\n"); return r; } } { size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; prepSize -= skippedSize; - memmove(dst, (char*)dst+skippedSize, prepSize); + prepBuffer = malloc(prepSize); + CONTROL(prepBuffer != NULL); + memmove(prepBuffer, (char*)dst+skippedSize, prepSize); } ZSTD_decompressBegin(g_zdc); - { PrepResult r = PREPRESULT_INIT; - r.prepSize = prepSize; - r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ - return r; - } + r.prepBuffer = prepBuffer; + r.prepSize = prepSize; + r.dst = dst; + r.dstCapacity = dstCapacity; + r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + return r; } extern size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx, @@ -259,8 +272,11 @@ local_ZSTD_decodeLiteralsHeader(const void* src, size_t srcSize, void* dst, size return ZSTD_decodeLiteralsHeader(g_zdc, src, srcSize); } -static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +static PrepResult prepSequences(const void* src, size_t srcSize, int cLevel) { + PrepResult r = PREPRESULT_INIT; + size_t const dstCapacity = srcSize; + void* dst = malloc(dstCapacity); const BYTE* ip = dst; const BYTE* iend; { size_t const cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel); @@ -275,7 +291,6 @@ static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, { blockProperties_t bp; size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstCapacity, &bp); /* Get 1st block type */ if (bp.blockType != bt_compressed) { - const PrepResult r = PREPRESULT_INIT; DISPLAY("no compressed sequences\n"); return r; } @@ -285,12 +300,14 @@ static PrepResult prepSequences(void* dst, size_t dstCapacity, const void* src, ZSTD_decompressBegin(g_zdc); CONTROL(iend > ip); ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dst, dstCapacity); /* skip literal segment */ - { PrepResult r = PREPRESULT_INIT; - r.prepSize = (size_t)(iend-ip); - r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ - memmove(dst, ip, r.prepSize); /* copy rest of block (it starts by SeqHeader) */ - return r; - } + r.prepSize = (size_t)(iend-ip); + r.prepBuffer = malloc(r.prepSize); + CONTROL(r.prepBuffer != NULL); + memmove(r.prepBuffer, ip, r.prepSize); /* copy rest of block (it starts by SeqHeader) */ + r.dst = dst; + r.dstCapacity = dstCapacity; + r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ + return r; } static size_t @@ -508,24 +525,33 @@ static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize, } #endif -static PrepResult prepCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +static PrepResult prepCopy(const void* src, size_t srcSize, int cLevel) { - const PrepResult r = { srcSize, srcSize, 0}; - (void)cLevel; - assert(dstCapacity >= srcSize); - memcpy(dst, src, srcSize); + PrepResult r = PREPRESULT_INIT; + r.prepSize = srcSize; + r.prepBuffer = malloc(srcSize); + CONTROL(r.prepBuffer != NULL); + memcpy(r.prepBuffer, src, srcSize); + r.dstCapacity = ZSTD_compressBound(srcSize); + r.dst = malloc(r.dstCapacity); + CONTROL(r.dst != NULL); return r; } -static PrepResult prepShorterDstCapacity(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel) +static PrepResult prepShorterDstCapacity(const void* src, size_t srcSize, int cLevel) { - PrepResult r = prepCopy(dst, dstCapacity, src, srcSize, cLevel); - r.moddedDstCapacity = dstCapacity - 1; + PrepResult r = prepCopy(src, srcSize, cLevel); + assert(r.dstCapacity > 1); + r.dstCapacity -= 1; return r; } +/*_******************************************************* +* List of Scenarios +*********************************************************/ + /* if PrepFunction_f returns 0, benchmarking is cancelled */ -typedef PrepResult (*PrepFunction_f)(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int cLevel); +typedef PrepResult (*PrepFunction_f)(const void* src, size_t srcSize, int cLevel); typedef size_t (*BenchedFunction_f)(const void* src, size_t srcSize, void* dst, size_t dstSize, void* opaque); typedef struct { @@ -560,16 +586,16 @@ static BenchScenario kScenarios[] = { #define NB_SCENARIOS (sizeof(kScenarios) / sizeof(kScenarios[0])) /*_******************************************************* -* Bench functions +* Bench loop *********************************************************/ static int benchMem(unsigned scenarioID, const void* origSrc, size_t origSrcSize, int cLevel, ZSTD_compressionParameters cparams) { - size_t dstCapacity = ZSTD_compressBound(origSrcSize); - void* dst; - void* prepBuff; - size_t prepBuffCapacity=dstCapacity, prepBuffSize; + size_t dstCapacity = 0; + void* dst = NULL; + void* prepBuff = NULL; + size_t prepBuffSize = 0; void* payload; const char* benchName; BMK_benchFn_t benchFunction; @@ -583,14 +609,7 @@ static int benchMem(unsigned scenarioID, prep_f = kScenarios[scenarioID].preparation_f; if (prep_f == NULL) prep_f = prepCopy; /* default */ - /* Allocation */ - dst = malloc(dstCapacity); - prepBuff = malloc(prepBuffCapacity); - if ((!dst) || (!prepBuff)) { - DISPLAY("\nError: not enough memory!\n"); - free(dst); free(prepBuff); - return 12; - } + /* Initialization */ if (g_zcc==NULL) g_zcc = ZSTD_createCCtx(); if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); if (g_cstream==NULL) g_cstream = ZSTD_createCStream(); @@ -620,10 +639,12 @@ static int benchMem(unsigned scenarioID, /* Preparation */ payload = &cparams; - { PrepResult pr = prep_f(prepBuff, prepBuffCapacity, origSrc, origSrcSize, cLevel); + { PrepResult pr = prep_f(origSrc, origSrcSize, cLevel); + dst = pr.dst; + dstCapacity = pr.dstCapacity; + prepBuff = pr.prepBuffer; prepBuffSize = pr.prepSize; - origSrcSize = pr.fixedOrigSize; - if (pr.moddedDstCapacity) dstCapacity = pr.moddedDstCapacity; + if (pr.fixedOrigSize) origSrcSize = pr.fixedOrigSize; } if (prepBuffSize==0) goto _cleanOut; /* failed preparation */ From 8ab04097ed9736923405e4928f928e49654e2c9a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 13 Dec 2024 17:22:19 -0800 Subject: [PATCH 235/405] add the compressSequences() benchmark scenario --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_compress_internal.h | 8 ----- lib/zstd.h | 6 ++-- tests/fullbench.c | 52 ++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bb92bd1ff..5aad13531 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7058,7 +7058,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, size_t cSize = 0; /* Transparent initialization stage, same as compressStream2() */ - DEBUGLOG(4, "ZSTD_compressSequences (dstCapacity=%zu)", dstCapacity); + DEBUGLOG(4, "ZSTD_compressSequences (nbSeqs=%zu,dstCapacity=%zu)", inSeqsSize, dstCapacity); assert(cctx != NULL); FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 90d462fd2..294835946 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -741,14 +741,6 @@ ZSTD_storeSeqOnly(SeqStore_t* seqStorePtr, U32 offBase, size_t matchLength) { -#if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6) - static const BYTE* g_start = NULL; - if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */ - { U32 const pos = (U32)((const BYTE*)literals - g_start); - DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offBase%7u", - pos, (U32)litLength, (U32)matchLength, (U32)offBase); - } -#endif assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq); /* update seqStorePtr->lit, so that we know how many literals were or will be copied */ assert(seqStorePtr->maxNbLit <= 128 KB); diff --git a/lib/zstd.h b/lib/zstd.h index 3c0e836c9..435fe34d4 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1328,7 +1328,7 @@ typedef struct { * * Note: This field is optional. ZSTD_generateSequences() will calculate the value of * 'rep', but repeat offsets do not necessarily need to be calculated from an external - * sequence provider's perspective. For example, ZSTD_compressSequences() does not + * sequence provider perspective. For example, ZSTD_compressSequences() does not * use this 'rep' field at all (as of now). */ } ZSTD_Sequence; @@ -1588,7 +1588,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize); * @param zc The compression context to be used for ZSTD_compress2(). Set any * compression parameters you need on this context. * @param outSeqs The output sequences buffer of size @p outSeqsSize - * @param outSeqsSize The size of the output sequences buffer. + * @param outSeqsCapacity The size of the output sequences buffer. * ZSTD_sequenceBound(srcSize) is an upper bound on the number * of sequences that can be generated. * @param src The source buffer to generate sequences from of size @p srcSize. @@ -1606,7 +1606,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize); ZSTD_DEPRECATED("For debugging only, will be replaced by ZSTD_extractSequences()") ZSTDLIB_STATIC_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, - ZSTD_Sequence* outSeqs, size_t outSeqsSize, + ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, const void* src, size_t srcSize); /*! ZSTD_mergeBlockDelimiters() : diff --git a/tests/fullbench.c b/tests/fullbench.c index 7218bd6e6..ff512149a 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -12,6 +12,7 @@ /*_************************************ * Includes **************************************/ +#include #define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still bench some deprecated functions */ #include "util.h" /* Compiler options, UTIL_GetFileSize */ #include /* malloc */ @@ -272,7 +273,7 @@ local_ZSTD_decodeLiteralsHeader(const void* src, size_t srcSize, void* dst, size return ZSTD_decodeLiteralsHeader(g_zdc, src, srcSize); } -static PrepResult prepSequences(const void* src, size_t srcSize, int cLevel) +static PrepResult prepSequences1stBlock(const void* src, size_t srcSize, int cLevel) { PrepResult r = PREPRESULT_INIT; size_t const dstCapacity = srcSize; @@ -456,7 +457,6 @@ local_ZSTD_decompressStream(const void* src, size_t srcSize, return buffOut.pos; } -#ifndef ZSTD_DLL_IMPORT static size_t local_ZSTD_compressContinue(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* payload) @@ -523,11 +523,54 @@ static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize, return regeneratedSize; } -#endif + +static PrepResult prepSequences(const void* src, size_t srcSize, int cLevel) +{ + PrepResult r = PREPRESULT_INIT; + size_t const dstCapacity = ZSTD_compressBound(srcSize); + void* const dst = malloc(dstCapacity); + size_t const prepCapacity = dstCapacity * 4; + void* prepBuffer = malloc(prepCapacity); + void* sequencesStart = (char*)prepBuffer + 2*sizeof(unsigned); + ZSTD_Sequence* const seqs = sequencesStart; + size_t const seqsCapacity = prepCapacity / sizeof(ZSTD_Sequence); + size_t nbSeqs; + ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel); + nbSeqs = ZSTD_generateSequences(g_zcc, seqs, seqsCapacity, src, srcSize); + CONTROL(srcSize < UINT_MAX); + MEM_write32(prepBuffer, (U32)srcSize); + MEM_write32((char*)prepBuffer+4, (U32)nbSeqs); + memcpy(seqs + nbSeqs, src, srcSize); + r.prepBuffer = prepBuffer; + r.prepSize = 8 + sizeof(ZSTD_Sequence)*nbSeqs + srcSize; + r.dst = dst; + r.dstCapacity = dstCapacity; + return r; +} + +static size_t local_compressSequences(const void* input, size_t inputSize, + void* dst, size_t dstCapacity, + void* payload) +{ + const char* ip = input; + size_t srcSize = MEM_read32(ip); + size_t nbSeqs = MEM_read32(ip+=4); + const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4); + const void* src = (ip+=nbSeqs * sizeof(ZSTD_Sequence)); + ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); + assert(8 + nbSeqs * sizeof(ZSTD_Sequence) + srcSize == inputSize); (void)inputSize; + (void)payload; + + return ZSTD_compressSequences(g_zcc, dst, dstCapacity, seqs, nbSeqs, src, srcSize); +} + static PrepResult prepCopy(const void* src, size_t srcSize, int cLevel) { PrepResult r = PREPRESULT_INIT; + (void)cLevel; r.prepSize = srcSize; r.prepBuffer = malloc(srcSize); CONTROL(r.prepBuffer != NULL); @@ -577,10 +620,11 @@ static BenchScenario kScenarios[] = { { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue }, { "compressStream2, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue }, { "compressStream2, -T2, end", NULL, local_ZSTD_compress_generic_T2_end }, + { "compressSequences", prepSequences, local_compressSequences }, #ifndef ZSTD_DLL_IMPORT { "decodeLiteralsHeader (1st block)", prepLiterals, local_ZSTD_decodeLiteralsHeader }, { "decodeLiteralsBlock (1st block)", prepLiterals, local_ZSTD_decodeLiteralsBlock }, - { "decodeSeqHeaders (1st block)", prepSequences, local_ZSTD_decodeSeqHeaders }, + { "decodeSeqHeaders (1st block)", prepSequences1stBlock, local_ZSTD_decodeSeqHeaders }, #endif }; #define NB_SCENARIOS (sizeof(kScenarios) / sizeof(kScenarios[0])) From ac05ea89a5e87cf9e9756790f08b9d21b349fd9e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 14 Dec 2024 12:34:26 -0800 Subject: [PATCH 236/405] fullbench: switch default generator to lorem ipsum which creates more "realistic" scenarios than former compressible noise. The legacy data generator remains accessible, it is triggered when requesting an explicit compressibility factor (-P#). --- tests/Makefile | 4 ++-- tests/fullbench.c | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 74e05774c..c10d66f53 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -150,12 +150,12 @@ $(FULLBENCHS) : LDFLAGS += $(MULTITHREAD_LD) $(FULLBENCHS) : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements $(FULLBENCHS) : DEBUGLEVEL = 0 # turn off assert() for speed measurements $(FULLBENCHS) : $(ZSTD_FILES) -$(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c +$(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c $(LINK.c) $^ -o $@$(EXT) CLEAN += fullbench-lib fullbench-lib : CPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(LIB_SRCDIR)/libzstd.a fullbench.c +fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(LIB_SRCDIR)/libzstd.a fullbench.c $(LINK.c) $^ -o $@$(EXT) # note : broken : requires symbols unavailable from dynamic library diff --git a/tests/fullbench.c b/tests/fullbench.c index ff512149a..889761ef4 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -33,6 +33,7 @@ #include "zstd.h" /* ZSTD_versionString */ #include "util.h" /* time functions */ #include "datagen.h" +#include "lorem.h" #include "benchfn.h" /* CustomBench */ #include "benchzstd.h" /* MB_UNIT */ @@ -50,7 +51,7 @@ #define DEFAULT_CLEVEL 1 -#define COMPRESSIBILITY_DEFAULT 0.50 +#define COMPRESSIBILITY_DEFAULT (-1.0) static const size_t kSampleSizeDefault = 10000000; #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ @@ -754,6 +755,11 @@ _cleanOut: #define BENCH_ALL_SCENARIOS 999 +/* + * if @compressibility < 0.0, use Lorem Ipsum generator + * otherwise, @compressibility is expected to be between 0.0 and 1.0 + * if scenarioID == BENCH_ALL_SCENARIOS, all scenarios will be run on the sample +*/ static int benchSample(U32 scenarioID, size_t benchedSize, double compressibility, int cLevel, ZSTD_compressionParameters cparams) @@ -763,7 +769,12 @@ static int benchSample(U32 scenarioID, if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); return 12; } /* Fill buffer */ - RDG_genBuffer(origBuff, benchedSize, compressibility, 0.0, 0); + if (compressibility < 0.0) { + LOREM_genBuffer(origBuff, benchedSize, 0); + } else { + RDG_genBuffer(origBuff, benchedSize, compressibility, 0.0, 0); + + } /* bench */ DISPLAY("\r%70s\r", ""); From f281497aef87a0e6459eef28f695c437a3dec42d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 14 Dec 2024 23:38:18 -0800 Subject: [PATCH 237/405] fullbench: new scenario: compressSequencesAndLiterals() --- lib/compress/zstd_compress.c | 2 +- tests/fullbench.c | 60 +++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 5aad13531..166208589 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7227,7 +7227,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, inSeqs, nbSequences, seqPos); U32 const lastBlock = (blockSize == remaining); FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); - RETURN_ERROR_IF(!lastBlock, GENERIC, "Only supports single block"); + RETURN_ERROR_IF(!lastBlock, srcSize_wrong, "Only supports single block"); assert(blockSize <= remaining); ZSTD_resetSeqStore(&cctx->seqStore); diff --git a/tests/fullbench.c b/tests/fullbench.c index 889761ef4..919ae2742 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -567,6 +567,63 @@ static size_t local_compressSequences(const void* input, size_t inputSize, return ZSTD_compressSequences(g_zcc, dst, dstCapacity, seqs, nbSeqs, src, srcSize); } +static PrepResult prepSequencesAndLiterals(const void* src, size_t srcSize, int cLevel) +{ + PrepResult r = PREPRESULT_INIT; + size_t const dstCapacity = ZSTD_compressBound(srcSize); + void* const dst = malloc(dstCapacity); + size_t const prepCapacity = dstCapacity * 4; + void* prepBuffer = malloc(prepCapacity); + void* sequencesStart = (char*)prepBuffer + 3*sizeof(unsigned); + ZSTD_Sequence* const seqs = sequencesStart; + size_t const seqsCapacity = prepCapacity / sizeof(ZSTD_Sequence); + size_t nbSeqs; + ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel); + nbSeqs = ZSTD_generateSequences(g_zcc, seqs, seqsCapacity, src, srcSize); + CONTROL(srcSize < UINT_MAX); + MEM_write32(prepBuffer, (U32)srcSize); + MEM_write32((char*)prepBuffer+4, (U32)nbSeqs); + /* copy literals */ + { char* const litStart = (char*)(seqs + nbSeqs); + size_t nbLiterals = 0; + const char* ip = src; + size_t n; + for (n=0; n Date: Sat, 14 Dec 2024 23:46:21 -0800 Subject: [PATCH 238/405] minor conversion warning fix --- lib/common/zstd_trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h index 173d63fb1..3ae779fa6 100644 --- a/lib/common/zstd_trace.h +++ b/lib/common/zstd_trace.h @@ -65,7 +65,7 @@ typedef struct { /** * Non-zero if streaming (de)compression is used. */ - unsigned streaming; + int streaming; /** * The dictionary ID. */ From 1c8f5b0f11c9fbcd47135a658dca9b927a0b27b7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 15 Dec 2024 16:14:38 -0800 Subject: [PATCH 239/405] minor optimization for ZSTD_compressSequencesAndLiterals() does not need to track and update internal `litPtr`. note: does not measurably impact performance. --- lib/compress/zstd_compress_internal.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 294835946..10bd8ca70 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -742,13 +742,10 @@ ZSTD_storeSeqOnly(SeqStore_t* seqStorePtr, size_t matchLength) { assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq); - /* update seqStorePtr->lit, so that we know how many literals were or will be copied */ - assert(seqStorePtr->maxNbLit <= 128 KB); - assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit); - seqStorePtr->lit += litLength; /* literal Length */ - if (litLength>0xFFFF) { + assert(litLength <= ZSTD_BLOCKSIZE_MAX); + if (UNLIKELY(litLength>0xFFFF)) { assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */ seqStorePtr->longLengthType = ZSTD_llt_literalLength; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); @@ -759,9 +756,10 @@ ZSTD_storeSeqOnly(SeqStore_t* seqStorePtr, seqStorePtr->sequences[0].offBase = offBase; /* match Length */ + assert(matchLength <= ZSTD_BLOCKSIZE_MAX); assert(matchLength >= MINMATCH); { size_t const mlBase = matchLength - MINMATCH; - if (mlBase>0xFFFF) { + if (UNLIKELY(mlBase>0xFFFF)) { assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */ seqStorePtr->longLengthType = ZSTD_llt_matchLength; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); @@ -811,6 +809,7 @@ ZSTD_storeSeq(SeqStore_t* seqStorePtr, } else { ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w); } + seqStorePtr->lit += litLength; ZSTD_storeSeqOnly(seqStorePtr, litLength, offBase, matchLength); } From f17651446730b580f0a45c4a7917236da140db76 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 15 Dec 2024 23:07:31 -0800 Subject: [PATCH 240/405] minor doc update --- lib/zstd.h | 17 +++++++++-------- tests/fullbench.c | 3 +++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/zstd.h b/lib/zstd.h index 435fe34d4..6218a5d0c 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1665,13 +1665,14 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * aka all literals already extracted and laid out into a single continuous buffer. * This can be useful if the process generating the sequences also happens to generate the buffer of literals, * thus skipping an extraction + caching stage. - * It's essentially a speed optimization when the right conditions are met, + * It's merely a speed optimization when the right conditions are met, * but it also features the following limitations: * - Only supports explicit delimiter mode * - Supports 1 block only (max input 128 KB) * - Not compatible with frame checksum, which must disabled * - Can fail (return an error) when input data cannot be compress sufficiently - * Also, to be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. + * - @litSize must be == sum of all @.litLength fields in @inSeqs. Discrepancy will generate an error. + * - the buffer @literals must be larger than @litSize by at least 8 bytes. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t @@ -2301,9 +2302,12 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo #define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18 /* ZSTD_c_searchForExternalRepcodes + * Note: for now, this param only has an effect if ZSTD_c_blockDelimiters is + * set to ZSTD_sf_explicitBlockDelimiters. That may change in the future. + * * This parameter affects how zstd parses external sequences, such as sequences - * provided through the compressSequences() API or from an external block-level - * sequence producer. + * provided through compressSequences() and variant API + * or from an external block-level sequence producer. * * If set to ZSTD_ps_enable, the library will check for repeated offsets in * external sequences, even if those repcodes are not explicitly indicated in @@ -2317,10 +2321,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo * compression ratio. * * The default value is ZSTD_ps_auto, for which the library will enable/disable - * based on compression level. - * - * Note: for now, this param only has an effect if ZSTD_c_blockDelimiters is - * set to ZSTD_sf_explicitBlockDelimiters. That may change in the future. + * based on compression level (currently: level<10 disables, level>=10 enables). */ #define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 diff --git a/tests/fullbench.c b/tests/fullbench.c index 919ae2742..09c426154 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -617,6 +617,9 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, const void* literals = (ip+=nbSeqs * sizeof(ZSTD_Sequence)); ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); +# if 0 /* for tests */ + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchForExternalRepcodes, ZSTD_ps_enable); +#endif assert(8 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; (void)payload; From a288751de78e3dd69dfacfe74d3f35c534b57096 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 11:31:28 -0800 Subject: [PATCH 241/405] minor optimization: only track seqPos->posInSrc when validateSequences is enabled note: very minor saving, no performance impact --- lib/compress/zstd_compress.c | 37 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 166208589..144a4b69d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7112,20 +7112,24 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, U32 idx = seqPos->idx; U32 const startIdx = idx; Repcodes_t updatedRepcodes; - U32 dictSize; + U32 dictSize = 0; size_t startPosInSrc = seqPos->posInSrc; size_t litConsumed = 0; DEBUGLOG(5, "ZSTD_transferSequencesOnly_wBlockDelim (blockSize = %zu)", blockSize); - if (cctx->cdict) { - dictSize = (U32)cctx->cdict->dictContentSize; - } else if (cctx->prefixDict.dict) { - dictSize = (U32)cctx->prefixDict.dictSize; - } else { - dictSize = 0; + /* dictSize is useful to check offset within Sequence validation */ + if (cctx->appliedParams.validateSequences) { + if (cctx->cdict) { + dictSize = (U32)cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = (U32)cctx->prefixDict.dictSize; + } } + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t)); + + /* Convert Sequences from public format to internal format */ for (; idx < nbSequences && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) { U32 const litLength = inSeqs[idx].litLength; U32 const matchLength = inSeqs[idx].matchLength; @@ -7140,8 +7144,8 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, } DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); - seqPos->posInSrc += litLength + matchLength; if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc, cctx->appliedParams.cParams.windowLog, dictSize, @@ -7156,14 +7160,17 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, /* last sequence (only literals) */ { size_t const lastLitLength = inSeqs[idx].litLength; - seqPos->posInSrc += lastLitLength; - cctx->seqStore.lit += lastLitLength; /* register proper length */ litConsumed += lastLitLength; + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += lastLitLength; + /* blockSize must be exactly correct (checked before calling this function) */ + RETURN_ERROR_IF((seqPos->posInSrc - startPosInSrc) != blockSize, externalSequences_invalid, "mismatch between Sequences and specified blockSize"); + } else { + /* blockSize presumed exactly correct (checked before calling this function) */ + seqPos->posInSrc += blockSize; + } } - /* blockSize must be exactly correct (checked before calling this function) */ - assert((seqPos->posInSrc - startPosInSrc) == blockSize); (void)startPosInSrc; - /* If we skipped repcode search while parsing, we need to update repcodes now */ assert(externalRepSearch != ZSTD_ps_auto); assert(idx >= startIdx); @@ -7236,8 +7243,8 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, inSeqs, nbSequences, blockSize, cctx->appliedParams.searchForExternalRepcodes); - RETURN_ERROR_IF(blockSize != remaining, GENERIC, "Must consume the entire block"); - RETURN_ERROR_IF(litConsumed != litSize, GENERIC, "Must consume the exact amount of literals provided"); + RETURN_ERROR_IF(blockSize != remaining, externalSequences_invalid, "Must consume the entire block"); + RETURN_ERROR_IF(litConsumed != litSize, externalSequences_invalid, "Must consume the exact amount of literals provided"); FORWARD_IF_ERROR(blockSize, "Bad sequence copy"); /* Note: when blockSize is very small, other variant send it uncompressed. From 1f6d6815c3fc4b6d1f406e01849c49b15518ba54 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 11:39:25 -0800 Subject: [PATCH 242/405] optimization: instantiate specialized version without Sequence checking code results in +4% compression speed, thanks to removal of branches in the hot loop. --- lib/compress/zstd_compress.c | 52 ++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 144a4b69d..6ff27056f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7102,12 +7102,13 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, * seqPos must end on an explicit block delimiter * @blockSize must be exactly correct. */ -static size_t -ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, +FORCE_INLINE_TEMPLATE size_t +ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, - ZSTD_ParamSwitch_e externalRepSearch) + ZSTD_ParamSwitch_e externalRepSearch, + int const checkSequences) { U32 idx = seqPos->idx; U32 const startIdx = idx; @@ -7119,7 +7120,7 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, DEBUGLOG(5, "ZSTD_transferSequencesOnly_wBlockDelim (blockSize = %zu)", blockSize); /* dictSize is useful to check offset within Sequence validation */ - if (cctx->appliedParams.validateSequences) { + if (checkSequences) { if (cctx->cdict) { dictSize = (U32)cctx->cdict->dictContentSize; } else if (cctx->prefixDict.dict) { @@ -7144,7 +7145,7 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, } DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); - if (cctx->appliedParams.validateSequences) { + if (checkSequences) { seqPos->posInSrc += litLength + matchLength; FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc, @@ -7161,7 +7162,7 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, /* last sequence (only literals) */ { size_t const lastLitLength = inSeqs[idx].litLength; litConsumed += lastLitLength; - if (cctx->appliedParams.validateSequences) { + if (checkSequences) { seqPos->posInSrc += lastLitLength; /* blockSize must be exactly correct (checked before calling this function) */ RETURN_ERROR_IF((seqPos->posInSrc - startPosInSrc) != blockSize, externalSequences_invalid, "mismatch between Sequences and specified blockSize"); @@ -7201,6 +7202,32 @@ ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, return blockSize; } +typedef size_t (*ZSTD_transferSequencesOnly_f) (ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + size_t blockSize, + ZSTD_ParamSwitch_e externalRepSearch); + +static size_t +ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + size_t blockSize, + ZSTD_ParamSwitch_e externalRepSearch) +{ + return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, externalRepSearch, 0); +} + +static size_t +ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + size_t blockSize, + ZSTD_ParamSwitch_e externalRepSearch) +{ + return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, externalRepSearch, 1); +} + static size_t ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, @@ -7211,6 +7238,9 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, size_t remaining = srcSize; ZSTD_SequencePosition seqPos = {0, 0, 0}; BYTE* op = (BYTE*)dst; + const ZSTD_transferSequencesOnly_f transfer = cctx->appliedParams.validateSequences ? + ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences + : ZSTD_transferSequencesOnly_wBlockDelim; DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu", nbSequences, litSize); if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { @@ -7238,11 +7268,11 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, assert(blockSize <= remaining); ZSTD_resetSeqStore(&cctx->seqStore); - blockSize = ZSTD_transferSequencesOnly_wBlockDelim(cctx, - &seqPos, &litConsumed, - inSeqs, nbSequences, - blockSize, - cctx->appliedParams.searchForExternalRepcodes); + blockSize = transfer(cctx, + &seqPos, &litConsumed, + inSeqs, nbSequences, + blockSize, + cctx->appliedParams.searchForExternalRepcodes); RETURN_ERROR_IF(blockSize != remaining, externalSequences_invalid, "Must consume the entire block"); RETURN_ERROR_IF(litConsumed != litSize, externalSequences_invalid, "Must consume the exact amount of literals provided"); FORWARD_IF_ERROR(blockSize, "Bad sequence copy"); From d2d0fdac4288fed2d63b4d3e0e41f4b4768f8b60 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 12:54:52 -0800 Subject: [PATCH 243/405] updated documentation on validateSequence --- lib/compress/zstd_compress.c | 6 +++--- lib/zstd.h | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 6ff27056f..dc084830e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6585,11 +6585,11 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, } /* ZSTD_validateSequence() : - * @offCode : is presumed to follow format required by ZSTD_storeSeq() + * @offBase : must use the format required by ZSTD_storeSeq() * @returns a ZSTD error code if sequence is not valid */ static size_t -ZSTD_validateSequence(U32 offCode, U32 matchLength, U32 minMatch, +ZSTD_validateSequence(U32 offBase, U32 matchLength, U32 minMatch, size_t posInSrc, U32 windowLog, size_t dictSize, int useSequenceProducer) { U32 const windowSize = 1u << windowLog; @@ -6600,7 +6600,7 @@ ZSTD_validateSequence(U32 offCode, U32 matchLength, U32 minMatch, */ size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize; size_t const matchLenLowerBound = (minMatch == 3 || useSequenceProducer) ? 3 : 4; - RETURN_ERROR_IF(offCode > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!"); + RETURN_ERROR_IF(offBase > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!"); /* Validate maxNbSeq is large enough for the given matchLength and minMatch */ RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, "Matchlength too small for the minMatch"); return 0; diff --git a/lib/zstd.h b/lib/zstd.h index 6218a5d0c..7f1d8c483 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1635,11 +1635,11 @@ ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, si * the block size derived from the cctx, and sequences may be split. This is the default setting. * * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain - * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. + * valid block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. * - * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined - * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for - * specifics regarding offset/matchlength requirements) then the function will bail out and return an error. + * If ZSTD_c_validateSequences == 0, this function blindly accepts the Sequences provided. Invalid Sequences cause undefined + * behavior. If ZSTD_c_validateSequences == 1, then the function will detect invalid Sequences (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) and then bail out and return an error. * * In addition to the two adjustable experimental params, there are other important cctx params. * - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN. @@ -1662,10 +1662,10 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, /*! ZSTD_compressSequencesAndLiterals() : * This is a variant of ZSTD_compressSequences() which, * instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), - * aka all literals already extracted and laid out into a single continuous buffer. + * aka all the literals, already extracted and laid out into a single continuous buffer. * This can be useful if the process generating the sequences also happens to generate the buffer of literals, * thus skipping an extraction + caching stage. - * It's merely a speed optimization when the right conditions are met, + * It's a speed optimization, useful when the right conditions are met, * but it also features the following limitations: * - Only supports explicit delimiter mode * - Supports 1 block only (max input 128 KB) @@ -2172,17 +2172,17 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo /* ZSTD_c_validateSequences * Default is 0 == disabled. Set to 1 to enable sequence validation. * - * For use with sequence compression API: ZSTD_compressSequences(). - * Designates whether or not we validate sequences provided to ZSTD_compressSequences() + * For use with sequence compression API: ZSTD_compressSequences*(). + * Designates whether or not provided sequences are validated within ZSTD_compressSequences*() * during function execution. * - * Without validation, providing a sequence that does not conform to the zstd spec will cause - * undefined behavior, and may produce a corrupted block. + * When Sequence validation is disabled (default), Sequences are compressed as-is, + * so they must correct, otherwise it would result in a corruption error. * - * With validation enabled, if sequence is invalid (see doc/zstd_compression_format.md for + * Sequence validation adds some protection, by ensuring that all values respect boundary conditions. + * If a Sequence is detected invalid (see doc/zstd_compression_format.md for * specifics regarding offset/matchlength requirements) then the function will bail out and * return an error. - * */ #define ZSTD_c_validateSequences ZSTD_c_experimentalParam12 From ca8bd83373310ade16a6d230c01b671d7725eaf1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 13:08:16 -0800 Subject: [PATCH 244/405] minor: cleaner function parameter repcodeResolution --- lib/compress/zstd_compress.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index dc084830e..6b3efb336 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7107,7 +7107,7 @@ ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, - ZSTD_ParamSwitch_e externalRepSearch, + int const repcodeResolution, int const checkSequences) { U32 idx = seqPos->idx; @@ -7136,7 +7136,7 @@ ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, U32 const matchLength = inSeqs[idx].matchLength; U32 offBase; - if (externalRepSearch == ZSTD_ps_disable) { + if (!repcodeResolution) { offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset); } else { U32 const ll0 = (litLength == 0); @@ -7173,9 +7173,8 @@ ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, } /* If we skipped repcode search while parsing, we need to update repcodes now */ - assert(externalRepSearch != ZSTD_ps_auto); assert(idx >= startIdx); - if (externalRepSearch == ZSTD_ps_disable && idx != startIdx) { + if (!repcodeResolution && idx != startIdx) { U32* const rep = updatedRepcodes.rep; U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */ @@ -7206,16 +7205,18 @@ typedef size_t (*ZSTD_transferSequencesOnly_f) (ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, - ZSTD_ParamSwitch_e externalRepSearch); + int const repcodeResolution); static size_t ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, - ZSTD_ParamSwitch_e externalRepSearch) + int const repcodeResolution) { - return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, externalRepSearch, 0); + return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, + seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, + repcodeResolution, 0); } static size_t @@ -7223,9 +7224,11 @@ ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, - ZSTD_ParamSwitch_e externalRepSearch) + int const repcodeResolution) { - return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, externalRepSearch, 1); + return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, + seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, + repcodeResolution, 1); } static size_t @@ -7238,6 +7241,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, size_t remaining = srcSize; ZSTD_SequencePosition seqPos = {0, 0, 0}; BYTE* op = (BYTE*)dst; + int const repcodeResolution = (cctx->appliedParams.searchForExternalRepcodes == ZSTD_ps_enable); const ZSTD_transferSequencesOnly_f transfer = cctx->appliedParams.validateSequences ? ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences : ZSTD_transferSequencesOnly_wBlockDelim; @@ -7246,6 +7250,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { RETURN_ERROR(GENERIC, "This mode is only compatible with explicit delimiters"); } + assert(cctx->appliedParams.searchForExternalRepcodes != ZSTD_ps_auto); /* Special case: empty frame */ if (remaining == 0) { @@ -7272,7 +7277,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, &seqPos, &litConsumed, inSeqs, nbSequences, blockSize, - cctx->appliedParams.searchForExternalRepcodes); + repcodeResolution); RETURN_ERROR_IF(blockSize != remaining, externalSequences_invalid, "Must consume the entire block"); RETURN_ERROR_IF(litConsumed != litSize, externalSequences_invalid, "Must consume the exact amount of literals provided"); FORWARD_IF_ERROR(blockSize, "Bad sequence copy"); @@ -7299,9 +7304,9 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, * but it could be considered from analyzing the sequence directly */ if (compressedSeqsSize == 0) { - /* Sending uncompressed blocks is difficult, because we don't have the source. - * In theory, we could use the sequences to regenerate the source, like a decompressor, - * but it's complex and likely overkill. + /* Sending uncompressed blocks is difficult, because the source is not provided. + * In theory, one could use the sequences to regenerate the source, like a decompressor, + * but it's complex, and memory hungry, killing the purpose of this variant. * Current outcome: generate an error code. */ RETURN_ERROR(dstSize_tooSmall, "Data is not compressible"); /* note: error code might be misleading */ From 5164d44dabbbf2f3f1cd89bbf1244b7b73d69ef3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 13:21:08 -0800 Subject: [PATCH 245/405] change advanced parameter name: ZSTD_c_repcodeResolution and updated its documentation. Note: older name ZSTD_c_searchForExternalRepcodes remains supported via #define --- lib/compress/zstd_compress.c | 12 ++++++------ lib/zstd.h | 23 +++++++++++++++-------- tests/fullbench.c | 2 +- tests/fuzz/zstd_helpers.c | 2 +- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 6b3efb336..be6107cb8 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -634,7 +634,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = ZSTD_BLOCKSIZE_MAX; return bounds; - case ZSTD_c_searchForExternalRepcodes: + case ZSTD_c_repcodeResolution: bounds.lowerBound = (int)ZSTD_ps_auto; bounds.upperBound = (int)ZSTD_ps_disable; return bounds; @@ -708,7 +708,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_prefetchCDictTables: case ZSTD_c_enableSeqProducerFallback: case ZSTD_c_maxBlockSize: - case ZSTD_c_searchForExternalRepcodes: + case ZSTD_c_repcodeResolution: default: return 0; } @@ -768,7 +768,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_prefetchCDictTables: case ZSTD_c_enableSeqProducerFallback: case ZSTD_c_maxBlockSize: - case ZSTD_c_searchForExternalRepcodes: + case ZSTD_c_repcodeResolution: break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); @@ -1020,8 +1020,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->maxBlockSize = (size_t)value; return CCtxParams->maxBlockSize; - case ZSTD_c_searchForExternalRepcodes: - BOUNDCHECK(ZSTD_c_searchForExternalRepcodes, value); + case ZSTD_c_repcodeResolution: + BOUNDCHECK(ZSTD_c_repcodeResolution, value); CCtxParams->searchForExternalRepcodes = (ZSTD_ParamSwitch_e)value; return CCtxParams->searchForExternalRepcodes; @@ -1169,7 +1169,7 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_maxBlockSize: *value = (int)CCtxParams->maxBlockSize; break; - case ZSTD_c_searchForExternalRepcodes: + case ZSTD_c_repcodeResolution: *value = (int)CCtxParams->searchForExternalRepcodes; break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); diff --git a/lib/zstd.h b/lib/zstd.h index 7f1d8c483..ffcb059cf 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1637,6 +1637,12 @@ ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, si * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain * valid block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. * + * When ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, it's possible to decide generating repcodes + * using the advanced parameter ZSTD_c_repcodeResolution. Repcodes will improve compression ratio, though the benefit + * can vary greatly depending on Sequences. On the other hand, repcode resolution is an expensive operation. + * By default, it's disabled at low (<10) compression levels, and enabled above the threshold (>=10). + * ZSTD_c_repcodeResolution makes it possible to directly manage this processing in either direction. + * * If ZSTD_c_validateSequences == 0, this function blindly accepts the Sequences provided. Invalid Sequences cause undefined * behavior. If ZSTD_c_validateSequences == 1, then the function will detect invalid Sequences (see doc/zstd_compression_format.md for * specifics regarding offset/matchlength requirements) and then bail out and return an error. @@ -2301,18 +2307,18 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo */ #define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18 -/* ZSTD_c_searchForExternalRepcodes - * Note: for now, this param only has an effect if ZSTD_c_blockDelimiters is - * set to ZSTD_sf_explicitBlockDelimiters. That may change in the future. +/* ZSTD_c_repcodeResolution + * This parameter only has an effect if ZSTD_c_blockDelimiters is + * set to ZSTD_sf_explicitBlockDelimiters (may change in the future). * - * This parameter affects how zstd parses external sequences, such as sequences - * provided through compressSequences() and variant API + * This parameter affects how zstd parses external sequences, + * provided via the ZSTD_compressSequences*() API * or from an external block-level sequence producer. * - * If set to ZSTD_ps_enable, the library will check for repeated offsets in + * If set to ZSTD_ps_enable, the library will check for repeated offsets within * external sequences, even if those repcodes are not explicitly indicated in * the "rep" field. Note that this is the only way to exploit repcode matches - * while using compressSequences() or an external sequence producer, since zstd + * while using compressSequences*() or an external sequence producer, since zstd * currently ignores the "rep" field of external sequences. * * If set to ZSTD_ps_disable, the library will not exploit repeated offsets in @@ -2323,7 +2329,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo * The default value is ZSTD_ps_auto, for which the library will enable/disable * based on compression level (currently: level<10 disables, level>=10 enables). */ -#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 +#define ZSTD_c_repcodeResolution ZSTD_c_experimentalParam19 +#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 /* older name */ /*! ZSTD_CCtx_getParameter() : diff --git a/tests/fullbench.c b/tests/fullbench.c index 09c426154..320b0ed73 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -618,7 +618,7 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); # if 0 /* for tests */ - ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchForExternalRepcodes, ZSTD_ps_enable); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable); #endif assert(8 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; (void)payload; diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c index c89e448d0..f3b2e6fba 100644 --- a/tests/fuzz/zstd_helpers.c +++ b/tests/fuzz/zstd_helpers.c @@ -146,7 +146,7 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer setRand(cctx, ZSTD_c_prefetchCDictTables, 0, 2, producer); setRand(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX_MIN, ZSTD_BLOCKSIZE_MAX, producer); setRand(cctx, ZSTD_c_validateSequences, 0, 1, producer); - setRand(cctx, ZSTD_c_searchForExternalRepcodes, 0, 2, producer); + setRand(cctx, ZSTD_c_repcodeResolution, 0, 2, producer); if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) { setRand(cctx, ZSTD_c_srcSizeHint, ZSTD_SRCSIZEHINT_MIN, 2 * srcSize, producer); } From 31b5ef25393c3abf4bb9e290cf32b06d97c78b93 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 18:05:40 -0800 Subject: [PATCH 246/405] ZSTD_compressSequencesAndLiterals() now supports multi-blocks frames. --- lib/compress/zstd_compress.c | 40 ++++++++++++++++++------------------ lib/zstd.h | 5 ++--- tests/fuzzer.c | 2 +- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index be6107cb8..71e40bdc1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7104,7 +7104,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, */ FORCE_INLINE_TEMPLATE size_t ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution, @@ -7197,37 +7197,36 @@ ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); seqPos->idx = idx+1; - *litConsumedPtr = litConsumed; - return blockSize; + return litConsumed; } typedef size_t (*ZSTD_transferSequencesOnly_f) (ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution); static size_t ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution) { return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, - seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, + seqPos, inSeqs, nbSequences, blockSize, repcodeResolution, 0); } static size_t ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, size_t* litConsumedPtr, + ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution) { return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, - seqPos, litConsumedPtr, inSeqs, nbSequences, blockSize, + seqPos, inSeqs, nbSequences, blockSize, repcodeResolution, 1); } @@ -7269,28 +7268,26 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, inSeqs, nbSequences, seqPos); U32 const lastBlock = (blockSize == remaining); FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); - RETURN_ERROR_IF(!lastBlock, srcSize_wrong, "Only supports single block"); assert(blockSize <= remaining); ZSTD_resetSeqStore(&cctx->seqStore); - blockSize = transfer(cctx, - &seqPos, &litConsumed, + litConsumed = transfer(cctx, + &seqPos, inSeqs, nbSequences, blockSize, repcodeResolution); - RETURN_ERROR_IF(blockSize != remaining, externalSequences_invalid, "Must consume the entire block"); - RETURN_ERROR_IF(litConsumed != litSize, externalSequences_invalid, "Must consume the exact amount of literals provided"); - FORWARD_IF_ERROR(blockSize, "Bad sequence copy"); + FORWARD_IF_ERROR(litConsumed, "Bad sequence conversion"); + RETURN_ERROR_IF(litConsumed > litSize, externalSequences_invalid, "discrepancy between literals buffer and Sequences"); /* Note: when blockSize is very small, other variant send it uncompressed. - * Here, we still send the sequences, because we don't have the source to send it uncompressed. - * In theory, it would be possible to reproduce the source from the sequences, - * but that's pretty complex and memory intensive, which goes against the principles of this variant. */ + * Here, we still send the sequences, because we don't have the original source to send it uncompressed. + * One could imagine it possible to reproduce the source from the sequences, + * but that's complex and costly memory intensive, which goes against the objectives of this variant. */ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); compressedSeqsSize = ZSTD_entropyCompressSeqStore_wExtLitBuffer( op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, - literals, litSize, + literals, litConsumed, blockSize, &cctx->seqStore, &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, @@ -7299,17 +7296,19 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, cctx->bmi2); FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); + litSize -= litConsumed; + literals = (const char*)literals + litConsumed; /* Note: difficult to check source for RLE block when only Literals are provided, * but it could be considered from analyzing the sequence directly */ if (compressedSeqsSize == 0) { - /* Sending uncompressed blocks is difficult, because the source is not provided. + /* Sending uncompressed blocks is out of reach, because the source is not provided. * In theory, one could use the sequences to regenerate the source, like a decompressor, * but it's complex, and memory hungry, killing the purpose of this variant. * Current outcome: generate an error code. */ - RETURN_ERROR(dstSize_tooSmall, "Data is not compressible"); /* note: error code might be misleading */ + RETURN_ERROR(dstSize_tooSmall, "Data is not compressible"); /* note: error code could be clearer */ } else { U32 cBlockHeader; assert(compressedSeqsSize > 1); /* no RLE */ @@ -7338,6 +7337,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, DEBUGLOG(5, "cSize running total: %zu (remaining dstCapacity=%zu)", cSize, dstCapacity); } + RETURN_ERROR_IF(litSize != 0, externalSequences_invalid, "literals must be entirely and exactly consumed"); DEBUGLOG(4, "cSize final total: %zu", cSize); return cSize; } diff --git a/lib/zstd.h b/lib/zstd.h index ffcb059cf..68e78b3ca 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1674,10 +1674,9 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * It's a speed optimization, useful when the right conditions are met, * but it also features the following limitations: * - Only supports explicit delimiter mode - * - Supports 1 block only (max input 128 KB) * - Not compatible with frame checksum, which must disabled - * - Can fail (return an error) when input data cannot be compress sufficiently - * - @litSize must be == sum of all @.litLength fields in @inSeqs. Discrepancy will generate an error. + * - If any block is incompressible, will fail and return an error + * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. * - the buffer @literals must be larger than @litSize by at least 8 bytes. * @return : final compressed size, or a ZSTD error code. */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 3063ec2d1..4901376ff 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3880,7 +3880,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : ZSTD_compressSequencesAndLiterals : ", testNb++); { - const size_t srcSize = 100 KB; + const size_t srcSize = 500 KB; const BYTE* const src = (BYTE*)CNBuffer; BYTE* const dst = (BYTE*)compressedBuffer; const size_t dstCapacity = ZSTD_compressBound(srcSize); From f0d0d952348b4bdc2e3111d73d6703f1b6151f0d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 18:08:14 -0800 Subject: [PATCH 247/405] added tests check that ZSTD_compressAndLiterals() also controls that the `srcSize` field is exact. --- tests/fuzzer.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4901376ff..b20031708 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3922,6 +3922,20 @@ static int basicUnitTests(U32 const seed, double compressibility) goto _output_error; } + /* too short srcSize: must fail */ + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize, srcSize-1); + if (!ZSTD_isError(compressedSize)) { + DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too short\n"); + goto _output_error; + } + + /* too large srcSize: must fail */ + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize, srcSize+1); + if (!ZSTD_isError(compressedSize)) { + DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too short\n"); + goto _output_error; + } + /* correct amount of literals: should compress successfully */ compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize); if (ZSTD_isError(compressedSize)) { From 6f8c1046d04a7a5439320edbd4775da5b5781726 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 21:05:24 -0800 Subject: [PATCH 248/405] update Visual Studio solutions --- build/VS2010/fullbench-dll/fullbench-dll.vcxproj | 1 + build/VS2010/fullbench/fullbench.vcxproj | 1 + 2 files changed, 2 insertions(+) diff --git a/build/VS2010/fullbench-dll/fullbench-dll.vcxproj b/build/VS2010/fullbench-dll/fullbench-dll.vcxproj index befdc0445..3e88d087a 100644 --- a/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +++ b/build/VS2010/fullbench-dll/fullbench-dll.vcxproj @@ -169,6 +169,7 @@ + diff --git a/build/VS2010/fullbench/fullbench.vcxproj b/build/VS2010/fullbench/fullbench.vcxproj index f60cfe726..c78a72ecc 100644 --- a/build/VS2010/fullbench/fullbench.vcxproj +++ b/build/VS2010/fullbench/fullbench.vcxproj @@ -184,6 +184,7 @@ + From 47edd0acf4ec6a6c2c9b4fc05fbd3de2d2252c59 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 21:23:30 -0800 Subject: [PATCH 249/405] removed fullbench-dll project from visual solutions --- .../fullbench-dll/fullbench-dll.vcxproj | 190 ------------------ build/VS2010/zstd.sln | 5 - 2 files changed, 195 deletions(-) delete mode 100644 build/VS2010/fullbench-dll/fullbench-dll.vcxproj diff --git a/build/VS2010/fullbench-dll/fullbench-dll.vcxproj b/build/VS2010/fullbench-dll/fullbench-dll.vcxproj deleted file mode 100644 index 3e88d087a..000000000 --- a/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {00000000-1CC8-4FD7-9281-6B8DBB9D3DF8} - Win32Proj - fullbench-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - MultiByte - - - Application - true - MultiByte - - - Application - false - true - MultiByte - - - Application - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - true - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(UniversalCRT_IncludePath); - false - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - false - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - false - - - - - Level4 - - - MaxSpeed - true - true - WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - libzstd.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - {00000000-94d5-4bf9-8a50-7bd9929a0850} - - - - - - diff --git a/build/VS2010/zstd.sln b/build/VS2010/zstd.sln index 12032db44..528aae8aa 100644 --- a/build/VS2010/zstd.sln +++ b/build/VS2010/zstd.sln @@ -7,11 +7,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuzzer", "fuzzer\fuzzer.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench", "fullbench\fullbench.vcxproj", "{61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench-dll", "fullbench-dll\fullbench-dll.vcxproj", "{00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}" - ProjectSection(ProjectDependencies) = postProject - {00000000-94D5-4BF9-8A50-7BD9929A0850} = {00000000-94D5-4BF9-8A50-7BD9929A0850} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datagen", "datagen\datagen.vcxproj", "{037E781E-81A6-494B-B1B3-438AB1200523}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "libzstd\libzstd.vcxproj", "{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}" From f617e86b71f71267b5ffc31aafb46c7ba83ee9e7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 21:29:20 -0800 Subject: [PATCH 250/405] fixed incorrect assert --- tests/Makefile | 2 +- tests/fullbench.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index c10d66f53..f24d5cb7b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -148,7 +148,7 @@ fullbench32: CPPFLAGS += -m32 $(FULLBENCHS) : CPPFLAGS += $(MULTITHREAD_CPP) -Wno-deprecated-declarations $(FULLBENCHS) : LDFLAGS += $(MULTITHREAD_LD) $(FULLBENCHS) : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements -$(FULLBENCHS) : DEBUGLEVEL = 0 # turn off assert() for speed measurements +$(FULLBENCHS) : DEBUGLEVEL ?= 0 # turn off assert() for speed measurements $(FULLBENCHS) : $(ZSTD_FILES) $(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c $(LINK.c) $^ -o $@$(EXT) diff --git a/tests/fullbench.c b/tests/fullbench.c index 320b0ed73..0776d4221 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -620,7 +620,7 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, # if 0 /* for tests */ ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable); #endif - assert(8 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; + assert(12 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; (void)payload; return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, srcSize); From 61ac8311e0983d21b95d5ef8ac98477b348a806e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 16 Dec 2024 21:48:10 -0800 Subject: [PATCH 251/405] attempt to silence Visual Studio warning about fopen() --- tests/fullbench.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 0776d4221..e89a2b326 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -12,8 +12,9 @@ /*_************************************ * Includes **************************************/ -#include +#define _CRT_SECURE_NO_WARNINGS /* disable Visual warning that it doesn't like fopen() */ #define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still bench some deprecated functions */ +#include #include "util.h" /* Compiler options, UTIL_GetFileSize */ #include /* malloc */ #include /* fprintf, fopen, ftello64 */ From d48e330ae10a4042b85122213b0add998d6598f6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 17 Dec 2024 14:24:29 -0800 Subject: [PATCH 252/405] change name to ZSTD_convertSequences*() --- lib/compress/zstd_compress.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 71e40bdc1..3c5cb209c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7103,7 +7103,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, * @blockSize must be exactly correct. */ FORCE_INLINE_TEMPLATE size_t -ZSTD_transferSequencesOnly_wBlockDelim_internal(ZSTD_CCtx* cctx, +ZSTD_convertSequences_wBlockDelim_internal(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, @@ -7207,25 +7207,25 @@ typedef size_t (*ZSTD_transferSequencesOnly_f) (ZSTD_CCtx* cctx, int const repcodeResolution); static size_t -ZSTD_transferSequencesOnly_wBlockDelim(ZSTD_CCtx* cctx, +ZSTD_convertSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution) { - return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, + return ZSTD_convertSequences_wBlockDelim_internal(cctx, seqPos, inSeqs, nbSequences, blockSize, repcodeResolution, 0); } static size_t -ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, +ZSTD_convertSequences_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution) { - return ZSTD_transferSequencesOnly_wBlockDelim_internal(cctx, + return ZSTD_convertSequences_wBlockDelim_internal(cctx, seqPos, inSeqs, nbSequences, blockSize, repcodeResolution, 1); } @@ -7242,8 +7242,8 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, BYTE* op = (BYTE*)dst; int const repcodeResolution = (cctx->appliedParams.searchForExternalRepcodes == ZSTD_ps_enable); const ZSTD_transferSequencesOnly_f transfer = cctx->appliedParams.validateSequences ? - ZSTD_transferSequencesOnly_wBlockDelim_andCheckSequences - : ZSTD_transferSequencesOnly_wBlockDelim; + ZSTD_convertSequences_wBlockDelim_andCheckSequences + : ZSTD_convertSequences_wBlockDelim; DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu", nbSequences, litSize); if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { From 95ad9e47ffa930d2facb5d2dd2de511bf8171e5d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 17 Dec 2024 17:25:57 -0800 Subject: [PATCH 253/405] added benchmark for ZSTD_convertBlockSequences_wBlockDelim() --- lib/compress/zstd_compress.c | 35 ++++++++-------- lib/compress/zstd_compress_internal.h | 16 +++++++ tests/fullbench.c | 60 +++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 17 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3c5cb209c..c4f699eb0 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3240,12 +3240,6 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq return litLenSum + matchLenSum; } -typedef struct { - U32 idx; /* Index in array of ZSTD_Sequence */ - U32 posInSequence; /* Position within sequence at idx */ - size_t posInSrc; /* Number of bytes given by sequences provided so far */ -} ZSTD_SequencePosition; - static size_t ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, @@ -7103,7 +7097,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, * @blockSize must be exactly correct. */ FORCE_INLINE_TEMPLATE size_t -ZSTD_convertSequences_wBlockDelim_internal(ZSTD_CCtx* cctx, +ZSTD_convertBlockSequences_wBlockDelim_internal(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, @@ -7200,32 +7194,39 @@ ZSTD_convertSequences_wBlockDelim_internal(ZSTD_CCtx* cctx, return litConsumed; } -typedef size_t (*ZSTD_transferSequencesOnly_f) (ZSTD_CCtx* cctx, +/* for tests only */ +void CCTX_resetSeqStore(ZSTD_CCtx* cctx) +{ + cctx->seqStore.sequences = cctx->seqStore.sequencesStart; + cctx->seqStore.lit = cctx->seqStore.litStart; +} + +typedef size_t (*ZSTD_convertBlockSequences_f) (ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution); -static size_t -ZSTD_convertSequences_wBlockDelim(ZSTD_CCtx* cctx, +size_t +ZSTD_convertBlockSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution) { - return ZSTD_convertSequences_wBlockDelim_internal(cctx, + return ZSTD_convertBlockSequences_wBlockDelim_internal(cctx, seqPos, inSeqs, nbSequences, blockSize, repcodeResolution, 0); } static size_t -ZSTD_convertSequences_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, +ZSTD_convertBlockSequences_wBlockDelim_andCheckSequences(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, size_t blockSize, int const repcodeResolution) { - return ZSTD_convertSequences_wBlockDelim_internal(cctx, + return ZSTD_convertBlockSequences_wBlockDelim_internal(cctx, seqPos, inSeqs, nbSequences, blockSize, repcodeResolution, 1); } @@ -7241,9 +7242,9 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, ZSTD_SequencePosition seqPos = {0, 0, 0}; BYTE* op = (BYTE*)dst; int const repcodeResolution = (cctx->appliedParams.searchForExternalRepcodes == ZSTD_ps_enable); - const ZSTD_transferSequencesOnly_f transfer = cctx->appliedParams.validateSequences ? - ZSTD_convertSequences_wBlockDelim_andCheckSequences - : ZSTD_convertSequences_wBlockDelim; + const ZSTD_convertBlockSequences_f convertBlockSequences = cctx->appliedParams.validateSequences ? + ZSTD_convertBlockSequences_wBlockDelim_andCheckSequences + : ZSTD_convertBlockSequences_wBlockDelim; DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu", nbSequences, litSize); if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { @@ -7271,7 +7272,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, assert(blockSize <= remaining); ZSTD_resetSeqStore(&cctx->seqStore); - litConsumed = transfer(cctx, + litConsumed = convertBlockSequences(cctx, &seqPos, inSeqs, nbSequences, blockSize, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 10bd8ca70..bbcf4a7d5 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1522,6 +1522,22 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); +typedef struct { + U32 idx; /* Index in array of ZSTD_Sequence */ + U32 posInSequence; /* Position within sequence at idx */ + size_t posInSrc; /* Number of bytes given by sequences provided so far */ +} ZSTD_SequencePosition; + +size_t +ZSTD_convertBlockSequences_wBlockDelim(ZSTD_CCtx* cctx, + ZSTD_SequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + size_t blockSize, + int const repcodeResolution); + +/* for tests only */ +void CCTX_resetSeqStore(ZSTD_CCtx* cctx); + /* ============================================================== * Private declarations * These prototypes shall only be called from within lib/compress diff --git a/tests/fullbench.c b/tests/fullbench.c index e89a2b326..c42c923c1 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -21,6 +21,7 @@ #include #include "mem.h" /* U32 */ +#include "compress/zstd_compress_internal.h" #ifndef ZSTD_DLL_IMPORT #include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, ZSTD_getcBlockSize, blockType_e, KB, MB */ #include "decompress/zstd_decompress_internal.h" /* ZSTD_DCtx struct */ @@ -627,6 +628,64 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, srcSize); } +static PrepResult prepConvertSequences(const void* src, size_t srcSize, int cLevel) +{ + PrepResult r = PREPRESULT_INIT; + size_t const prepCapacity = srcSize * 4; + void* prepBuffer = malloc(prepCapacity); + void* sequencesStart = (char*)prepBuffer + 2*sizeof(unsigned); + ZSTD_Sequence* const seqs = sequencesStart; + size_t const seqsCapacity = prepCapacity / sizeof(ZSTD_Sequence); + size_t totalNbSeqs, nbSeqs, blockSize=0; + ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel); + totalNbSeqs = ZSTD_generateSequences(g_zcc, seqs, seqsCapacity, src, srcSize); + CONTROL(!ZSTD_isError(totalNbSeqs)); + /* find nb sequences in first block */ + { size_t n; + for (n=0; n Date: Tue, 17 Dec 2024 21:33:26 -0800 Subject: [PATCH 254/405] improved speed of the Sequences converter --- doc/zstd_manual.html | 36 +++-- lib/compress/zstd_compress.c | 209 ++++++++++---------------- lib/compress/zstd_compress_internal.h | 10 +- lib/zstd.h | 3 +- tests/Makefile | 6 +- tests/fullbench.c | 11 +- tests/fuzzer.c | 20 +-- 7 files changed, 116 insertions(+), 179 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 7cfeda22d..2c4c4b0e8 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1084,7 +1084,7 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); * * Note: This field is optional. ZSTD_generateSequences() will calculate the value of * 'rep', but repeat offsets do not necessarily need to be calculated from an external - * sequence provider's perspective. For example, ZSTD_compressSequences() does not + * sequence provider perspective. For example, ZSTD_compressSequences() does not * use this 'rep' field at all (as of now). */ } ZSTD_Sequence; @@ -1331,7 +1331,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr,
    ZSTD_DEPRECATED("For debugging only, will be replaced by ZSTD_extractSequences()")
     ZSTDLIB_STATIC_API size_t
     ZSTD_generateSequences(ZSTD_CCtx* zc,
    -           ZSTD_Sequence* outSeqs, size_t outSeqsSize,
    +           ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,
                const void* src, size_t srcSize);
     

    WARNING: This function is meant for debugging and informational purposes ONLY! Its implementation is flawed, and it will be deleted in a future version. @@ -1345,7 +1345,7 @@ ZSTD_generateSequences(ZSTD_CCtx* zc, @param zc The compression context to be used for ZSTD_compress2(). Set any compression parameters you need on this context. @param outSeqs The output sequences buffer of size @p outSeqsSize - @param outSeqsSize The size of the output sequences buffer. + @param outSeqsCapacity The size of the output sequences buffer. ZSTD_sequenceBound(srcSize) is an upper bound on the number of sequences that can be generated. @param src The source buffer to generate sequences from of size @p srcSize. @@ -1392,11 +1392,17 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, the block size derived from the cctx, and sequences may be split. This is the default setting. If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain - block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. + valid block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. - If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined - behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for - specifics regarding offset/matchlength requirements) then the function will bail out and return an error. + When ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, it's possible to decide generating repcodes + using the advanced parameter ZSTD_c_repcodeResolution. Repcodes will improve compression ratio, though the benefit + can vary greatly depending on Sequences. On the other hand, repcode resolution is an expensive operation. + By default, it's disabled at low (<10) compression levels, and enabled above the threshold (>=10). + ZSTD_c_repcodeResolution makes it possible to directly manage this processing in either direction. + + If ZSTD_c_validateSequences == 0, this function blindly accepts the Sequences provided. Invalid Sequences cause undefined + behavior. If ZSTD_c_validateSequences == 1, then the function will detect invalid Sequences (see doc/zstd_compression_format.md for + specifics regarding offset/matchlength requirements) and then bail out and return an error. In addition to the two adjustable experimental params, there are other important cctx params. - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN. @@ -1414,19 +1420,21 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx,

    ZSTDLIB_STATIC_API size_t
     ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,
                           void* dst, size_t dstCapacity,
    -                const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
    -                const void* literals, size_t litSize, size_t srcSize);
    +                const ZSTD_Sequence* inSeqs, size_t nbSequences,
    +                const void* literals, size_t litSize);
     

    This is a variant of ZSTD_compressSequences() which, instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), - aka all literals already extracted and laid out into a single continuous buffer. + aka all the literals, already extracted and laid out into a single continuous buffer. This can be useful if the process generating the sequences also happens to generate the buffer of literals, thus skipping an extraction + caching stage. - It's essentially a speed optimization when the right conditions are met, - but it also is restricted by the following limitations: + It's a speed optimization, useful when the right conditions are met, + but it also features the following limitations: - Only supports explicit delimiter mode - Not compatible with frame checksum, which must disabled - - Can fail when unable to compress sufficiently - Also, to be valid, @litSize must be equal to the sum of all @.litLength fields in @inSeqs. + - Does not write the content size in frame header + - If any block is incompressible, will fail and return an error + - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. + - the buffer @literals must be larger than @litSize by at least 8 bytes. @return : final compressed size, or a ZSTD error code.


    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index c4f699eb0..70a9731bf 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2207,7 +2207,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, zc->appliedParams.fParams.contentSizeFlag = 0; DEBUGLOG(4, "pledged content size : %u ; flag : %u", (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag); - zc->blockSize = blockSize; + zc->blockSizeMax = blockSize; XXH64_reset(&zc->xxhState, 0); zc->stage = ZSTDcs_init; @@ -4293,8 +4293,8 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, lastBlock, 0 /* isPartition */); FORWARD_IF_ERROR(cSizeSingleBlock, "Compressing single block from splitBlock_internal() failed!"); DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal: No splits"); - assert(zc->blockSize <= ZSTD_BLOCKSIZE_MAX); - assert(cSizeSingleBlock <= zc->blockSize + ZSTD_blockHeaderSize); + assert(zc->blockSizeMax <= ZSTD_BLOCKSIZE_MAX); + assert(cSizeSingleBlock <= zc->blockSizeMax + ZSTD_blockHeaderSize); return cSizeSingleBlock; } @@ -4328,7 +4328,7 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, dstCapacity -= cSizeChunk; cSize += cSizeChunk; *currSeqStore = *nextSeqStore; - assert(cSizeChunk <= zc->blockSize + ZSTD_blockHeaderSize); + assert(cSizeChunk <= zc->blockSizeMax + ZSTD_blockHeaderSize); } /* cRep and dRep may have diverged during the compression. * If so, we use the dRep repcodes for the next block. @@ -4580,7 +4580,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, const void* src, size_t srcSize, U32 lastFrameChunk) { - size_t blockSizeMax = cctx->blockSize; + size_t blockSizeMax = cctx->blockSizeMax; size_t remaining = srcSize; const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; @@ -4816,7 +4816,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, src, (BYTE const*)src + srcSize); } - DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize); + DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSizeMax); { size_t const cSize = frame ? ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */); @@ -6070,11 +6070,11 @@ size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx) { if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { - return cctx->blockSize - cctx->stableIn_notConsumed; + return cctx->blockSizeMax - cctx->stableIn_notConsumed; } assert(cctx->appliedParams.inBufferMode == ZSTD_bm_buffered); { size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos; - if (hintInSize==0) hintInSize = cctx->blockSize; + if (hintInSize==0) hintInSize = cctx->blockSizeMax; return hintInSize; } } @@ -6162,7 +6162,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, } else { assert(zcs->appliedParams.inBufferMode == ZSTD_bm_stable); if ( (flushMode == ZSTD_e_continue) - && ( (size_t)(iend - ip) < zcs->blockSize) ) { + && ( (size_t)(iend - ip) < zcs->blockSizeMax) ) { /* can't compress a full block : stop here */ zcs->stableIn_notConsumed = (size_t)(iend - ip); ip = iend; /* pretend to have consumed input */ @@ -6181,7 +6181,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, size_t cSize; size_t oSize = (size_t)(oend-op); size_t const iSize = inputBuffered ? zcs->inBuffPos - zcs->inToCompress - : MIN((size_t)(iend - ip), zcs->blockSize); + : MIN((size_t)(iend - ip), zcs->blockSizeMax); if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) cDst = op; /* compress into output buffer, to skip flush stage */ else @@ -6196,9 +6196,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); zcs->frameEnded = lastBlock; /* prepare next block */ - zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; + zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSizeMax; if (zcs->inBuffTarget > zcs->inBuffSize) - zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; + zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSizeMax; DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); if (!lastBlock) @@ -6413,7 +6413,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, /* for small input: avoid automatic flush on reaching end of block, since * it would require to add a 3-bytes null block to end frame */ - cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize); + cctx->inBuffTarget = cctx->blockSizeMax + (cctx->blockSizeMax == pledgedSrcSize); } else { cctx->inBuffTarget = 0; } @@ -6951,7 +6951,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, size_t compressedSeqsSize; size_t cBlockSize; size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters, - cctx->blockSize, remaining, + cctx->blockSizeMax, remaining, inSeqs, inSeqsSize, seqPos); U32 const lastBlock = (blockSize == remaining); FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); @@ -7093,167 +7093,112 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, } /* - * seqPos must end on an explicit block delimiter - * @blockSize must be exactly correct. + * Note: Sequence validation functionality has been disabled (removed). + * This is helpful to find back simplicity, leading to performance. + * It may be re-inserted later. */ -FORCE_INLINE_TEMPLATE size_t -ZSTD_convertBlockSequences_wBlockDelim_internal(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, +size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, const ZSTD_Sequence* const inSeqs, size_t nbSequences, - size_t blockSize, - int const repcodeResolution, - int const checkSequences) + int const repcodeResolution) { - U32 idx = seqPos->idx; - U32 const startIdx = idx; Repcodes_t updatedRepcodes; - U32 dictSize = 0; - size_t startPosInSrc = seqPos->posInSrc; size_t litConsumed = 0; + size_t seqNb = 0; - DEBUGLOG(5, "ZSTD_transferSequencesOnly_wBlockDelim (blockSize = %zu)", blockSize); + DEBUGLOG(5, "ZSTD_convertBlockSequences (nbSequences = %zu)", nbSequences); - /* dictSize is useful to check offset within Sequence validation */ - if (checkSequences) { - if (cctx->cdict) { - dictSize = (U32)cctx->cdict->dictContentSize; - } else if (cctx->prefixDict.dict) { - dictSize = (U32)cctx->prefixDict.dictSize; - } - } + RETURN_ERROR_IF(nbSequences >= cctx->seqStore.maxNbSeq, externalSequences_invalid, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t)); + /* check end condition */ + assert(nbSequences >= 1); + assert(inSeqs[nbSequences-1].matchLength == 0); + assert(inSeqs[nbSequences-1].offset == 0); + /* Convert Sequences from public format to internal format */ - for (; idx < nbSequences && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) { - U32 const litLength = inSeqs[idx].litLength; - U32 const matchLength = inSeqs[idx].matchLength; + for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) { + U32 const litLength = inSeqs[seqNb].litLength; + U32 const matchLength = inSeqs[seqNb].matchLength; U32 offBase; if (!repcodeResolution) { - offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset); + offBase = OFFSET_TO_OFFBASE(inSeqs[seqNb].offset); } else { U32 const ll0 = (litLength == 0); - offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0); + offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0); ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); } DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); - if (checkSequences) { - seqPos->posInSrc += litLength + matchLength; - FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, - seqPos->posInSrc, - cctx->appliedParams.cParams.windowLog, dictSize, - ZSTD_hasExtSeqProd(&cctx->appliedParams)), - "Sequence validation failed"); - } - RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, - "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); litConsumed += litLength; } /* last sequence (only literals) */ - { size_t const lastLitLength = inSeqs[idx].litLength; - litConsumed += lastLitLength; - if (checkSequences) { - seqPos->posInSrc += lastLitLength; - /* blockSize must be exactly correct (checked before calling this function) */ - RETURN_ERROR_IF((seqPos->posInSrc - startPosInSrc) != blockSize, externalSequences_invalid, "mismatch between Sequences and specified blockSize"); - } else { - /* blockSize presumed exactly correct (checked before calling this function) */ - seqPos->posInSrc += blockSize; - } - } + litConsumed += inSeqs[nbSequences-1].litLength; /* If we skipped repcode search while parsing, we need to update repcodes now */ - assert(idx >= startIdx); - if (!repcodeResolution && idx != startIdx) { + if (!repcodeResolution && nbSequences > 1) { U32* const rep = updatedRepcodes.rep; - U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */ - if (lastSeqIdx >= startIdx + 2) { + if (nbSequences >= 4) { + U32 lastSeqIdx = (U32)nbSequences - 2; /* index of last full sequence */ rep[2] = inSeqs[lastSeqIdx - 2].offset; rep[1] = inSeqs[lastSeqIdx - 1].offset; rep[0] = inSeqs[lastSeqIdx].offset; - } else if (lastSeqIdx == startIdx + 1) { + } else if (nbSequences == 3) { rep[2] = rep[0]; - rep[1] = inSeqs[lastSeqIdx - 1].offset; - rep[0] = inSeqs[lastSeqIdx].offset; + rep[1] = inSeqs[0].offset; + rep[0] = inSeqs[1].offset; } else { - assert(lastSeqIdx == startIdx); + assert(nbSequences == 2); rep[2] = rep[1]; rep[1] = rep[0]; - rep[0] = inSeqs[lastSeqIdx].offset; + rep[0] = inSeqs[0].offset; } } ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); - seqPos->idx = idx+1; return litConsumed; } -/* for tests only */ -void CCTX_resetSeqStore(ZSTD_CCtx* cctx) -{ - cctx->seqStore.sequences = cctx->seqStore.sequencesStart; - cctx->seqStore.lit = cctx->seqStore.litStart; -} - typedef size_t (*ZSTD_convertBlockSequences_f) (ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, const ZSTD_Sequence* const inSeqs, size_t nbSequences, - size_t blockSize, int const repcodeResolution); -size_t -ZSTD_convertBlockSequences_wBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, - const ZSTD_Sequence* const inSeqs, size_t nbSequences, - size_t blockSize, - int const repcodeResolution) +static size_t getNbSequencesFor1Block(const ZSTD_Sequence* seqs, size_t nbSeqs) { - return ZSTD_convertBlockSequences_wBlockDelim_internal(cctx, - seqPos, inSeqs, nbSequences, blockSize, - repcodeResolution, 0); + size_t n; + assert(seqs); + for (n=0; nappliedParams.searchForExternalRepcodes == ZSTD_ps_enable); - const ZSTD_convertBlockSequences_f convertBlockSequences = cctx->appliedParams.validateSequences ? - ZSTD_convertBlockSequences_wBlockDelim_andCheckSequences - : ZSTD_convertBlockSequences_wBlockDelim; - - DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu", nbSequences, litSize); - if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { - RETURN_ERROR(GENERIC, "This mode is only compatible with explicit delimiters"); - } assert(cctx->appliedParams.searchForExternalRepcodes != ZSTD_ps_auto); + DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu", nbSequences, litSize); + RETURN_ERROR_IF(nbSequences == 0, externalSequences_invalid, "Requires at least 1 end-of-block"); + /* Special case: empty frame */ - if (remaining == 0) { + if ((nbSequences == 1) && (inSeqs[0].litLength == 0)) { U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1); RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header"); MEM_writeLE32(op, cBlockHeader24); @@ -7262,23 +7207,21 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, cSize += ZSTD_blockHeaderSize; } - while (remaining) { + while (nbSequences) { size_t compressedSeqsSize, cBlockSize, litConsumed; - size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters, - cctx->blockSize, remaining, - inSeqs, nbSequences, seqPos); - U32 const lastBlock = (blockSize == remaining); - FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); - assert(blockSize <= remaining); + size_t nbBlockSeqs = getNbSequencesFor1Block(inSeqs, nbSequences); + U32 const lastBlock = (nbBlockSeqs == nbSequences); + FORWARD_IF_ERROR(nbBlockSeqs, "Error while trying to determine nb of sequences for a block"); + assert(nbBlockSeqs <= nbSequences); ZSTD_resetSeqStore(&cctx->seqStore); - litConsumed = convertBlockSequences(cctx, - &seqPos, - inSeqs, nbSequences, - blockSize, + litConsumed = ZSTD_convertBlockSequences(cctx, + inSeqs, nbBlockSeqs, repcodeResolution); FORWARD_IF_ERROR(litConsumed, "Bad sequence conversion"); RETURN_ERROR_IF(litConsumed > litSize, externalSequences_invalid, "discrepancy between literals buffer and Sequences"); + inSeqs += nbBlockSeqs; + nbSequences -= nbBlockSeqs; /* Note: when blockSize is very small, other variant send it uncompressed. * Here, we still send the sequences, because we don't have the original source to send it uncompressed. @@ -7286,16 +7229,18 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, * but that's complex and costly memory intensive, which goes against the objectives of this variant. */ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); - compressedSeqsSize = ZSTD_entropyCompressSeqStore_wExtLitBuffer( + + compressedSeqsSize = ZSTD_entropyCompressSeqStore_internal( op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, literals, litConsumed, - blockSize, &cctx->seqStore, &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, &cctx->appliedParams, cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */, cctx->bmi2); FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); + /* note: the spec forbids for any compressed block to be larger than maximum block size */ + if (compressedSeqsSize > cctx->blockSizeMax) compressedSeqsSize = 0; DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); litSize -= litConsumed; literals = (const char*)literals + litConsumed; @@ -7331,7 +7276,6 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, break; } else { op += cBlockSize; - remaining -= blockSize; dstCapacity -= cBlockSize; cctx->isFirstBlock = 0; } @@ -7347,7 +7291,7 @@ size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t inSeqsSize, - const void* literals, size_t litSize, size_t srcSize) + const void* literals, size_t litSize) { BYTE* op = (BYTE*)dst; size_t cSize = 0; @@ -7355,15 +7299,18 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, /* Transparent initialization stage, same as compressStream2() */ DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)", dstCapacity); assert(cctx != NULL); - FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_continue, ZSTD_CONTENTSIZE_UNKNOWN), "CCtx initialization failed"); + if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { + RETURN_ERROR(frameParameter_unsupported, "This mode is only compatible with explicit delimiters"); + } if (cctx->appliedParams.fParams.checksumFlag) { - RETURN_ERROR(frameParameter_unsupported, "this mode is incompatible with frame checksum"); + RETURN_ERROR(frameParameter_unsupported, "this mode is not compatible with frame checksum"); } /* Begin writing output, starting with frame header */ { size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, - &cctx->appliedParams, srcSize, cctx->dictID); + &cctx->appliedParams, ZSTD_CONTENTSIZE_UNKNOWN, cctx->dictID); op += frameHeaderSize; assert(frameHeaderSize <= dstCapacity); dstCapacity -= frameHeaderSize; @@ -7374,7 +7321,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, { size_t const cBlocksSize = ZSTD_compressSequencesAndLiterals_internal(cctx, op, dstCapacity, inSeqs, inSeqsSize, - literals, litSize, srcSize); + literals, litSize); FORWARD_IF_ERROR(cBlocksSize, "Compressing blocks failed!"); cSize += cBlocksSize; assert(cBlocksSize <= dstCapacity); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index bbcf4a7d5..2d4ecc89f 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -484,7 +484,7 @@ struct ZSTD_CCtx_s { size_t dictContentSize; ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */ - size_t blockSize; + size_t blockSizeMax; unsigned long long pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */ unsigned long long consumedSrcSize; unsigned long long producedCSize; @@ -1528,15 +1528,11 @@ typedef struct { size_t posInSrc; /* Number of bytes given by sequences provided so far */ } ZSTD_SequencePosition; -size_t -ZSTD_convertBlockSequences_wBlockDelim(ZSTD_CCtx* cctx, - ZSTD_SequencePosition* seqPos, +/* for benchmark */ +size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, const ZSTD_Sequence* const inSeqs, size_t nbSequences, - size_t blockSize, int const repcodeResolution); -/* for tests only */ -void CCTX_resetSeqStore(ZSTD_CCtx* cctx); /* ============================================================== * Private declarations diff --git a/lib/zstd.h b/lib/zstd.h index 68e78b3ca..3fb02619c 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1675,6 +1675,7 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * but it also features the following limitations: * - Only supports explicit delimiter mode * - Not compatible with frame checksum, which must disabled + * - Does not write the content size in frame header * - If any block is incompressible, will fail and return an error * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. * - the buffer @literals must be larger than @litSize by at least 8 bytes. @@ -1684,7 +1685,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t nbSequences, - const void* literals, size_t litSize, size_t srcSize); + const void* literals, size_t litSize); /*! ZSTD_writeSkippableFrame() : diff --git a/tests/Makefile b/tests/Makefile index f24d5cb7b..982181de8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -26,6 +26,9 @@ export ZSTD_LEGACY_SUPPORT DEBUGLEVEL ?= 2 export DEBUGLEVEL # transmit value to sub-makefiles +.PHONY: default +default: fullbench + LIBZSTD_MK_DIR := ../lib include $(LIBZSTD_MK_DIR)/libzstd.mk @@ -78,9 +81,6 @@ FUZZERTEST ?= -T200s ZSTDRTTEST = --test-large-data DECODECORPUS_TESTTIME ?= -T30 -.PHONY: default -default: fullbench - .PHONY: all all: fullbench fuzzer zstreamtest paramgrill datagen decodecorpus roundTripCrash poolTests diff --git a/tests/fullbench.c b/tests/fullbench.c index c42c923c1..3f5044c71 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -623,9 +623,9 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable); #endif assert(12 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; - (void)payload; + (void)payload; (void)srcSize; - return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, srcSize); + return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals); } static PrepResult prepConvertSequences(const void* src, size_t srcSize, int cLevel) @@ -669,22 +669,21 @@ local_convertSequences(const void* input, size_t inputSize, void* dst, size_t dstCapacity, void* payload) { - ZSTD_SequencePosition seqPos = { 0, 0 , 0 }; const char* ip = input; size_t const blockSize = MEM_read32(ip); size_t const nbSeqs = MEM_read32(ip+=4); const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4); ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); - CCTX_resetSeqStore(g_zcc); + ZSTD_resetSeqStore(&g_zcc->seqStore); ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); # if 0 /* for tests */ ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable); #endif assert(8 + nbSeqs * sizeof(ZSTD_Sequence) == inputSize); (void)inputSize; (void)dst; (void)dstCapacity; - (void)payload; + (void)payload; (void)blockSize; - return ZSTD_convertBlockSequences_wBlockDelim(g_zcc, &seqPos, seqs, nbSeqs, blockSize, 0); + return ZSTD_convertBlockSequences(g_zcc, seqs, nbSeqs, 0); } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index b20031708..09572e909 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3909,35 +3909,21 @@ static int basicUnitTests(U32 const seed, double compressibility) FUZ_transferLiterals(litBuffer, decompressSize, CNBuffer, srcSize, seqs, nbSeqs); /* not enough literals: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1, srcSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: not enough literals provided\n"); goto _output_error; } /* too many literals: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1, srcSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: too many literals provided\n"); goto _output_error; } - /* too short srcSize: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize, srcSize-1); - if (!ZSTD_isError(compressedSize)) { - DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too short\n"); - goto _output_error; - } - - /* too large srcSize: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize, srcSize+1); - if (!ZSTD_isError(compressedSize)) { - DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too short\n"); - goto _output_error; - } - /* correct amount of literals: should compress successfully */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize); if (ZSTD_isError(compressedSize)) { DISPLAY("Error in ZSTD_compressSequencesAndLiterals()\n"); goto _output_error; From b7b4e8634786024499dd42d479a2be3a2edae92c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 17 Dec 2024 22:08:43 -0800 Subject: [PATCH 255/405] fixed minor conversion warning --- lib/compress/zstd_compress.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 70a9731bf..867e7fbf1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7299,7 +7299,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, /* Transparent initialization stage, same as compressStream2() */ DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)", dstCapacity); assert(cctx != NULL); - FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_continue, ZSTD_CONTENTSIZE_UNKNOWN), "CCtx initialization failed"); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_continue, 0), "CCtx initialization failed"); if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { RETURN_ERROR(frameParameter_unsupported, "This mode is only compatible with explicit delimiters"); @@ -7350,7 +7350,6 @@ size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush); } - size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) { ZSTD_inBuffer input = inBuffer_forEndFlush(zcs); From ad023b392fc5081f53ebc30f68d6e8dfda256104 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 17 Dec 2024 22:27:09 -0800 Subject: [PATCH 256/405] fixed minor error in one benchmark scenario --- tests/fullbench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 3f5044c71..9505110ec 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -659,7 +659,7 @@ static PrepResult prepConvertSequences(const void* src, size_t srcSize, int cLev MEM_write32((char*)prepBuffer+4, (U32)nbSeqs); memcpy(seqs + nbSeqs, src, srcSize); r.prepBuffer = prepBuffer; - r.prepSize = 8 + sizeof(ZSTD_Sequence)*nbSeqs + srcSize; + r.prepSize = 8 + sizeof(ZSTD_Sequence) * nbSeqs; r.fixedOrigSize = blockSize; return r; } From 0a54f6f288bab194e1c4edcd03cedc8d084c2d6f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 07:26:38 -0800 Subject: [PATCH 257/405] ZSTD_compressSequencesAndLiterals requires srcSize as parameter this makes it possible to adjust windowSize to its tightest. --- doc/zstd_manual.html | 2 +- lib/compress/zstd_compress.c | 6 +++--- lib/zstd.h | 3 +-- tests/fullbench.c | 8 ++++---- tests/fuzzer.c | 6 +++--- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 2c4c4b0e8..a50dd3c5d 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1421,7 +1421,7 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t nbSequences, - const void* literals, size_t litSize); + const void* literals, size_t litSize, size_t srcSize);

    This is a variant of ZSTD_compressSequences() which, instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), aka all the literals, already extracted and laid out into a single continuous buffer. diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 867e7fbf1..655adf34b 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7291,7 +7291,7 @@ size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t inSeqsSize, - const void* literals, size_t litSize) + const void* literals, size_t litSize, size_t srcSize) { BYTE* op = (BYTE*)dst; size_t cSize = 0; @@ -7299,7 +7299,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, /* Transparent initialization stage, same as compressStream2() */ DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)", dstCapacity); assert(cctx != NULL); - FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_continue, 0), "CCtx initialization failed"); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { RETURN_ERROR(frameParameter_unsupported, "This mode is only compatible with explicit delimiters"); @@ -7310,7 +7310,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, /* Begin writing output, starting with frame header */ { size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, - &cctx->appliedParams, ZSTD_CONTENTSIZE_UNKNOWN, cctx->dictID); + &cctx->appliedParams, srcSize, cctx->dictID); op += frameHeaderSize; assert(frameHeaderSize <= dstCapacity); dstCapacity -= frameHeaderSize; diff --git a/lib/zstd.h b/lib/zstd.h index 3fb02619c..68e78b3ca 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1675,7 +1675,6 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * but it also features the following limitations: * - Only supports explicit delimiter mode * - Not compatible with frame checksum, which must disabled - * - Does not write the content size in frame header * - If any block is incompressible, will fail and return an error * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. * - the buffer @literals must be larger than @litSize by at least 8 bytes. @@ -1685,7 +1684,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t nbSequences, - const void* literals, size_t litSize); + const void* literals, size_t litSize, size_t srcSize); /*! ZSTD_writeSkippableFrame() : diff --git a/tests/fullbench.c b/tests/fullbench.c index 9505110ec..8601af769 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -608,8 +608,8 @@ static PrepResult prepSequencesAndLiterals(const void* src, size_t srcSize, int static size_t local_compressSequencesAndLiterals(const void* input, size_t inputSize, - void* dst, size_t dstCapacity, - void* payload) + void* dst, size_t dstCapacity, + void* payload) { const char* ip = input; size_t srcSize = MEM_read32(ip); @@ -623,9 +623,9 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable); #endif assert(12 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; - (void)payload; (void)srcSize; + (void)payload; - return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals); + return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, srcSize); } static PrepResult prepConvertSequences(const void* src, size_t srcSize, int cLevel) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 09572e909..4901376ff 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3909,21 +3909,21 @@ static int basicUnitTests(U32 const seed, double compressibility) FUZ_transferLiterals(litBuffer, decompressSize, CNBuffer, srcSize, seqs, nbSeqs); /* not enough literals: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1, srcSize); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: not enough literals provided\n"); goto _output_error; } /* too many literals: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1, srcSize); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: too many literals provided\n"); goto _output_error; } /* correct amount of literals: should compress successfully */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize); if (ZSTD_isError(compressedSize)) { DISPLAY("Error in ZSTD_compressSequencesAndLiterals()\n"); goto _output_error; From a80f55f47d7d4076c19a000459b88e28e8c95eee Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 07:38:14 -0800 Subject: [PATCH 258/405] added a test for ZSTD_compressSequencesAndLiterals checks that srcSize is present in the frame header and bounds the window size. --- tests/fuzzer.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4901376ff..7907dbfad 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3880,7 +3880,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : ZSTD_compressSequencesAndLiterals : ", testNb++); { - const size_t srcSize = 500 KB; + const size_t srcSize = 497000; const BYTE* const src = (BYTE*)CNBuffer; BYTE* const dst = (BYTE*)compressedBuffer; const size_t dstCapacity = ZSTD_compressBound(srcSize); @@ -3929,6 +3929,21 @@ static int basicUnitTests(U32 const seed, double compressibility) goto _output_error; } } + { ZSTD_frameHeader zfh; + size_t const zfhStatus = ZSTD_getFrameHeader(&zfh, dst, compressedSize); + if (zfhStatus != 0) { + DISPLAY("Error reading frame header\n"); + goto _output_error; + } + if (zfh.frameContentSize != srcSize) { + DISPLAY("Error: ZSTD_compressSequencesAndLiterals() did not report srcSize in the frame header\n"); + goto _output_error; + } + if (zfh.windowSize > srcSize) { + DISPLAY("Error: ZSTD_compressSequencesAndLiterals() did not resized window size to smaller contentSize\n"); + goto _output_error; + } + } { size_t const dSize = ZSTD_decompress(decompressBuffer, decompressSize, dst, compressedSize); if (ZSTD_isError(dSize)) { DISPLAY("Error during decompression of frame produced by ZSTD_compressSequencesAndLiterals()\n"); From b339efff2bc9d11ce091bca62328c1884a38b5f3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 09:45:28 -0800 Subject: [PATCH 259/405] add dedicated error code for special case ZSTD_compressSequencesAndLiterals() cannot produce an uncompressed block --- doc/zstd_manual.html | 1 - lib/common/error_private.c | 1 + lib/compress/zstd_compress.c | 2 +- lib/zstd_errors.h | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index a50dd3c5d..30908e0aa 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1431,7 +1431,6 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, but it also features the following limitations: - Only supports explicit delimiter mode - Not compatible with frame checksum, which must disabled - - Does not write the content size in frame header - If any block is incompressible, will fail and return an error - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. - the buffer @literals must be larger than @litSize by at least 8 bytes. diff --git a/lib/common/error_private.c b/lib/common/error_private.c index 075fc5ef4..7e7f24f67 100644 --- a/lib/common/error_private.c +++ b/lib/common/error_private.c @@ -40,6 +40,7 @@ const char* ERR_getErrorString(ERR_enum code) case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported"; case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large"; case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small"; + case PREFIX(cannotProduce_uncompressedBlock): return "This mode cannot generate an uncompressed block"; case PREFIX(stabilityCondition_notRespected): return "pledged buffer stability condition is not respected"; case PREFIX(dictionary_corrupted): return "Dictionary is corrupted"; case PREFIX(dictionary_wrong): return "Dictionary mismatch"; diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 655adf34b..d5adeb68e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7254,7 +7254,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, * but it's complex, and memory hungry, killing the purpose of this variant. * Current outcome: generate an error code. */ - RETURN_ERROR(dstSize_tooSmall, "Data is not compressible"); /* note: error code could be clearer */ + RETURN_ERROR(cannotProduce_uncompressedBlock, "ZSTD_compressSequencesAndLiterals cannot generate an uncompressed block"); } else { U32 cBlockHeader; assert(compressedSeqsSize > 1); /* no RLE */ diff --git a/lib/zstd_errors.h b/lib/zstd_errors.h index 20e488f15..8ebc95cbb 100644 --- a/lib/zstd_errors.h +++ b/lib/zstd_errors.h @@ -76,6 +76,7 @@ typedef enum { ZSTD_error_tableLog_tooLarge = 44, ZSTD_error_maxSymbolValue_tooLarge = 46, ZSTD_error_maxSymbolValue_tooSmall = 48, + ZSTD_error_cannotProduce_uncompressedBlock = 49, ZSTD_error_stabilityCondition_notRespected = 50, ZSTD_error_stage_wrong = 60, ZSTD_error_init_missing = 62, From ab0f1798e8ec85dc03d39412513c84a5ef5539ff Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 14:41:33 -0800 Subject: [PATCH 260/405] ensure that srcSize is controlled --- lib/compress/zstd_compress.c | 89 +++++++++++++++++++++--------------- tests/fullbench.c | 3 +- tests/fuzzer.c | 14 ++++++ 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d5adeb68e..5ef7337cc 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7093,16 +7093,16 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, } /* + * @return: 0 on success, or an error code. * Note: Sequence validation functionality has been disabled (removed). - * This is helpful to find back simplicity, leading to performance. + * This is helpful to generate a lean main pipeline, improving performance. * It may be re-inserted later. */ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, const ZSTD_Sequence* const inSeqs, size_t nbSequences, - int const repcodeResolution) + int repcodeResolution) { Repcodes_t updatedRepcodes; - size_t litConsumed = 0; size_t seqNb = 0; DEBUGLOG(5, "ZSTD_convertBlockSequences (nbSequences = %zu)", nbSequences); @@ -7133,12 +7133,8 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); - litConsumed += litLength; } - /* last sequence (only literals) */ - litConsumed += inSeqs[nbSequences-1].litLength; - /* If we skipped repcode search while parsing, we need to update repcodes now */ if (!repcodeResolution && nbSequences > 1) { U32* const rep = updatedRepcodes.rep; @@ -7162,24 +7158,40 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); - return litConsumed; + return 0; } -typedef size_t (*ZSTD_convertBlockSequences_f) (ZSTD_CCtx* cctx, - const ZSTD_Sequence* const inSeqs, size_t nbSequences, - int const repcodeResolution); +typedef struct { + size_t nbSequences; + size_t blockSize; + size_t litSize; +} BlockSummary; -static size_t getNbSequencesFor1Block(const ZSTD_Sequence* seqs, size_t nbSeqs) +static BlockSummary get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) { + size_t blockSize = 0; + size_t litSize = 0; size_t n; assert(seqs); for (n=0; nappliedParams.searchForExternalRepcodes == ZSTD_ps_enable); @@ -7208,31 +7221,32 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, } while (nbSequences) { - size_t compressedSeqsSize, cBlockSize, litConsumed; - size_t nbBlockSeqs = getNbSequencesFor1Block(inSeqs, nbSequences); - U32 const lastBlock = (nbBlockSeqs == nbSequences); - FORWARD_IF_ERROR(nbBlockSeqs, "Error while trying to determine nb of sequences for a block"); - assert(nbBlockSeqs <= nbSequences); + size_t compressedSeqsSize, cBlockSize, conversionStatus; + BlockSummary const block = get1BlockSummary(inSeqs, nbSequences); + U32 const lastBlock = (block.nbSequences == nbSequences); + FORWARD_IF_ERROR(block.nbSequences, "Error while trying to determine nb of sequences for a block"); + assert(block.nbSequences <= nbSequences); + RETURN_ERROR_IF(block.litSize > litSize, externalSequences_invalid, "discrepancy: Sequences require more literals than present in buffer"); ZSTD_resetSeqStore(&cctx->seqStore); - litConsumed = ZSTD_convertBlockSequences(cctx, - inSeqs, nbBlockSeqs, + conversionStatus = ZSTD_convertBlockSequences(cctx, + inSeqs, block.nbSequences, repcodeResolution); - FORWARD_IF_ERROR(litConsumed, "Bad sequence conversion"); - RETURN_ERROR_IF(litConsumed > litSize, externalSequences_invalid, "discrepancy between literals buffer and Sequences"); - inSeqs += nbBlockSeqs; - nbSequences -= nbBlockSeqs; + FORWARD_IF_ERROR(conversionStatus, "Bad sequence conversion"); + inSeqs += block.nbSequences; + nbSequences -= block.nbSequences; + remaining -= block.blockSize; /* Note: when blockSize is very small, other variant send it uncompressed. * Here, we still send the sequences, because we don't have the original source to send it uncompressed. - * One could imagine it possible to reproduce the source from the sequences, - * but that's complex and costly memory intensive, which goes against the objectives of this variant. */ + * One could imagine in theory reproducing the source from the sequences, + * but that's complex and costly memory intensive, and goes against the objectives of this variant. */ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); compressedSeqsSize = ZSTD_entropyCompressSeqStore_internal( op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, - literals, litConsumed, + literals, block.litSize, &cctx->seqStore, &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, &cctx->appliedParams, @@ -7242,8 +7256,8 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, /* note: the spec forbids for any compressed block to be larger than maximum block size */ if (compressedSeqsSize > cctx->blockSizeMax) compressedSeqsSize = 0; DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); - litSize -= litConsumed; - literals = (const char*)literals + litConsumed; + litSize -= block.litSize; + literals = (const char*)literals + block.litSize; /* Note: difficult to check source for RLE block when only Literals are provided, * but it could be considered from analyzing the sequence directly */ @@ -7271,18 +7285,19 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, } cSize += cBlockSize; + op += cBlockSize; + dstCapacity -= cBlockSize; + cctx->isFirstBlock = 0; + DEBUGLOG(5, "cSize running total: %zu (remaining dstCapacity=%zu)", cSize, dstCapacity); if (lastBlock) { + assert(nbSequences == 0); break; - } else { - op += cBlockSize; - dstCapacity -= cBlockSize; - cctx->isFirstBlock = 0; } - DEBUGLOG(5, "cSize running total: %zu (remaining dstCapacity=%zu)", cSize, dstCapacity); } RETURN_ERROR_IF(litSize != 0, externalSequences_invalid, "literals must be entirely and exactly consumed"); + RETURN_ERROR_IF(remaining != 0, externalSequences_invalid, "Sequences must represent a total of exactly srcSize=%zu", srcSize); DEBUGLOG(4, "cSize final total: %zu", cSize); return cSize; } @@ -7321,7 +7336,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, { size_t const cBlocksSize = ZSTD_compressSequencesAndLiterals_internal(cctx, op, dstCapacity, inSeqs, inSeqsSize, - literals, litSize); + literals, litSize, srcSize); FORWARD_IF_ERROR(cBlocksSize, "Compressing blocks failed!"); cSize += cBlocksSize; assert(cBlocksSize <= dstCapacity); diff --git a/tests/fullbench.c b/tests/fullbench.c index 8601af769..4ac686a4d 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -683,7 +683,8 @@ local_convertSequences(const void* input, size_t inputSize, (void)dst; (void)dstCapacity; (void)payload; (void)blockSize; - return ZSTD_convertBlockSequences(g_zcc, seqs, nbSeqs, 0); + (void)ZSTD_convertBlockSequences(g_zcc, seqs, nbSeqs, 0); + return nbSeqs; } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 7907dbfad..335fbd5c4 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3922,6 +3922,20 @@ static int basicUnitTests(U32 const seed, double compressibility) goto _output_error; } + /* srcSize too large: must fail */ + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize+1); + if (!ZSTD_isError(compressedSize)) { + DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too large\n"); + goto _output_error; + } + + /* srcSize too small: must fail */ + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize-1); + if (!ZSTD_isError(compressedSize)) { + DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too small\n"); + goto _output_error; + } + /* correct amount of literals: should compress successfully */ compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize); if (ZSTD_isError(compressedSize)) { From 52a9bc6fca23bf0f9d51be0fe97a525db85aa12b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 15:00:12 -0800 Subject: [PATCH 261/405] fixed minor error in preparation of one fullbench scenario --- tests/fullbench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 4ac686a4d..05d6bf027 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -594,7 +594,7 @@ static PrepResult prepSequencesAndLiterals(const void* src, size_t srcSize, int for (n=0; n Date: Thu, 19 Dec 2024 15:39:57 -0800 Subject: [PATCH 262/405] add a check, to return an error if Sequence validation is enabled since ZSTD_compressSequencesAndLiterals() doesn't support it. --- doc/zstd_manual.html | 3 ++- lib/compress/zstd_compress.c | 3 +++ lib/zstd.h | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 30908e0aa..dd6f9d7ab 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1430,7 +1430,8 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, It's a speed optimization, useful when the right conditions are met, but it also features the following limitations: - Only supports explicit delimiter mode - - Not compatible with frame checksum, which must disabled + - Currently does not support Sequences validation (so input Sequences are trusted) + - Not compatible with frame checksum, which must be disabled - If any block is incompressible, will fail and return an error - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. - the buffer @literals must be larger than @litSize by at least 8 bytes. diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 5ef7337cc..b5831650f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7319,6 +7319,9 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { RETURN_ERROR(frameParameter_unsupported, "This mode is only compatible with explicit delimiters"); } + if (cctx->appliedParams.validateSequences) { + RETURN_ERROR(parameter_unsupported, "This mode is not compatible with Sequence validation"); + } if (cctx->appliedParams.fParams.checksumFlag) { RETURN_ERROR(frameParameter_unsupported, "this mode is not compatible with frame checksum"); } diff --git a/lib/zstd.h b/lib/zstd.h index 68e78b3ca..feb1ae17a 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1674,7 +1674,8 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * It's a speed optimization, useful when the right conditions are met, * but it also features the following limitations: * - Only supports explicit delimiter mode - * - Not compatible with frame checksum, which must disabled + * - Currently does not support Sequences validation (so input Sequences are trusted) + * - Not compatible with frame checksum, which must be disabled * - If any block is incompressible, will fail and return an error * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. * - the buffer @literals must be larger than @litSize by at least 8 bytes. From b7a9e69d8dc8b61be9d341a4e7a56350fb1e545e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 15:55:11 -0800 Subject: [PATCH 263/405] added parameter litCapacity to ZSTD_compressSequencesAndLiterals() to enforce the litCapacity >= litSize+8 condition. --- doc/zstd_manual.html | 6 ++++-- lib/compress/zstd_compress.c | 12 ++++++++---- lib/zstd.h | 6 ++++-- tests/fullbench.c | 4 ++-- tests/fuzzer.c | 10 +++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index dd6f9d7ab..ecb2b622c 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1421,7 +1421,8 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t nbSequences, - const void* literals, size_t litSize, size_t srcSize); + const void* literals, size_t litSize, size_t litCapacity, + size_t decompressedSize);

    This is a variant of ZSTD_compressSequences() which, instead of receiving (src,srcSize) as input parameter, receives (literals,litSize), aka all the literals, already extracted and laid out into a single continuous buffer. @@ -1434,7 +1435,8 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, - Not compatible with frame checksum, which must be disabled - If any block is incompressible, will fail and return an error - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. - - the buffer @literals must be larger than @litSize by at least 8 bytes. + - the buffer @literals must have a size @litCapacity which is larger than @litSize by at least 8 bytes. + - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error. @return : final compressed size, or a ZSTD error code.


    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b5831650f..b5e88325d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7306,7 +7306,8 @@ size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t inSeqsSize, - const void* literals, size_t litSize, size_t srcSize) + const void* literals, size_t litSize, size_t litCapacity, + size_t decompressedSize) { BYTE* op = (BYTE*)dst; size_t cSize = 0; @@ -7314,7 +7315,10 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, /* Transparent initialization stage, same as compressStream2() */ DEBUGLOG(4, "ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)", dstCapacity); assert(cctx != NULL); - FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); + if (litCapacity < litSize) { + RETURN_ERROR(workSpace_tooSmall, "literals buffer is not large enough: must be at least 8 bytes larger than litSize (risk of read out-of-bound)"); + } + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, decompressedSize), "CCtx initialization failed"); if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) { RETURN_ERROR(frameParameter_unsupported, "This mode is only compatible with explicit delimiters"); @@ -7328,7 +7332,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, /* Begin writing output, starting with frame header */ { size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, - &cctx->appliedParams, srcSize, cctx->dictID); + &cctx->appliedParams, decompressedSize, cctx->dictID); op += frameHeaderSize; assert(frameHeaderSize <= dstCapacity); dstCapacity -= frameHeaderSize; @@ -7339,7 +7343,7 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, { size_t const cBlocksSize = ZSTD_compressSequencesAndLiterals_internal(cctx, op, dstCapacity, inSeqs, inSeqsSize, - literals, litSize, srcSize); + literals, litSize, decompressedSize); FORWARD_IF_ERROR(cBlocksSize, "Compressing blocks failed!"); cSize += cBlocksSize; assert(cBlocksSize <= dstCapacity); diff --git a/lib/zstd.h b/lib/zstd.h index feb1ae17a..36668b85b 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1678,14 +1678,16 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * - Not compatible with frame checksum, which must be disabled * - If any block is incompressible, will fail and return an error * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. - * - the buffer @literals must be larger than @litSize by at least 8 bytes. + * - the buffer @literals must have a size @litCapacity which is larger than @litSize by at least 8 bytes. + * - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t nbSequences, - const void* literals, size_t litSize, size_t srcSize); + const void* literals, size_t litSize, size_t litCapacity, + size_t decompressedSize); /*! ZSTD_writeSkippableFrame() : diff --git a/tests/fullbench.c b/tests/fullbench.c index 05d6bf027..5683eca25 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -612,7 +612,7 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, void* payload) { const char* ip = input; - size_t srcSize = MEM_read32(ip); + size_t decompressedSize = MEM_read32(ip); size_t nbSeqs = MEM_read32(ip+=4); size_t nbLiterals = MEM_read32(ip+=4); const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4); @@ -625,7 +625,7 @@ local_compressSequencesAndLiterals(const void* input, size_t inputSize, assert(12 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize; (void)payload; - return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, srcSize); + return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, nbLiterals + 8, decompressedSize); } static PrepResult prepConvertSequences(const void* src, size_t srcSize, int cLevel) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 335fbd5c4..6d165aea4 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3909,35 +3909,35 @@ static int basicUnitTests(U32 const seed, double compressibility) FUZ_transferLiterals(litBuffer, decompressSize, CNBuffer, srcSize, seqs, nbSeqs); /* not enough literals: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1, srcSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1, decompressSize, srcSize); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: not enough literals provided\n"); goto _output_error; } /* too many literals: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1, srcSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1, decompressSize, srcSize); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: too many literals provided\n"); goto _output_error; } /* srcSize too large: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize+1); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, decompressSize, srcSize+1); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too large\n"); goto _output_error; } /* srcSize too small: must fail */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize-1); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, decompressSize, srcSize-1); if (!ZSTD_isError(compressedSize)) { DISPLAY("ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too small\n"); goto _output_error; } /* correct amount of literals: should compress successfully */ - compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, srcSize); + compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, decompressSize, srcSize); if (ZSTD_isError(compressedSize)) { DISPLAY("Error in ZSTD_compressSequencesAndLiterals()\n"); goto _output_error; From 522adc34eb83c9145dfe1be36412eefa642413e1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 19 Dec 2024 16:11:46 -0800 Subject: [PATCH 264/405] minor: use MEM_writeLE24() so that an empty frame needs only 3 bytes of dstCapacity. --- lib/compress/zstd_compress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b5e88325d..fcd8035fa 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7213,8 +7213,8 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, /* Special case: empty frame */ if ((nbSequences == 1) && (inSeqs[0].litLength == 0)) { U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1); - RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header"); - MEM_writeLE32(op, cBlockHeader24); + RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, "No room for empty frame block header"); + MEM_writeLE24(op, cBlockHeader24); op += ZSTD_blockHeaderSize; dstCapacity -= ZSTD_blockHeaderSize; cSize += ZSTD_blockHeaderSize; From 47cbfc87a9c7ecb5a9058ad8e55ba19dcaf6a861 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 20 Dec 2024 09:03:26 -0800 Subject: [PATCH 265/405] restore invocation of ZSTD_entropyCompressSeqStore() in the ZSTD_compressSequences() pipeline --- lib/compress/zstd_compress.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index fcd8035fa..3af69c1ae 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3015,7 +3015,7 @@ static size_t ZSTD_entropyCompressSeqStore_wExtLitBuffer( void* dst, size_t dstCapacity, const void* literals, size_t litSize, - size_t srcSize, + size_t blockSize, const SeqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, @@ -3032,14 +3032,14 @@ ZSTD_entropyCompressSeqStore_wExtLitBuffer( /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block. * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block. */ - if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) { + if ((cSize == ERROR(dstSize_tooSmall)) & (blockSize <= dstCapacity)) { DEBUGLOG(4, "not enough dstCapacity (%zu) for ZSTD_entropyCompressSeqStore_internal()=> do not compress block", dstCapacity); return 0; /* block not compressed */ } FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSeqStore_internal failed"); /* Check compressibility */ - { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); + { size_t const maxCSize = blockSize - ZSTD_minGain(blockSize, cctxParams->cParams.strategy); if (cSize >= maxCSize) return 0; /* block not compressed */ } DEBUGLOG(5, "ZSTD_entropyCompressSeqStore() cSize: %zu", cSize); @@ -6980,13 +6980,11 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, } RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); - compressedSeqsSize = ZSTD_entropyCompressSeqStore_wExtLitBuffer( - op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, - cctx->seqStore.litStart, (size_t)(cctx->seqStore.lit - cctx->seqStore.litStart), - blockSize, - &cctx->seqStore, + compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore, &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, &cctx->appliedParams, + op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, + blockSize, cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */, cctx->bmi2); FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); From f0937b83d9a32cb2b59f99bbc4db717ae6e83c9b Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 20 Dec 2024 09:40:32 -0800 Subject: [PATCH 266/405] [cmake] Fix -z noexecstack portability Summary: Issue reported by @ryandesign and @MarcusCalhoun-Lopez. CMake doesn't support spaces in flags. This caused older versions of gcc to ignore the unknown flag "-z noexecstack" on MacOS since it was interpreted as a single flag, not two separate flags. Then, during compilation it was treated as "-z" "noexecstack", which was correctly forwarded to the linker. But the MacOS linker does not support `-z noexecstack` so compilation failed. The fix is to use `-Wl,-z,noexecstack`. This is never misinterpreted by a compiler. However, not all compilers support this syntax to forward flags to the linker. To fix this issue, we check if all the relevant `noexecstack` flags have been successfully set, and if they haven't we disable assembly. See also PR#4056 and PR#4061. I decided to go a different route because this is simpler. It might not successfully set these flags on some compilers, but in that case it also disables assembly, so they aren't required. Test Plan: ``` mkdir build-cmake cmake ../build/cmake/CMakeLists.txt make -j ``` See that the linker flag is successfully detected & that assembly is enabled. Run the same commands on MacOS which doesn't support `-Wl,-z,noexecstack` and see that everything compiles and that `LD_FLAG_WL_Z_NOEXECSTACK` and `ZSTD_HAS_NOEXECSTACK` are both false. --- .../CMakeModules/AddZstdCompilationFlags.cmake | 18 +++++++++++++++++- build/cmake/lib/CMakeLists.txt | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake index 153c51bae..5f381c656 100644 --- a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake +++ b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake @@ -50,6 +50,10 @@ function(EnableCompilerFlag _flag _C _CXX _LD) endfunction() macro(ADD_ZSTD_COMPILATION_FLAGS) + # We set ZSTD_HAS_NOEXECSTACK if we are certain we've set all the required + # compiler flags to mark the stack as non-executable. + set(ZSTD_HAS_NOEXECSTACK false) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" OR MINGW) #Not only UNIX but also WIN32 for MinGW # It's possible to select the exact standard used for compilation. # It's not necessary, but can be employed for specific purposes. @@ -75,10 +79,22 @@ macro(ADD_ZSTD_COMPILATION_FLAGS) endif () # Add noexecstack flags # LDFLAGS - EnableCompilerFlag("-z noexecstack" false false true) + EnableCompilerFlag("-Wl,-z,noexecstack" false false true) # CFLAGS & CXXFLAGS EnableCompilerFlag("-Qunused-arguments" true true false) EnableCompilerFlag("-Wa,--noexecstack" true true false) + # NOTE: Using 3 nested ifs because the variables are sometimes + # empty if the condition is false, and sometimes equal to false. + # This implicitly converts them to truthy values. There may be + # a better way to do this, but this reliably works. + if (${LD_FLAG_WL_Z_NOEXECSTACK}) + if (${C_FLAG_WA_NOEXECSTACK}) + if (${CXX_FLAG_WA_NOEXECSTACK}) + # We've succeeded in marking the stack as non-executable + set(ZSTD_HAS_NOEXECSTACK true) + endif() + endif() + endif() elseif (MSVC) # Add specific compilation flags for Windows Visual set(ACTIVATE_MULTITHREADED_COMPILATION "ON" CACHE BOOL "activate multi-threaded compilation (/MP flag)") diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 43b14d175..d07b1f5ff 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -39,7 +39,7 @@ file(GLOB DecompressSources ${LIBRARY_DIR}/decompress/*.c) if (MSVC) add_compile_options(-DZSTD_DISABLE_ASM) else () - if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|AMD64.*|x86_64.*|X86_64.*") + if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|AMD64.*|x86_64.*|X86_64.*" AND ${ZSTD_HAS_NOEXECSTACK}) set(DecompressSources ${DecompressSources} ${LIBRARY_DIR}/decompress/huf_decompress_amd64.S) else() add_compile_options(-DZSTD_DISABLE_ASM) From f8725e80cc6089ec21903e292a58a21d322e302b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 23 Dec 2024 18:42:51 -0800 Subject: [PATCH 267/405] added fuzzer test for compressSequencesAndLiterals() piggy-backing onto existing compressSequences() fuzzer test --- tests/fuzz/Makefile | 8 +-- tests/fuzz/sequence_compression_api.c | 83 ++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index 1333675d0..a64d2d252 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -28,6 +28,9 @@ LIBZSTD_MK_DIR = ../../lib DEBUGLEVEL ?= 2 ZSTD_LEGACY_SUPPORT ?= 1 +.PHONY: default +default: all + include $(LIBZSTD_MK_DIR)/libzstd.mk PRGDIR = ../../programs @@ -101,10 +104,6 @@ FUZZ_RT_OBJ9 := $(FUZZ_RT_OBJ8:.c=.o) FUZZ_RT_OBJ10 := $(THIRD_PARTY_SEQ_PROD_OBJ) $(FUZZ_RT_OBJ9) FUZZ_ROUND_TRIP_OBJ := $(FUZZ_RT_OBJ10:.S=.o) -.PHONY: default all clean cleanall - -default: all - FUZZ_TARGETS := \ simple_round_trip \ stream_round_trip \ @@ -128,6 +127,7 @@ FUZZ_TARGETS := \ decompress_cross_format \ generate_sequences +.PHONY: all clean cleanall all: libregression.a $(FUZZ_TARGETS) rt_lib_common_%.o: $(LIB_SRCDIR)/common/%.c diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index 5e5e1e604..32710afb9 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -155,7 +155,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, if (mode == ZSTD_sf_explicitBlockDelimiters) { /* ensure that no sequence can be larger than one block */ literalsSizeLimit = MIN(literalsSizeLimit, blockSizeMax/2); - matchLengthMax = MIN(matchLengthMax, blockSizeMax/2); + matchLengthMax = MIN(matchLengthMax, (uint32_t)blockSizeMax/2); } while ( nbSeqGenerated < ZSTD_FUZZ_MAX_NBSEQ - 3 /* extra room for explicit delimiters */ @@ -171,7 +171,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, if (bytesGenerated > ZSTD_FUZZ_GENERATED_SRC_MAXSIZE) { break; } - offsetBound = (bytesGenerated > windowSize) ? windowSize : bytesGenerated + (uint32_t)dictSize; + offsetBound = (bytesGenerated > windowSize) ? (uint32_t)windowSize : bytesGenerated + (uint32_t)dictSize; offset = FUZZ_dataProducer_uint32Range(producer, 1, offsetBound); if (dictSize > 0 && bytesGenerated <= windowSize) { /* Prevent match length from being such that it would be associated with an offset too large @@ -180,7 +180,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, */ const size_t bytesToReachWindowSize = windowSize - bytesGenerated; if (bytesToReachWindowSize < ZSTD_MINMATCH_MIN) { - const uint32_t newOffsetBound = offsetBound > windowSize ? windowSize : offsetBound; + const uint32_t newOffsetBound = offsetBound > windowSize ? (uint32_t)windowSize : offsetBound; offset = FUZZ_dataProducer_uint32Range(producer, 1, newOffsetBound); } else { matchBound = MIN(matchLengthMax, (uint32_t)bytesToReachWindowSize); @@ -201,14 +201,14 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, if (blockSize + seqSize > blockSizeMax) { /* reaching limit : must end block now */ const ZSTD_Sequence endBlock = {0, 0, 0, 0}; generatedSequences[nbSeqGenerated++] = endBlock; - blockSize = seqSize; + blockSize = (uint32_t)seqSize; } if (split) { const ZSTD_Sequence endBlock = {0, lastLits, 0, 0}; generatedSequences[nbSeqGenerated++] = endBlock; assert(lastLits <= seq.litLength); seq.litLength -= lastLits; - blockSize = seqSize - lastLits; + blockSize = (uint32_t)(seqSize - lastLits); } else { blockSize += seqSize; } @@ -227,10 +227,67 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, return nbSeqGenerated; } +static size_t +transferLiterals(void* dst, size_t dstCapacity, const ZSTD_Sequence* seqs, size_t nbSeqs, const void* src, size_t srcSize) +{ + size_t n; + char* op = dst; + char* const oend = op + dstCapacity; + const char* ip = src; + const char* const iend = ip + srcSize; + for (n=0; n= 8); + return (size_t)(op - (char*)dst); +} + +static size_t roundTripTest_compressSequencesAndLiterals( + void* result, size_t resultCapacity, + void* compressed, size_t compressedCapacity, + const void* src, size_t srcSize, + const ZSTD_Sequence* seqs, size_t nbSeqs, + ZSTD_SequenceFormat_e mode) +{ + size_t const litCapacity = srcSize + 8; + void* literals = malloc(litCapacity); + size_t cSize, litSize; + + assert(literals); + litSize = transferLiterals(literals, litCapacity, seqs, nbSeqs, src, srcSize); + + cSize = ZSTD_compressSequencesAndLiterals(cctx, + compressed, compressedCapacity, + seqs, nbSeqs, + literals, litSize, litCapacity, srcSize); + if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall) + && (mode == ZSTD_sf_explicitBlockDelimiters) ) { + /* Valid scenario : in explicit delimiter mode, + * it might be possible for the compressed size to outgrow dstCapacity. + * In which case, it's still a valid fuzzer scenario, + * but no roundtrip shall be possible */ + return 0; + } + /* round-trip */ + FUZZ_ZASSERT(cSize); + { size_t const dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize); + FUZZ_ZASSERT(dSize); + FUZZ_ASSERT_MSG(dSize == srcSize, "Incorrect regenerated size"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, result, srcSize), "Corruption!"); + return dSize; + } +} + static size_t roundTripTest(void* result, size_t resultCapacity, void* compressed, size_t compressedCapacity, const void* src, size_t srcSize, - const ZSTD_Sequence* seqs, size_t seqSize, + const ZSTD_Sequence* seqs, size_t nbSeqs, unsigned hasDict, ZSTD_SequenceFormat_e mode) { @@ -242,8 +299,16 @@ static size_t roundTripTest(void* result, size_t resultCapacity, FUZZ_ZASSERT(ZSTD_DCtx_refDDict(dctx, ddict)); } + { int blockMode; + /* compressSequencesAndLiterals() only supports explicitBlockDelimiters */ + FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_blockDelimiters, &blockMode)); + if (blockMode == ZSTD_sf_explicitBlockDelimiters) { + FUZZ_ZASSERT(roundTripTest_compressSequencesAndLiterals(result, resultCapacity, compressed, compressedCapacity, src, srcSize, seqs, nbSeqs, mode)); + } + } + cSize = ZSTD_compressSequences(cctx, compressed, compressedCapacity, - seqs, seqSize, + seqs, nbSeqs, src, srcSize); if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall) && (mode == ZSTD_sf_explicitBlockDelimiters) ) { @@ -298,10 +363,10 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size) ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters); ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0); ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel); - ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, wLog); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)wLog); ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, ZSTD_MINMATCH_MIN); ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1); - ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, mode); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, (int)mode); ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach); if (!literalsBuffer) { From 7b294caf461a15d74e64389bde16d5c33fc3d0c8 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 23 Dec 2024 19:43:17 -0800 Subject: [PATCH 268/405] add one valid test case ZSTD_compressSequencesAndLiterals() may return a specific error code when data to compress is non-compressible. --- tests/fuzz/sequence_compression_api.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index 32710afb9..21b6ac84e 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -16,6 +16,7 @@ */ #define ZSTD_STATIC_LINKING_ONLY +#include "zstd_errors.h" #include #include @@ -275,7 +276,12 @@ static size_t roundTripTest_compressSequencesAndLiterals( return 0; } /* round-trip */ - FUZZ_ZASSERT(cSize); + if (ZSTD_isError(cSize)) { + ZSTD_ErrorCode err = ZSTD_getErrorCode(cSize); + /* this specific error might happen as a result of data being uncompressible */ + if (err != ZSTD_error_cannotProduce_uncompressedBlock) + FUZZ_ZASSERT(cSize); + } { size_t const dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize); FUZZ_ZASSERT(dSize); FUZZ_ASSERT_MSG(dSize == srcSize, "Incorrect regenerated size"); From 72ce56b527d1710dd2fa193ca0c22933da382f44 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 23 Dec 2024 21:15:50 -0800 Subject: [PATCH 269/405] fixed another invalid scenario compressSequencesAndLiterals() doesn't support sequence validation --- .github/workflows/dev-long-tests.yml | 2 +- tests/fuzz/Makefile | 5 +++-- tests/fuzz/dictionary_loader.c | 6 ++--- tests/fuzz/sequence_compression_api.c | 32 +++++++++++++-------------- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index d5e476b4c..0adfed914 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -188,7 +188,7 @@ jobs: - name: ASan + UBSan + Regression Test run: make -j uasanregressiontest - clang-ubsan-regression: + clang-asan-ubsan-regression: runs-on: ubuntu-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index a64d2d252..13e29bb7a 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -263,9 +263,10 @@ corpora: $(patsubst %,corpora/%,$(FUZZ_TARGETS)) .PHONY: seedcorpora seedcorpora: $(patsubst %,corpora/%_seed_corpus.zip,$(FUZZ_TARGETS)) +REGRESSION_TARGET ?= all regressiontest: corpora - CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" $(PYTHON) ./fuzz.py build all --debug=$(DEBUGLEVEL) - $(PYTHON) ./fuzz.py regression all + CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" $(PYTHON) ./fuzz.py build $(REGRESSION_TARGET) --debug=$(DEBUGLEVEL) + $(PYTHON) ./fuzz.py regression $(REGRESSION_TARGET) clean: @$(RM) *.a *.o $(FUZZ_TARGETS) diff --git a/tests/fuzz/dictionary_loader.c b/tests/fuzz/dictionary_loader.c index 7b7c00428..ec9de4b0b 100644 --- a/tests/fuzz/dictionary_loader.c +++ b/tests/fuzz/dictionary_loader.c @@ -77,9 +77,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) FUZZ_dataProducer_uint32Range(producer, 0, 2); size = FUZZ_dataProducer_remainingBytes(producer); - DEBUGLOG(2, "Dict load method %d", dlm); - DEBUGLOG(2, "Dict content type %d", dct); - DEBUGLOG(2, "Dict size %u", (unsigned)size); + DEBUGLOG(4, "Dict load method %d", dlm); + DEBUGLOG(4, "Dict content type %d", dct); + DEBUGLOG(4, "Dict size %u", (unsigned)size); void* const rBuf = FUZZ_malloc(size); size_t const cBufSize = ZSTD_compressBound(size); diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index 21b6ac84e..9295d248c 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -239,8 +239,8 @@ transferLiterals(void* dst, size_t dstCapacity, const ZSTD_Sequence* seqs, size_ for (n=0; n Date: Sun, 29 Dec 2024 02:35:53 -0800 Subject: [PATCH 270/405] clarify doc on Frame-level methods when invoked on a skippable frame following discussion at #4226 --- lib/zstd.h | 39 +++++++++++++++++++++++---------------- tests/fuzzer.c | 18 ++++++++++++------ 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/lib/zstd.h b/lib/zstd.h index 36668b85b..acbcd0f99 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -178,6 +178,7 @@ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) * note 1 : a 0 return value means the frame is valid but "empty". + * When invoking this method on a skippable frame, it will return 0. * note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode). * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. * In which case, it's necessary to use streaming mode to decompress data. @@ -197,22 +198,26 @@ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, #define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); -/*! ZSTD_getDecompressedSize() : - * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). +/*! ZSTD_getDecompressedSize() (obsolete): + * This function is now obsolete, in favor of ZSTD_getFrameContentSize(). * Both functions work the same way, but ZSTD_getDecompressedSize() blends * "empty", "unknown" and "error" results to the same return value (0), * while ZSTD_getFrameContentSize() gives them separate return values. * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ ZSTD_DEPRECATED("Replaced by ZSTD_getFrameContentSize") -ZSTDLIB_API -unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); +ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); /*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+ * `src` should point to the start of a ZSTD frame or skippable frame. * `srcSize` must be >= first frame size * @return : the compressed size of the first frame starting at `src`, * suitable to pass as `srcSize` to `ZSTD_decompress` or similar, - * or an error code if input is invalid */ + * or an error code if input is invalid + * Note 1: this method is called _find*() because it's not enough to read the header, + * it may have to scan through the frame's content, to reach its end. + * Note 2: this method also works with Skippable Frames. In which case, + * it returns the size of the complete skippable frame, + * which is always equal to its content size + 8 bytes for headers. */ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); @@ -1507,7 +1512,7 @@ typedef struct { /*! ZSTD_getFrameHeader() : * decode Frame Header, or requires larger `srcSize`. * @return : 0, `zfhPtr` is correctly filled, - * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * >0, `srcSize` is too small, @return value is the wanted `srcSize` amount, * or an error code, which can be tested using ZSTD_isError() */ ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ /*! ZSTD_getFrameHeader_advanced() : @@ -1695,8 +1700,8 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, * * Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number, * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15. - * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so - * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant. + * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, + * so the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant. * * Returns an error if destination buffer is not large enough, if the source size is not representable * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid). @@ -1704,26 +1709,28 @@ ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, * @return : number of bytes written or a ZSTD error. */ ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity, - const void* src, size_t srcSize, unsigned magicVariant); + const void* src, size_t srcSize, + unsigned magicVariant); /*! ZSTD_readSkippableFrame() : - * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer. + * Retrieves the content of a zstd skippable frame starting at @src, and writes it to @dst buffer. * - * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written, - * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested - * in the magicVariant. + * The parameter @magicVariant will receive the magicVariant that was supplied when the frame was written, + * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. + * This can be NULL if the caller is not interested in the magicVariant. * * Returns an error if destination buffer is not large enough, or if the frame is not skippable. * * @return : number of bytes written or a ZSTD error. */ -ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant, - const void* src, size_t srcSize); +ZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, + unsigned* magicVariant, + const void* src, size_t srcSize); /*! ZSTD_isSkippableFrame() : * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame. */ -ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size); +ZSTDLIB_STATIC_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 6d165aea4..706dd9b95 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -4110,12 +4110,18 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); - /* findFrameCompressedSize on skippable frames */ - DISPLAYLEVEL(3, "test%3i : frame compressed size of skippable frame : ", testNb++); - { const char* frame = "\x50\x2a\x4d\x18\x05\x0\x0\0abcde"; - size_t const frameSrcSize = 13; - if (ZSTD_findFrameCompressedSize(frame, frameSrcSize) != frameSrcSize) goto _output_error; } - DISPLAYLEVEL(3, "OK \n"); + /* frame operations on skippable frames */ + { const char skippableFrame[] = "\x50\x2a\x4d\x18\x05\x0\x0\0abcde"; + size_t const skippableFrameSize = sizeof(skippableFrame) - 1 /* remove final /0 */; + + DISPLAYLEVEL(3, "test%3i : ZSTD_findFrameCompressedSize on skippable frame : ", testNb++); + if (ZSTD_findFrameCompressedSize(skippableFrame, skippableFrameSize) != skippableFrameSize) goto _output_error; + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize on skippable frame : ", testNb++); + if (ZSTD_getFrameContentSize(skippableFrame, skippableFrameSize) != 0) goto _output_error; + DISPLAYLEVEL(3, "OK \n"); + } /* error string tests */ DISPLAYLEVEL(3, "test%3i : testing ZSTD error code strings : ", testNb++); From a2ff6ea7846c598812be580026dfc63fd7229db3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 29 Dec 2024 12:26:04 -0800 Subject: [PATCH 271/405] improve ZSTD_getFrameHeader on skippable frames now reports: - the header size - the magic variant (within @dictID field) --- lib/common/zstd_trace.h | 2 +- lib/decompress/zstd_decompress.c | 6 ++++-- lib/zstd.h | 12 ++++++------ tests/fuzzer.c | 21 +++++++++++++++++---- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h index 3ae779fa6..d33edf35d 100644 --- a/lib/common/zstd_trace.h +++ b/lib/common/zstd_trace.h @@ -74,7 +74,7 @@ typedef struct { * Is the dictionary cold? * Only set on decompression. */ - unsigned dictionaryIsCold; + int dictionaryIsCold; /** * The dictionary size or zero if no dictionary. */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 6aac5dd3f..b2eb39c51 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -484,8 +484,10 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); - zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); zfhPtr->frameType = ZSTD_skippableFrame; + zfhPtr->dictID = MEM_readLE32(src) - ZSTD_MAGIC_SKIPPABLE_START; + zfhPtr->headerSize = ZSTD_SKIPPABLEHEADERSIZE; + zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); return 0; } RETURN_ERROR(prefix_unknown, ""); @@ -917,7 +919,7 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, return regenSize; } -static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming) +static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, int streaming) { #if ZSTD_TRACE if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) { diff --git a/lib/zstd.h b/lib/zstd.h index acbcd0f99..bbddacee7 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1491,7 +1491,7 @@ ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); /*! ZSTD_frameHeaderSize() : - * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. + * srcSize must be large enough, aka >= ZSTD_FRAMEHEADERSIZE_PREFIX. * @return : size of the Frame Header, * or an error code (if srcSize is too small) */ ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); @@ -1503,18 +1503,18 @@ typedef struct { unsigned blockSizeMax; ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ unsigned headerSize; - unsigned dictID; + unsigned dictID; /* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */ unsigned checksumFlag; unsigned _reserved1; unsigned _reserved2; } ZSTD_frameHeader; /*! ZSTD_getFrameHeader() : - * decode Frame Header, or requires larger `srcSize`. - * @return : 0, `zfhPtr` is correctly filled, - * >0, `srcSize` is too small, @return value is the wanted `srcSize` amount, + * decode Frame Header into `zfhPtr`, or requires larger `srcSize`. + * @return : 0 => header is complete, `zfhPtr` is correctly filled, + * >0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled, * or an error code, which can be tested using ZSTD_isError() */ -ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /*! ZSTD_getFrameHeader_advanced() : * same as ZSTD_getFrameHeader(), * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 706dd9b95..4ef0db2d0 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -4111,15 +4111,28 @@ static int basicUnitTests(U32 const seed, double compressibility) /* frame operations on skippable frames */ - { const char skippableFrame[] = "\x50\x2a\x4d\x18\x05\x0\x0\0abcde"; - size_t const skippableFrameSize = sizeof(skippableFrame) - 1 /* remove final /0 */; + { const char skippableFrame[] = "\x52\x2a\x4d\x18\x05\x0\x0\0abcde"; + size_t const skippableFrameSize = sizeof(skippableFrame) - 1 /* remove the terminating /0 */; DISPLAYLEVEL(3, "test%3i : ZSTD_findFrameCompressedSize on skippable frame : ", testNb++); - if (ZSTD_findFrameCompressedSize(skippableFrame, skippableFrameSize) != skippableFrameSize) goto _output_error; + CHECK(ZSTD_findFrameCompressedSize(skippableFrame, skippableFrameSize) == skippableFrameSize); DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize on skippable frame : ", testNb++); - if (ZSTD_getFrameContentSize(skippableFrame, skippableFrameSize) != 0) goto _output_error; + CHECK(ZSTD_getFrameContentSize(skippableFrame, skippableFrameSize) == 0); + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameHeader on skippable frame : ", testNb++); + { ZSTD_frameHeader zfh; + size_t const s = ZSTD_getFrameHeader(&zfh, skippableFrame, skippableFrameSize); + CHECK_Z(s); + CHECK(s == 0); /* success */ + CHECK(zfh.frameType == ZSTD_skippableFrame); + CHECK(zfh.headerSize == ZSTD_SKIPPABLEHEADERSIZE); + CHECK(zfh.dictID == 2); /* magic variant */ + assert(skippableFrameSize >= ZSTD_SKIPPABLEHEADERSIZE); + CHECK(zfh.frameContentSize == skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE); + } DISPLAYLEVEL(3, "OK \n"); } From 04a2a0219ca424595949d725fda5da5cf764b419 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 29 Dec 2024 14:25:33 -0800 Subject: [PATCH 272/405] update type names naming convention: Type names should start with a Capital letter (after the prefix) --- contrib/linux-kernel/linux_zstd.h | 2 +- doc/zstd_manual.html | 10 +++++----- lib/decompress/zstd_decompress.c | 14 +++++++------- lib/decompress/zstd_decompress_internal.h | 2 +- lib/zstd.h | 14 ++++++++------ programs/fileio.c | 4 ++-- tests/fuzz/simple_round_trip.c | 2 +- tests/fuzz/zstd_frame_info.c | 2 +- tests/fuzzer.c | 18 +++++++++--------- tests/zstreamtest.c | 4 ++-- 10 files changed, 37 insertions(+), 35 deletions(-) diff --git a/contrib/linux-kernel/linux_zstd.h b/contrib/linux-kernel/linux_zstd.h index a7ce080dc..2daf5d25a 100644 --- a/contrib/linux-kernel/linux_zstd.h +++ b/contrib/linux-kernel/linux_zstd.h @@ -465,7 +465,7 @@ void zstd_register_sequence_producer( * * See zstd_lib.h. */ -typedef ZSTD_frameHeader zstd_frame_header; +typedef ZSTD_FrameHeader zstd_frame_header; /** * zstd_get_frame_header() - extracts parameters from a zstd or skippable frame diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index ecb2b622c..485d5eafb 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1244,13 +1244,13 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); or an error code (if srcSize is too small)


    -
    typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e;
    +
    typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e;
     

    typedef struct {
         unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */
         unsigned long long windowSize;       /* can be very large, up to <= frameContentSize */
         unsigned blockSizeMax;
    -    ZSTD_frameType_e frameType;          /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */
    +    ZSTD_FrameType_e frameType;          /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */
         unsigned headerSize;
         unsigned dictID;
         unsigned checksumFlag;
    @@ -1258,11 +1258,11 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
         unsigned _reserved2;
     } ZSTD_frameHeader;
     

    -
    ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize);   /**< doesn't consume input */
    +
    ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize);   /**< doesn't consume input */
     /*! ZSTD_getFrameHeader_advanced() :
      *  same as ZSTD_getFrameHeader(),
      *  with added capability to select a format (like ZSTD_f_zstd1_magicless) */
    -ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
    +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
     

    decode Frame Header, or requires larger `srcSize`. @return : 0, `zfhPtr` is correctly filled, >0, `srcSize` is too small, value is wanted `srcSize` amount, @@ -2124,7 +2124,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const Z >0 : `srcSize` is too small, please provide at least result bytes on next attempt. errorCode, which can be tested using ZSTD_isError(). - It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, + It fills a ZSTD_FrameHeader structure with important information to correctly decode the frame, such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. As a consequence, check that values remain within valid application range. diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index b2eb39c51..402d75349 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -444,7 +444,7 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) * @return : 0, `zfhPtr` is correctly filled, * >0, `srcSize` is too small, value is wanted `srcSize` amount, ** or an error code, which can be tested using ZSTD_isError() */ -size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format) +size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format) { const BYTE* ip = (const BYTE*)src; size_t const minInputSize = ZSTD_startingInputLength(format); @@ -556,7 +556,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s * @return : 0, `zfhPtr` is correctly filled, * >0, `srcSize` is too small, value is wanted `srcSize` amount, * or an error code, which can be tested using ZSTD_isError() */ -size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize) +size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize) { return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1); } @@ -574,7 +574,7 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize) return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret; } #endif - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0) return ZSTD_CONTENTSIZE_ERROR; if (zfh.frameType == ZSTD_skippableFrame) { @@ -752,7 +752,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize const BYTE* const ipstart = ip; size_t remainingSize = srcSize; size_t nbBlocks = 0; - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; /* Extract Frame Header */ { size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format); @@ -845,7 +845,7 @@ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize) ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1); size_t const compressedSize = frameSizeInfo.compressedSize; unsigned long long const decompressedBound = frameSizeInfo.decompressedBound; - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), ""); if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR) @@ -1643,7 +1643,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize) * ZSTD_getFrameHeader(), which will provide a more precise error code. */ unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize) { - ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 }; + ZSTD_FrameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 }; size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize); if (ZSTD_isError(hError)) return 0; return zfp.dictID; @@ -2001,7 +2001,7 @@ size_t ZSTD_estimateDStreamSize(size_t windowSize) size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) { U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */ - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize); if (ZSTD_isError(err)) return err; RETURN_ERROR_IF(err>0, srcSize_wrong, ""); diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 83a7a0115..7d1f1053b 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -136,7 +136,7 @@ struct ZSTD_DCtx_s const void* virtualStart; /* virtual start of previous segment if it was just before current one */ const void* dictEnd; /* end of previous segment */ size_t expected; - ZSTD_frameHeader fParams; + ZSTD_FrameHeader fParams; U64 processedCSize; U64 decodedSize; blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */ diff --git a/lib/zstd.h b/lib/zstd.h index bbddacee7..08b3b357a 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1496,29 +1496,31 @@ ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size * or an error code (if srcSize is too small) */ ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); -typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; +typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e; +#define ZSTD_frameType_e ZSTD_FrameType_e /* old name */ typedef struct { unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ unsigned blockSizeMax; - ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ + ZSTD_FrameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ unsigned headerSize; unsigned dictID; /* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */ unsigned checksumFlag; unsigned _reserved1; unsigned _reserved2; -} ZSTD_frameHeader; +} ZSTD_FrameHeader; +#define ZSTD_frameHeader ZSTD_FrameHeader /* old name */ /*! ZSTD_getFrameHeader() : * decode Frame Header into `zfhPtr`, or requires larger `srcSize`. * @return : 0 => header is complete, `zfhPtr` is correctly filled, * >0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled, * or an error code, which can be tested using ZSTD_isError() */ -ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize); /*! ZSTD_getFrameHeader_advanced() : * same as ZSTD_getFrameHeader(), * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ -ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); /*! ZSTD_decompressionMargin() : * Zstd supports in-place decompression, where the input and output buffers overlap. @@ -3047,7 +3049,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_ >0 : `srcSize` is too small, please provide at least result bytes on next attempt. errorCode, which can be tested using ZSTD_isError(). - It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, + It fills a ZSTD_FrameHeader structure with important information to correctly decode the frame, such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. As a consequence, check that values remain within valid application range. diff --git a/programs/fileio.c b/programs/fileio.c index c2036b83c..1b8aa8a99 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -2401,7 +2401,7 @@ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs, size_t err, const char* srcFileName) { - ZSTD_frameHeader header; + ZSTD_FrameHeader header; /* Help message only for one specific error */ if (ZSTD_getErrorCode(err) != ZSTD_error_frameParameter_windowTooLarge) @@ -3201,7 +3201,7 @@ FIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile) { U32 const magicNumber = MEM_readLE32(headerBuffer); /* Zstandard frame */ if (magicNumber == ZSTD_MAGICNUMBER) { - ZSTD_frameHeader header; + ZSTD_FrameHeader header; U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead); if ( frameContentSize == ZSTD_CONTENTSIZE_ERROR || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN ) { diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c index 660092e61..ab50aadb4 100644 --- a/tests/fuzz/simple_round_trip.c +++ b/tests/fuzz/simple_round_trip.c @@ -34,7 +34,7 @@ static size_t getDecompressionMargin(void const* compressed, size_t cSize, size_ /* The macro should be correct in this case, but it may be smaller * because of e.g. block splitting, so take the smaller of the two. */ - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; size_t marginM; FUZZ_ZASSERT(ZSTD_getFrameHeader(&zfh, compressed, cSize)); if (maxBlockSize == 0) { diff --git a/tests/fuzz/zstd_frame_info.c b/tests/fuzz/zstd_frame_info.c index 95dbdd49a..4d17bba74 100644 --- a/tests/fuzz/zstd_frame_info.c +++ b/tests/fuzz/zstd_frame_info.c @@ -21,7 +21,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; if (size == 0) { src = NULL; } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4ef0db2d0..b457c2171 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -955,7 +955,7 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_freeCCtx(cctx); } { /* ensure frame content size is missing */ - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; size_t const ret = ZSTD_getFrameHeader(&zfh, compressedBuffer, compressedBufferSize); if (ret != 0 || zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error; } @@ -2512,7 +2512,7 @@ static int basicUnitTests(U32 const seed, double compressibility) CHECK_VAR(cSize, ZSTD_compressEnd(ctxDuplicated, compressedBuffer, ZSTD_compressBound(testSize), (const char*)CNBuffer + dictSize, testSize) ); - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; if (ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize)) goto _output_error; if ((zfh.frameContentSize != testSize) && (zfh.frameContentSize != 0)) goto _output_error; } } @@ -3585,7 +3585,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : decompress of magic-less frame : ", testNb++); ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters); CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) ); - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; size_t const zfhrt = ZSTD_getFrameHeader_advanced(&zfh, compressedBuffer, cSize, ZSTD_f_zstd1_magicless); if (zfhrt != 0) goto _output_error; } @@ -3943,7 +3943,7 @@ static int basicUnitTests(U32 const seed, double compressibility) goto _output_error; } } - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; size_t const zfhStatus = ZSTD_getFrameHeader(&zfh, dst, compressedSize); if (zfhStatus != 0) { DISPLAY("Error reading frame header\n"); @@ -4123,7 +4123,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameHeader on skippable frame : ", testNb++); - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; size_t const s = ZSTD_getFrameHeader(&zfh, skippableFrame, skippableFrameSize); CHECK_Z(s); CHECK(s == 0); /* success */ @@ -4153,8 +4153,8 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_CCtx* const cctx = ZSTD_createCCtx(); ZSTD_CDict* const lgCDict = ZSTD_createCDict(CNBuffer, size, 1); ZSTD_CDict* const smCDict = ZSTD_createCDict(CNBuffer, 1 KB, 1); - ZSTD_frameHeader lgHeader; - ZSTD_frameHeader smHeader; + ZSTD_FrameHeader lgHeader; + ZSTD_FrameHeader smHeader; CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, lgCDict)); CHECK_Z(ZSTD_getFrameHeader(&lgHeader, compressedBuffer, compressedBufferSize)); @@ -4773,7 +4773,7 @@ static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const } } /* frame header decompression test */ - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; CHECK_Z( ZSTD_getFrameHeader(&zfh, cBuffer, cSize) ); CHECK(zfh.frameContentSize != sampleSize, "Frame content size incorrect"); } @@ -4915,7 +4915,7 @@ static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const /* streaming decompression test */ DISPLAYLEVEL(5, "fuzzer t%u: Bufferless streaming decompression test \n", testNb); /* ensure memory requirement is good enough (should always be true) */ - { ZSTD_frameHeader zfh; + { ZSTD_FrameHeader zfh; CHECK( ZSTD_getFrameHeader(&zfh, cBuffer, ZSTD_FRAMEHEADERSIZE_MAX), "ZSTD_getFrameHeader(): error retrieving frame information"); { size_t const roundBuffSize = ZSTD_decodingBufferSize_min(zfh.windowSize, zfh.frameContentSize); diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 8df86d985..b8290fefc 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -436,7 +436,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) /* context size functions */ DISPLAYLEVEL(3, "test%3i : estimate DStream size : ", testNb++); - { ZSTD_frameHeader fhi; + { ZSTD_FrameHeader fhi; const void* cStart = (char*)compressedBuffer + (skippableFrameSize + 8); size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize); if (gfhError!=0) goto _output_error; @@ -1530,7 +1530,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : decompress large frame created from multiple threads + dictionary : ", testNb++); { ZSTD_DStream* const dstream = ZSTD_createDCtx(); - ZSTD_frameHeader zfh; + ZSTD_FrameHeader zfh; ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize); DISPLAYLEVEL(5, "frame windowsize = %u : ", (unsigned)zfh.windowSize); outBuff.dst = decodedBuffer; From 54c3d998a04a4002697a3a44293074cb01df54a5 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Thu, 2 Jan 2025 14:02:10 -0800 Subject: [PATCH 273/405] Support for libc variants without fseeko/ftello Some older Android libc implementations don't support `fseeko` or `ftello`. This commit adds a new compile-time macro `LIBC_NO_FSEEKO` as well as a usage in CMake for old Android APIs. --- build/cmake/CMakeLists.txt | 12 ++++++++++++ contrib/seekable_format/zstdseek_decompress.c | 5 ++++- programs/fileio_common.h | 6 +++++- programs/util.h | 5 ++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index b43671cc2..e03eadb66 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -82,8 +82,19 @@ else () add_definitions(-DZSTD_LEGACY_SUPPORT=0) endif () +get_cmake_property(_variableNames VARIABLES) +list (SORT _variableNames) +foreach (_variableName ${_variableNames}) + message("${_variableName}=${${_variableName}}") +endforeach() + if (ANDROID) set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT OFF) + # Old versions of bionic libc don't have fseeko/ftello + if ((NOT ${ANDROID_PLATFORM_LEVEL}) OR ${ANDROID_PLATFORM_LEVEL} VERSION_LESS 24) + message("Hi Android SDK") + add_compile_definitions(LIBC_NO_FSEEKO) + endif () else() set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT ON) endif() @@ -153,6 +164,7 @@ if (ZSTD_BUILD_PROGRAMS) elseif(NOT ZSTD_BUILD_SHARED AND ZSTD_PROGRAMS_LINK_SHARED) message(SEND_ERROR "You need to build shared library to build zstd CLI") endif () + message("Building program") add_subdirectory(programs) endif () diff --git a/contrib/seekable_format/zstdseek_decompress.c b/contrib/seekable_format/zstdseek_decompress.c index 5ee6e0541..7f4979875 100644 --- a/contrib/seekable_format/zstdseek_decompress.c +++ b/contrib/seekable_format/zstdseek_decompress.c @@ -77,7 +77,10 @@ /* ************************************************************ * Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW ***************************************************************/ -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(LIBC_NO_FSEEKO) +/* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ +#define LONG_SEEK fseek +#elif defined(_MSC_VER) && _MSC_VER >= 1400 # define LONG_SEEK _fseeki64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ # define LONG_SEEK fseeko diff --git a/programs/fileio_common.h b/programs/fileio_common.h index 7a014ee4b..f1eb8160b 100644 --- a/programs/fileio_common.h +++ b/programs/fileio_common.h @@ -79,7 +79,11 @@ extern UTIL_time_t g_displayClock; /* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW */ -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(LIBC_NO_FSEEKO) +/* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ +#define LONG_SEEK fseek +#define LONG_TELL ftell +#elif defined(_MSC_VER) && _MSC_VER >= 1400 # define LONG_SEEK _fseeki64 # define LONG_TELL _ftelli64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ diff --git a/programs/util.h b/programs/util.h index ec8139684..e66d95c08 100644 --- a/programs/util.h +++ b/programs/util.h @@ -24,7 +24,10 @@ /*-************************************************************ * Fix fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW ***************************************************************/ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#if defined(LIBC_NO_FSEEKO) +/* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ +#define UTIL_fseek fseek +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) # define UTIL_fseek _fseeki64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ # define UTIL_fseek fseeko From 757e29e170565ac48ff7d893a4cc421e0450dd72 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Thu, 2 Jan 2025 14:17:24 -0800 Subject: [PATCH 274/405] Oops --- build/cmake/CMakeLists.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index e03eadb66..b9003c867 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -82,17 +82,11 @@ else () add_definitions(-DZSTD_LEGACY_SUPPORT=0) endif () -get_cmake_property(_variableNames VARIABLES) -list (SORT _variableNames) -foreach (_variableName ${_variableNames}) - message("${_variableName}=${${_variableName}}") -endforeach() - if (ANDROID) set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT OFF) # Old versions of bionic libc don't have fseeko/ftello if ((NOT ${ANDROID_PLATFORM_LEVEL}) OR ${ANDROID_PLATFORM_LEVEL} VERSION_LESS 24) - message("Hi Android SDK") + message(STATUS "Setting compile definitions for old Android API") add_compile_definitions(LIBC_NO_FSEEKO) endif () else() @@ -164,7 +158,6 @@ if (ZSTD_BUILD_PROGRAMS) elseif(NOT ZSTD_BUILD_SHARED AND ZSTD_PROGRAMS_LINK_SHARED) message(SEND_ERROR "You need to build shared library to build zstd CLI") endif () - message("Building program") add_subdirectory(programs) endif () From 6b046f58410fe66ea300c31ffc92dbfb4c956bb1 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Thu, 2 Jan 2025 15:05:58 -0800 Subject: [PATCH 275/405] PR feedback --- contrib/seekable_format/zstdseek_decompress.c | 2 +- programs/fileio_common.h | 4 ++-- programs/util.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/seekable_format/zstdseek_decompress.c b/contrib/seekable_format/zstdseek_decompress.c index 7f4979875..ab9088a10 100644 --- a/contrib/seekable_format/zstdseek_decompress.c +++ b/contrib/seekable_format/zstdseek_decompress.c @@ -79,7 +79,7 @@ ***************************************************************/ #if defined(LIBC_NO_FSEEKO) /* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ -#define LONG_SEEK fseek +# define LONG_SEEK fseek #elif defined(_MSC_VER) && _MSC_VER >= 1400 # define LONG_SEEK _fseeki64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ diff --git a/programs/fileio_common.h b/programs/fileio_common.h index f1eb8160b..044001506 100644 --- a/programs/fileio_common.h +++ b/programs/fileio_common.h @@ -81,8 +81,8 @@ extern UTIL_time_t g_displayClock; /* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW */ #if defined(LIBC_NO_FSEEKO) /* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ -#define LONG_SEEK fseek -#define LONG_TELL ftell +# define LONG_SEEK fseek +# define LONG_TELL ftell #elif defined(_MSC_VER) && _MSC_VER >= 1400 # define LONG_SEEK _fseeki64 # define LONG_TELL _ftelli64 diff --git a/programs/util.h b/programs/util.h index e66d95c08..3a83a50ae 100644 --- a/programs/util.h +++ b/programs/util.h @@ -26,7 +26,7 @@ ***************************************************************/ #if defined(LIBC_NO_FSEEKO) /* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ -#define UTIL_fseek fseek +# define UTIL_fseek fseek #elif defined(_MSC_VER) && (_MSC_VER >= 1400) # define UTIL_fseek _fseeki64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ From dfb236b2aa58d3460945f5112e8d5388d7c4a666 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Thu, 2 Jan 2025 15:10:40 -0800 Subject: [PATCH 276/405] chore: indentation alignment --- programs/fileio_common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/fileio_common.h b/programs/fileio_common.h index 044001506..696626fe4 100644 --- a/programs/fileio_common.h +++ b/programs/fileio_common.h @@ -81,14 +81,14 @@ extern UTIL_time_t g_displayClock; /* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW */ #if defined(LIBC_NO_FSEEKO) /* Some older libc implementations don't include these functions (e.g. Bionic < 24) */ -# define LONG_SEEK fseek -# define LONG_TELL ftell +# define LONG_SEEK fseek +# define LONG_TELL ftell #elif defined(_MSC_VER) && _MSC_VER >= 1400 # define LONG_SEEK _fseeki64 # define LONG_TELL _ftelli64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ -# define LONG_SEEK fseeko -# define LONG_TELL ftello +# define LONG_SEEK fseeko +# define LONG_TELL ftello #elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__) # define LONG_SEEK fseeko64 # define LONG_TELL ftello64 From 1548bfc3497f45399daab58bcec4ab06a0878af1 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 20 Dec 2024 17:32:28 -0500 Subject: [PATCH 277/405] [opt] Fix too short of match getting generated The optimal parser with LDM enabled using minMatch > 3 could generate a match length of 3 when minMatch >= 4. This is not allowed. 1. Fix the bug 2. Add validation logic to `ZSTD_buildSeqStore()` in debug mode for all block compressors that checks we never generate too short a match. This way we don't rely on the `generate_sequences` fuzzer to find this issue. Credit to OSS-Fuzz --- lib/compress/zstd_compress.c | 22 ++++++++++++++++++++++ lib/compress/zstd_opt.c | 18 +++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3af69c1ae..52c54b4da 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3240,6 +3240,27 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq return litLenSum + matchLenSum; } +/** + * Function to validate sequences produced by a block compressor. + */ +static void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_compressionParameters* cParams) +{ +#if DEBUGLEVEL >= 1 + const SeqDef* seq = seqStore->sequencesStart; + const SeqDef* const seqEnd = seqStore->sequences; + size_t const matchLenLowerBound = cParams->minMatch == 3 ? 3 : 4; + for (; seq < seqEnd; ++seq) { + const ZSTD_SequenceLength seqLength = ZSTD_getSequenceLength(seqStore, seq); + assert(seqLength.matchLength >= matchLenLowerBound); + (void)seqLength; + (void)matchLenLowerBound; + } +#else + (void)seqStore; + (void)cParams; +#endif +} + static size_t ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_SequencePosition* seqPos, @@ -3410,6 +3431,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize); } } + ZSTD_validateSeqStore(&zc->seqStore, &zc->appliedParams.cParams); return ZSTDbss_compress; } diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 0ab33d56e..3d7171b75 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -972,7 +972,7 @@ ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock return; } - /* Matches may be < MINMATCH by this process. In that case, we will reject them + /* Matches may be < minMatch by this process. In that case, we will reject them when we are deciding whether or not to add the ldm */ optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining; optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining; @@ -994,7 +994,8 @@ ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock * into 'matches'. Maintains the correct ordering of 'matches'. */ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches, - const ZSTD_optLdm_t* optLdm, U32 currPosInBlock) + const ZSTD_optLdm_t* optLdm, U32 currPosInBlock, + U32 minMatch) { U32 const posDiff = currPosInBlock - optLdm->startPosInBlock; /* Note: ZSTD_match_t actually contains offBase and matchLength (before subtracting MINMATCH) */ @@ -1003,7 +1004,7 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches, /* Ensure that current block position is not outside of the match */ if (currPosInBlock < optLdm->startPosInBlock || currPosInBlock >= optLdm->endPosInBlock - || candidateMatchLength < MINMATCH) { + || candidateMatchLength < minMatch) { return; } @@ -1023,7 +1024,8 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches, static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches, - U32 currPosInBlock, U32 remainingBytes) + U32 currPosInBlock, U32 remainingBytes, + U32 minMatch) { if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { return; @@ -1040,7 +1042,7 @@ ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, } ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes); } - ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock); + ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock, minMatch); } @@ -1122,7 +1124,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, U32 const ll0 = !litlen; U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, ip, iend, rep, ll0, minMatch); ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, - (U32)(ip-istart), (U32)(iend-ip)); + (U32)(ip-istart), (U32)(iend-ip), + minMatch); if (!nbMatches) { DEBUGLOG(8, "no match found at cPos %u", (unsigned)(ip-istart)); ip++; @@ -1276,7 +1279,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, U32 matchNb; ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, - (U32)(inr-istart), (U32)(iend-inr)); + (U32)(inr-istart), (U32)(iend-inr), + minMatch); if (!nbMatches) { DEBUGLOG(7, "rPos:%u : no match found", cur); From d88651e6041995243c8cd6884bbc44c279ab80d2 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Fri, 3 Jan 2025 09:35:18 -0800 Subject: [PATCH 278/405] Do not vary row matchfinder selection based on availability of SSE2/Neon Move towards a stronger guarantee of reproducibility by removing this small difference for machines without SSE2/Neon. The SIMD behavior is now the default for all platforms. --- lib/compress/zstd_compress.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 52c54b4da..04b6bb9f1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -237,19 +237,10 @@ static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_Para /* Returns row matchfinder usage given an initial mode and cParams */ static ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode, const ZSTD_compressionParameters* const cParams) { -#if defined(ZSTD_ARCH_X86_SSE2) || defined(ZSTD_ARCH_ARM_NEON) - int const kHasSIMD128 = 1; -#else - int const kHasSIMD128 = 0; -#endif if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */ mode = ZSTD_ps_disable; if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode; - if (kHasSIMD128) { - if (cParams->windowLog > 14) mode = ZSTD_ps_enable; - } else { - if (cParams->windowLog > 17) mode = ZSTD_ps_enable; - } + if (cParams->windowLog > 14) mode = ZSTD_ps_enable; return mode; } From 0fd521048d9304e2e06020bebcfb0b481261b2fc Mon Sep 17 00:00:00 2001 From: Po-Chuan Hsieh Date: Sun, 5 Jan 2025 22:26:08 +0800 Subject: [PATCH 279/405] Update MANDIR for FreeBSD share/man became a valid path for manpage since Jan 2020. And we converted the whole ports tree to share/man around last March. --- programs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/Makefile b/programs/Makefile index 4d32e0fa8..f4af5e981 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -388,7 +388,7 @@ datarootdir ?= $(PREFIX)/share mandir ?= $(datarootdir)/man man1dir ?= $(mandir)/man1 -ifneq (,$(filter OpenBSD FreeBSD NetBSD DragonFly SunOS,$(UNAME))) +ifneq (,$(filter OpenBSD NetBSD DragonFly SunOS,$(UNAME))) MANDIR ?= $(PREFIX)/man MAN1DIR ?= $(MANDIR)/man1 else From 42d704ad5e286fe8ad8b8aca0af4c78543abd3f1 Mon Sep 17 00:00:00 2001 From: MessyHack Date: Fri, 10 Jan 2025 22:38:56 -0800 Subject: [PATCH 280/405] should check defined(_M_X64) not defined(_M_X86) when building with MSVC. _M_X86 is only defined under MSVC 32Bit _M_X64 is only defined under MSVC 64Bit --- lib/common/bitstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index bcfa09b89..a1dac889d 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -309,7 +309,7 @@ FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits(BitContainerType bitContainer, U3 * such cpus old (pre-Haswell, 2013) and their performance is not of that * importance. */ -#if defined(__x86_64__) || defined(_M_X86) +#if defined(__x86_64__) || defined(_M_X64) return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1); #else return (bitContainer >> (start & regMask)) & BIT_mask[nbBits]; From 56500044c4c517dc405c04e6933130684743cb89 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 12 Jan 2025 01:32:40 -0800 Subject: [PATCH 281/405] bench: nb threads specified with -v --- programs/zstdcli.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 9fa7e2275..7d00a94b2 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1312,7 +1312,8 @@ int main(int argCount, const char* argv[]) nbWorkers = default_nbThreads(); } } - DISPLAYLEVEL(4, "Compressing with %u worker threads \n", nbWorkers); + if (operation != zom_bench) + DISPLAYLEVEL(4, "Compressing with %u worker threads \n", nbWorkers); #else (void)singleThread; (void)nbWorkers; (void)defaultLogicalCores; #endif @@ -1397,13 +1398,19 @@ int main(int argCount, const char* argv[]) if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel(); if (cLevelLast < cLevel) cLevelLast = cLevel; - if (cLevelLast > cLevel) - DISPLAYLEVEL(3, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast); + DISPLAYLEVEL(3, "Benchmarking "); + if (filenames->tableSize > 1) + DISPLAYLEVEL(3, "%u files ", (unsigned)filenames->tableSize); + if (cLevelLast > cLevel) { + DISPLAYLEVEL(3, "from level %d to %d ", cLevel, cLevelLast); + } else { + DISPLAYLEVEL(3, "at level %d ", cLevel); + } + DISPLAYLEVEL(3, "using %i threads \n", nbWorkers); if (filenames->tableSize > 0) { if(separateFiles) { unsigned i; for(i = 0; i < filenames->tableSize; i++) { - DISPLAYLEVEL(3, "Benchmarking %s \n", filenames->fileNames[i]); operationResult = BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams); } } else { From f5dbdac81879e34a4dfffb77dd7769c536a9b702 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 12 Jan 2025 23:08:26 -0800 Subject: [PATCH 282/405] fixed macro name typo --- programs/platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/platform.h b/programs/platform.h index 05a26a564..e2cc1c3e6 100644 --- a/programs/platform.h +++ b/programs/platform.h @@ -32,7 +32,7 @@ #if defined __ia64 || defined _M_IA64 /* Intel Itanium */ \ || defined __powerpc64__ || defined __ppc64__ || defined __PPC64__ /* POWER 64-bit */ \ || (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__ /* SPARC 64-bit */ \ - || defined __x86_64__s || defined _M_X64 /* x86 64-bit */ \ + || defined __x86_64__ || defined _M_X64 /* x86 64-bit */ \ || defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__ /* ARM 64-bit */ \ || (defined __mips && (__mips == 64 || __mips == 4 || __mips == 3)) /* MIPS 64-bit */ \ || defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */ \ From e490be895cda9d1d6f707eaa86f8a72995960053 Mon Sep 17 00:00:00 2001 From: Mingjie Shen Date: Mon, 13 Jan 2025 16:39:34 -0500 Subject: [PATCH 283/405] fix out-of-bounds array index access --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 04b6bb9f1..ef1817f52 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6713,7 +6713,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); - if (inSeqs[idx].litLength) { + if (idx < inSeqsSize && inSeqs[idx].litLength) { DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength); ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength); ip += inSeqs[idx].litLength; From 80af41e08a630946a75a5cda9e4cdf192247f20a Mon Sep 17 00:00:00 2001 From: Sean Bartell Date: Thu, 20 Jun 2024 15:52:43 -0500 Subject: [PATCH 284/405] [contrib/pzstd] Prevent hangs when there are errors When two threads are using a WorkQueue and the reader thread exits due to an error, it must call WorkQueue::finish() to wake up the writer thread. Otherwise, if the queue is full and the writer thread is waiting for a free slot, it could hang forever. This can happen in pratice when decompressing a large, corrupted file that does not contain pzstd skippable frames. --- contrib/pzstd/Pzstd.cpp | 12 ++++++++++-- contrib/pzstd/utils/WorkQueue.h | 7 ++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/contrib/pzstd/Pzstd.cpp b/contrib/pzstd/Pzstd.cpp index 67b941991..048a006b3 100644 --- a/contrib/pzstd/Pzstd.cpp +++ b/contrib/pzstd/Pzstd.cpp @@ -269,7 +269,10 @@ static void compress( std::shared_ptr out, size_t maxInputSize) { auto& errorHolder = state.errorHolder; - auto guard = makeScopeGuard([&] { out->finish(); }); + auto guard = makeScopeGuard([&] { + in->finish(); + out->finish(); + }); // Initialize the CCtx auto ctx = state.cStreamPool->get(); if (!errorHolder.check(ctx != nullptr, "Failed to allocate ZSTD_CStream")) { @@ -431,7 +434,10 @@ static void decompress( std::shared_ptr in, std::shared_ptr out) { auto& errorHolder = state.errorHolder; - auto guard = makeScopeGuard([&] { out->finish(); }); + auto guard = makeScopeGuard([&] { + in->finish(); + out->finish(); + }); // Initialize the DCtx auto ctx = state.dStreamPool->get(); if (!errorHolder.check(ctx != nullptr, "Failed to allocate ZSTD_DStream")) { @@ -578,6 +584,7 @@ std::uint64_t writeFile( FILE* outputFd, bool decompress) { auto& errorHolder = state.errorHolder; + auto outsFinishGuard = makeScopeGuard([&outs] { outs.finish(); }); auto lineClearGuard = makeScopeGuard([&state] { state.log.clear(kLogInfo); }); @@ -585,6 +592,7 @@ std::uint64_t writeFile( std::shared_ptr out; // Grab the output queue for each decompression job (in order). while (outs.pop(out)) { + auto outFinishGuard = makeScopeGuard([&out] { out->finish(); }); if (errorHolder.hasError()) { continue; } diff --git a/contrib/pzstd/utils/WorkQueue.h b/contrib/pzstd/utils/WorkQueue.h index d7947b814..07842e598 100644 --- a/contrib/pzstd/utils/WorkQueue.h +++ b/contrib/pzstd/utils/WorkQueue.h @@ -115,13 +115,14 @@ class WorkQueue { } /** - * Promise that `push()` won't be called again, so once the queue is empty - * there will never any more work. + * Promise that either the reader side or the writer side is done. + * If the writer is done, `push()` won't be called again, so once the queue + * is empty there will never be any more work. If the reader is done, `pop()` + * won't be called again, so further items pushed will just be ignored. */ void finish() { { std::lock_guard lock(mutex_); - assert(!done_); done_ = true; } readerCv_.notify_all(); From afff3d2cce1ad2e81b16459de5b572131949c44f Mon Sep 17 00:00:00 2001 From: Mingjie Shen Date: Mon, 13 Jan 2025 20:52:06 -0500 Subject: [PATCH 285/405] return error if block delimiter is not found --- lib/compress/zstd_compress.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ef1817f52..e033a04cc 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -6687,6 +6687,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength); ip += matchLength + litLength; } + RETURN_ERROR_IF(idx == inSeqsSize, externalSequences_invalid, "Block delimiter not found."); /* If we skipped repcode search while parsing, we need to update repcodes now */ assert(externalRepSearch != ZSTD_ps_auto); @@ -6713,7 +6714,7 @@ ZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx, ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t)); - if (idx < inSeqsSize && inSeqs[idx].litLength) { + if (inSeqs[idx].litLength) { DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength); ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength); ip += inSeqs[idx].litLength; From 7d63a1c7c3ceb5befd0839e8c50b91c3289019ce Mon Sep 17 00:00:00 2001 From: lalakii Date: Wed, 15 Jan 2025 02:16:42 +0800 Subject: [PATCH 286/405] add prerelease option --- build/VS_scripts/build.VSPreview.cmd | 7 +++++++ build/VS_scripts/build.generic.cmd | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 build/VS_scripts/build.VSPreview.cmd diff --git a/build/VS_scripts/build.VSPreview.cmd b/build/VS_scripts/build.VSPreview.cmd new file mode 100644 index 000000000..c594bb12c --- /dev/null +++ b/build/VS_scripts/build.VSPreview.cmd @@ -0,0 +1,7 @@ +@echo off + +rem build 32-bit +call "%~p0%build.generic.cmd" preview Win32 Release v143 + +rem build 64-bit +call "%~p0%build.generic.cmd" preview x64 Release v143 \ No newline at end of file diff --git a/build/VS_scripts/build.generic.cmd b/build/VS_scripts/build.generic.cmd index 6597d79ca..0912d2347 100644 --- a/build/VS_scripts/build.generic.cmd +++ b/build/VS_scripts/build.generic.cmd @@ -19,10 +19,10 @@ GOTO build :display_help echo Syntax: build.generic.cmd msbuild_version msbuild_platform msbuild_configuration msbuild_toolset -echo msbuild_version: VS installed version (latest, VS2012, VS2013, VS2015, VS2017, VS2019, ...) +echo msbuild_version: VS installed version (latest, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022, ...) echo msbuild_platform: Platform (x64 or Win32) echo msbuild_configuration: VS configuration (Release or Debug) -echo msbuild_toolset: Platform Toolset (v100, v110, v120, v140, v141, v142, ...) +echo msbuild_toolset: Platform Toolset (v100, v110, v120, v140, v141, v142, v143, ...) EXIT /B 1 @@ -39,6 +39,7 @@ IF %msbuild_version% == VS2019 SET vswhere_params=-version [16,17) -products * IF %msbuild_version% == VS2022 SET vswhere_params=-version [17,18) -products * REM Add the next Visual Studio version here. IF %msbuild_version% == latest SET vswhere_params=-latest -products * +IF %msbuild_version% == preview SET vswhere_params=-prerelease -products * IF NOT DEFINED vswhere_params GOTO skip_vswhere SET vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" From 908a95889b2bbcdb30e945ac12e0b6b2e025fa4d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 14:49:45 -0800 Subject: [PATCH 287/405] fix clang-pgo test --- .github/workflows/dev-short-tests.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 7ed068d6e..752dda324 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -615,18 +615,6 @@ jobs: run: | make clangbuild - clang-pgo: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: Build PGO Zstd with Clang - env: - CC: clang-14 - LLVM_PROFDATA: llvm-profdata-14 - run: | - make -C programs zstd-pgo - ./programs/zstd -b - gcc-pgo: runs-on: ubuntu-latest steps: @@ -638,6 +626,19 @@ jobs: make -C programs zstd-pgo ./programs/zstd -b + clang-pgo: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + - name: Build PGO Zstd with Clang + env: + CC: clang + run: | + sudo apt install -y llvm + llvm-profdata --version + make -C programs zstd-pgo + ./programs/zstd -b + intel-cet-compatibility: runs-on: ubuntu-latest steps: From 0e819c9f933a6b1193cfa26453ba967eb198af13 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 15:15:27 -0800 Subject: [PATCH 288/405] fix meson-linux build test missing the liblzma package --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 752dda324..2867e4f3e 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -220,7 +220,7 @@ jobs: - name: Install packages run: | sudo apt-get update - sudo apt-get -y install build-essential python3-pip ninja-build liblz4-dev + sudo apt-get -y install build-essential python3-pip ninja-build liblz4-dev liblzma-dev pip install --pre meson - name: Build with Meson run: | From 196e76efe16623c4a1aa5d636298b59f392671b5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 15:24:27 -0800 Subject: [PATCH 289/405] fix make-external-compressors "only-lzma" test missing the liblzma-dev package --- .github/workflows/dev-short-tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 2867e4f3e..7e58b40e6 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -199,7 +199,9 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: Build with ${{matrix.name}} - run: ${{matrix.flags}} make zstd + run: | + sudo apt install liblzma-dev + ${{matrix.flags}} make zstd implicit-fall-through: From 80ff61de1de352fb14d4bee6de7f7dd1e254da38 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 15:28:23 -0800 Subject: [PATCH 290/405] fixed cmake-build-and-test-check missing the liblzma library --- .github/workflows/dev-short-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 7e58b40e6..0dfd48529 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -89,6 +89,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: cmake build and test run: | + sudo apt install liblzma-dev FUZZERTEST=-T1mn ZSTREAM_TESTTIME=-T1mn make cmakebuild V=1 cpp-gnu90-c99-compatibility: From 642157cc450c5e2b1c5703ba0a164514ce29061a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 15:39:20 -0800 Subject: [PATCH 291/405] short-test-1: separate tests, giving each a name to better observe where the problem might be --- .github/workflows/commit.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index ca5a85b8f..4fff0f5d7 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -45,16 +45,24 @@ jobs: run: | sudo apt-get update sudo apt-get install gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu libc6-dev-ppc64-powerpc-cross libcurl4-gnutls-dev lib64gcc-11-dev-powerpc-cross - - name: Test - run: |- - make gnu90build; make clean - make gnu99build; make clean - make ppc64build V=1; make clean - make ppcbuild V=1; make clean - make armbuild V=1; make clean - make aarch64build V=1; make clean - make -C tests test-legacy test-longmatch; make clean - make -C lib libzstd-nomt; make clean + - name: gnu90 build + run: make gnu90build && make clean + - name: gnu99 build + run: make gnu99build && make clean + - name: ppc64 build + run: make ppc64build V=1 && make clean + - name: ppc build + run: make ppcbuild V=1 && make clean + - name: arm build + run: make armbuild V=1 && make clean + - name: aarch64 build + run: make aarch64build V=1 && make clean + - name: test-legacy + run: make -C tests test-legacy V=1 && make clean + - name: test-longmatch + run: make -C tests test-longmatch V=1 && make clean + - name: libzstd-nomt build + run: make -C lib libzstd-nomt V=1 && make clean regression-test: runs-on: ubuntu-latest From d4ae5c3752c0f4a918cadcfb9489c91e59bb1f47 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 15:52:27 -0800 Subject: [PATCH 292/405] update installed lib64gcc version --- .github/workflows/commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 4fff0f5d7..2aa8a6d86 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -44,7 +44,7 @@ jobs: - name: Install Dependencies run: | sudo apt-get update - sudo apt-get install gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu libc6-dev-ppc64-powerpc-cross libcurl4-gnutls-dev lib64gcc-11-dev-powerpc-cross + sudo apt-get install gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu libc6-dev-ppc64-powerpc-cross libcurl4-gnutls-dev lib64gcc-13-dev-powerpc-cross - name: gnu90 build run: make gnu90build && make clean - name: gnu99 build From 43626f1ce0ae4f7f3a9f6d5b7b04f54566d49b52 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 16:05:42 -0800 Subject: [PATCH 293/405] zlib-wrapper: separate test components to better understand what is failing --- .github/workflows/dev-short-tests.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 0dfd48529..25919922d 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -141,12 +141,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: zlib wrapper test + - name: install valgrind run: | sudo apt-get -qqq update make valgrindinstall - make -C zlibWrapper test - make -C zlibWrapper test-valgrind + - name: zlib wrapper test + run: make -C zlibWrapper test + - name: zlib wrapper test under valgrind + run: make -C zlibWrapper test-valgrind lz4-threadpool-libs: runs-on: ubuntu-latest From 0b96e6d42a9b22eb472a050fcd2cc4be3ffb8e2b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 15 Jan 2025 16:31:00 -0800 Subject: [PATCH 294/405] fixed zlib test new versions of the library generate a different error code --- zlibWrapper/examples/example.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zlibWrapper/examples/example.c b/zlibWrapper/examples/example.c index 99fbf5b19..eaae69747 100644 --- a/zlibWrapper/examples/example.c +++ b/zlibWrapper/examples/example.c @@ -340,7 +340,7 @@ void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr, /* =========================================================================== * Test inflate() with large buffers - */ + */ void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) { int err; @@ -442,8 +442,8 @@ void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) { CHECK_ERR(err, "inflateSync"); err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); + if (err != Z_STREAM_END) { + fprintf(stderr, "inflate reported %i != %i (Z_STREAM_END)\n", err, Z_STREAM_END); /* Because of incorrect adler32 */ exit(1); } From 886720442f712b6e94c13075edaec1f224c1ae1a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 29 Dec 2024 02:13:57 -0800 Subject: [PATCH 295/405] initial implementation (incomplete) needs to take care of long lengths > 65535 --- lib/compress/zstd_compress.c | 264 ++++++++++++++++++++++++++++++++--- tests/Makefile | 2 +- 2 files changed, 249 insertions(+), 17 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 04b6bb9f1..d91fae619 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -15,7 +15,9 @@ #include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */ #include "../common/mem.h" #include "../common/error_private.h" +#include "compiler.h" #include "hist.h" /* HIST_countFast_wksp */ +#include "zstd_internal.h" #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ #include "../common/fse.h" #include "../common/huf.h" @@ -7103,15 +7105,226 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, return cSize; } + +#if defined(__AVX2__) + +#include /* AVX2 intrinsics */ + /* + * Convert 2 sequences per iteration, using AVX2 intrinsics: + * - offset -> offBase = offset + 2 + * - litLength -> (U16) litLength + * - matchLength -> (U16)(matchLength - 3) + * - rep is ignored + * Store only 8 bytes per SeqDef (offBase[4], litLength[2], mlBase[2]). + * + * At the end, instead of extracting two __m128i, + * we use _mm256_permute4x64_epi64(..., 0xE8) to move lane2 into lane1, + * then store the lower 16 bytes in one go. + */ +void convertSequences_noRepcodes( + SeqDef* dstSeqs, + const ZSTD_Sequence* inSeqs, + size_t nbSequences) +{ + /* + * addition: + * For each 128-bit half: (offset+2, litLength+0, matchLength-3, rep+0) + */ + const __m256i addition = _mm256_setr_epi32( + ZSTD_REP_NUM, 0, -MINMATCH, 0, /* for sequence i */ + ZSTD_REP_NUM, 0, -MINMATCH, 0 /* for sequence i+1 */ + ); + + /* + * shuffle mask for byte-level rearrangement in each 128-bit half: + * + * Input layout (after addition) per 128-bit half: + * [ offset+2 (4 bytes) | litLength (4 bytes) | matchLength (4 bytes) | rep (4 bytes) ] + * We only need: + * offBase (4 bytes) = offset+2 + * litLength (2 bytes) = low 2 bytes of litLength + * mlBase (2 bytes) = low 2 bytes of (matchLength) + * => Bytes [0..3, 4..5, 8..9], zero the rest. + */ + const __m256i mask = _mm256_setr_epi8( + /* For the lower 128 bits => sequence i */ + 0, 1, 2, 3, /* offset+2 */ + 4, 5, /* litLength (16 bits) */ + 8, 9, /* matchLength (16 bits) */ + (char)0x80, (char)0x80, (char)0x80, (char)0x80, + (char)0x80, (char)0x80, (char)0x80, (char)0x80, + + /* For the upper 128 bits => sequence i+1 */ + 16,17,18,19, /* offset+2 */ + 20,21, /* litLength */ + 24,25, /* matchLength */ + (char)0x80, (char)0x80, (char)0x80, (char)0x80, + (char)0x80, (char)0x80, (char)0x80, (char)0x80 + ); + + /* + * Next, we'll use _mm256_permute4x64_epi64(vshf, 0xE8). + * Explanation of 0xE8 = 11101000b => [lane0, lane2, lane2, lane3]. + * So the lower 128 bits become [lane0, lane2] => combining seq0 and seq1. + */ +#define PERM_LANE_0X_E8 0xE8 /* [0,2,2,3] in lane indices */ + + size_t i = 0; + /* Process 2 sequences per loop iteration */ + for (; i + 1 < nbSequences; i += 2) { + /* 1) Load 2 ZSTD_Sequence (32 bytes) */ + __m256i vin = _mm256_loadu_si256((__m256i const*)&inSeqs[i]); + + /* 2) Add {2, 0, -3, 0} in each 128-bit half */ + __m256i vadd = _mm256_add_epi32(vin, addition); + + /* 3) Shuffle bytes so each half gives us the 8 bytes we need */ + __m256i vshf = _mm256_shuffle_epi8(vadd, mask); + /* + * Now: + * Lane0 = seq0's 8 bytes + * Lane1 = 0 + * Lane2 = seq1's 8 bytes + * Lane3 = 0 + */ + + /* 4) Permute 64-bit lanes => move Lane2 down into Lane1. */ + __m256i vperm = _mm256_permute4x64_epi64(vshf, PERM_LANE_0X_E8); + /* + * Now the lower 16 bytes (Lane0+Lane1) = [seq0, seq1]. + * The upper 16 bytes are [Lane2, Lane3] = [seq1, 0], but we won't use them. + */ + + /* 5) Store only the lower 16 bytes => 2 SeqDef (8 bytes each) */ + _mm_storeu_si128((__m128i *)&dstSeqs[i], _mm256_castsi256_si128(vperm)); + /* + * This writes out 16 bytes total: + * - offset 0..7 => seq0 (offBase, litLength, mlBase) + * - offset 8..15 => seq1 (offBase, litLength, mlBase) + */ + } + + /* Handle leftover if nbSequences is odd */ + if (i < nbSequences) { + /* Fallback: process last sequence */ + assert(i == nbSequences - 1); + dstSeqs[i].offBase = OFFSET_TO_OFFBASE(inSeqs[i].offset); + /* note: doesn't work if one length is > 65535 */ + dstSeqs[i].litLength = (U16)inSeqs[i].litLength; + dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH); + } +} + +#elif defined(__SSSE3__) + +#include /* SSSE3 intrinsics: _mm_shuffle_epi8 */ +#include /* SSE2 intrinsics: _mm_add_epi32, etc. */ + +/* + * Convert sequences with SSE. + * - offset -> offBase = offset + 2 + * - litLength (32-bit) -> (U16) litLength + * - matchLength (32-bit) -> (U16)(matchLength - 3) + * - rep is discarded. + * + * We shuffle so that only the first 8 bytes in the final 128-bit + * register are used. We still store 16 bytes (low 8 are good, high 8 are "don't care"). + */ +static void convertSequences_noRepcodes(SeqDef* dstSeqs, + const ZSTD_Sequence* inSeqs, + size_t nbSequences) +{ + /* + addition = { offset+2, litLength+0, matchLength-3, rep+0 } + setr means the first argument is placed in the lowest 32 bits, + second in next-lower 32 bits, etc. + */ + const __m128i addition = _mm_setr_epi32(2, 0, -3, 0); + + /* + Shuffle mask: we reorder bytes after the addition. + + Input layout in 128-bit register (after addition): + Bytes: [ 0..3 | 4..7 | 8..11 | 12..15 ] + Fields: offset+2 litLength matchLength rep + + We want in output: + Bytes: [ 0..3 | 4..5 | 6..7 | 8..15 ignore ] + Fields: offset+2 (U16)litLength (U16)(matchLength) + + _mm_shuffle_epi8 picks bytes from the source. A byte of 0x80 means “zero out”. + So we want: + out[0] = in[0], out[1] = in[1], out[2] = in[2], out[3] = in[3], // offset+2 (4 bytes) + out[4] = in[4], out[5] = in[5], // (U16) litLength + out[6] = in[8], out[7] = in[9], // (U16) matchLength + out[8..15] = 0x80 => won't matter if we only care about first 8 bytes + */ + const __m128i mask = _mm_setr_epi8( + 0, 1, 2, 3, /* offset (4 bytes) */ + 4, 5, /* litLength (2 bytes) */ + 8, 9, /* matchLength (2 bytes) */ + (char)0x80, (char)0x80, (char)0x80, (char)0x80, + (char)0x80, (char)0x80, (char)0x80, (char)0x80 + ); + size_t i; + + for (i = 0; i + 1 < nbSequences; i += 2) { + /*-------------------------*/ + /* Process inSeqs[i] */ + /*-------------------------*/ + __m128i vin0 = _mm_loadu_si128((const __m128i *)(const void*)&inSeqs[i]); + __m128i vadd0 = _mm_add_epi32(vin0, addition); + __m128i vshf0 = _mm_shuffle_epi8(vadd0, mask); + _mm_storel_epi64((__m128i *)(void*)&dstSeqs[i], vshf0); + + /*-------------------------*/ + /* Process inSeqs[i + 1] */ + /*-------------------------*/ + __m128i vin1 = _mm_loadu_si128((__m128i const *)(const void*)&inSeqs[i + 1]); + __m128i vadd1 = _mm_add_epi32(vin1, addition); + __m128i vshf1 = _mm_shuffle_epi8(vadd1, mask); + _mm_storel_epi64((__m128i *)(void*)&dstSeqs[i + 1], vshf1); + } + + /* Handle leftover if nbSequences is odd */ + if (i < nbSequences) { + /* Fallback: process last sequence */ + assert(i == nbSequences - 1); + dstSeqs[i].offBase = OFFSET_TO_OFFBASE(inSeqs[i].offset); + /* note: doesn't work if one length is > 65535 */ + dstSeqs[i].litLength = (U16)inSeqs[i].litLength; + dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH); + } + +} + +#else /* no SSE */ + +FORCE_INLINE_TEMPLATE void convertSequences_noRepcodes(SeqDef* dstSeqs, + const ZSTD_Sequence* const inSeqs, size_t nbSequences) +{ + size_t n; + for (n=0; n 65535 */ + dstSeqs[n].litLength = (U16)inSeqs[n].litLength; + dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH); + } +} + +#endif + +/* + * Precondition: Sequences must end on an explicit Block Delimiter * @return: 0 on success, or an error code. * Note: Sequence validation functionality has been disabled (removed). * This is helpful to generate a lean main pipeline, improving performance. * It may be re-inserted later. */ -size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, - const ZSTD_Sequence* const inSeqs, size_t nbSequences, - int repcodeResolution) +static size_t ZSTD_convertBlockSequences_internal(ZSTD_CCtx* cctx, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + int repcodeResolution) { Repcodes_t updatedRepcodes; size_t seqNb = 0; @@ -7129,21 +7342,26 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, assert(inSeqs[nbSequences-1].offset == 0); /* Convert Sequences from public format to internal format */ - for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) { - U32 const litLength = inSeqs[seqNb].litLength; - U32 const matchLength = inSeqs[seqNb].matchLength; - U32 offBase; + if (!repcodeResolution) { + convertSequences_noRepcodes(cctx->seqStore.sequencesStart, inSeqs, nbSequences); + cctx->seqStore.sequences += nbSequences; + } else { + for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) { + U32 const litLength = inSeqs[seqNb].litLength; + U32 const matchLength = inSeqs[seqNb].matchLength; + U32 offBase; - if (!repcodeResolution) { - offBase = OFFSET_TO_OFFBASE(inSeqs[seqNb].offset); - } else { - U32 const ll0 = (litLength == 0); - offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0); - ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); + if (!repcodeResolution) { + offBase = OFFSET_TO_OFFBASE(inSeqs[seqNb].offset); + } else { + U32 const ll0 = (litLength == 0); + offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0); + ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); + } + + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); + ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); } - - DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); - ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); } /* If we skipped repcode search while parsing, we need to update repcodes now */ @@ -7172,6 +7390,20 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, return 0; } +static size_t ZSTD_convertBlockSequences_noRepcode(ZSTD_CCtx* cctx, + const ZSTD_Sequence* const inSeqs, size_t nbSequences) +{ + return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); +} + +size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, + const ZSTD_Sequence* const inSeqs, size_t nbSequences, + int repcodeResolution) +{ + (void)repcodeResolution; + return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); +} + typedef struct { size_t nbSequences; size_t blockSize; diff --git a/tests/Makefile b/tests/Makefile index 982181de8..abb0b2b1d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -148,7 +148,7 @@ fullbench32: CPPFLAGS += -m32 $(FULLBENCHS) : CPPFLAGS += $(MULTITHREAD_CPP) -Wno-deprecated-declarations $(FULLBENCHS) : LDFLAGS += $(MULTITHREAD_LD) $(FULLBENCHS) : DEBUGFLAGS = -DNDEBUG # turn off assert() for speed measurements -$(FULLBENCHS) : DEBUGLEVEL ?= 0 # turn off assert() for speed measurements +$(FULLBENCHS) : DEBUGLEVEL = 0 # turn off assert() for speed measurements $(FULLBENCHS) : $(ZSTD_FILES) $(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c $(LINK.c) $^ -o $@$(EXT) From d1f0e5fb9738073150e7e5c25b03444b5a6a5389 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 15:51:38 -0800 Subject: [PATCH 296/405] fullbench can run a verification function compressSequencesAndLiterals: fixed long lengths in scalar mode --- lib/compress/zstd_compress.c | 29 +++++++++++-- tests/fullbench.c | 80 +++++++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d91fae619..c8dc86ccf 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7205,7 +7205,7 @@ void convertSequences_noRepcodes( */ } - /* Handle leftover if nbSequences is odd */ + /* Handle leftover if @nbSequences is odd */ if (i < nbSequences) { /* Fallback: process last sequence */ assert(i == nbSequences - 1); @@ -7301,16 +7301,23 @@ static void convertSequences_noRepcodes(SeqDef* dstSeqs, #else /* no SSE */ -FORCE_INLINE_TEMPLATE void convertSequences_noRepcodes(SeqDef* dstSeqs, +static size_t +convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* const inSeqs, size_t nbSequences) { + size_t longLen = 0; size_t n; for (n=0; n 65535 */ dstSeqs[n].litLength = (U16)inSeqs[n].litLength; dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH); + if (UNLIKELY(inSeqs[n].litLength > 65535)) { + assert(longLen == 0); + longLen = n + nbSequences + 1; + } } + return longLen; } #endif @@ -7343,8 +7350,22 @@ static size_t ZSTD_convertBlockSequences_internal(ZSTD_CCtx* cctx, /* Convert Sequences from public format to internal format */ if (!repcodeResolution) { - convertSequences_noRepcodes(cctx->seqStore.sequencesStart, inSeqs, nbSequences); - cctx->seqStore.sequences += nbSequences; + size_t const longl = convertSequences_noRepcodes(cctx->seqStore.sequencesStart, inSeqs, nbSequences-1); + cctx->seqStore.sequences = cctx->seqStore.sequencesStart + nbSequences-1; + if (longl) { + DEBUGLOG(5, "long length"); + assert(cctx->seqStore.longLengthType == ZSTD_llt_none); + if (longl <= nbSequences-1) { + DEBUGLOG(5, "long match length detected at pos %zu", longl-1); + cctx->seqStore.longLengthType = ZSTD_llt_matchLength; + cctx->seqStore.longLengthPos = (U32)(longl-1); + } else { + DEBUGLOG(5, "long literals length detected at pos %zu", longl-nbSequences); + assert(longl <= 2* (nbSequences-1)); + cctx->seqStore.longLengthType = ZSTD_llt_literalLength; + cctx->seqStore.longLengthPos = (U32)(longl-nbSequences); + } + } } else { for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) { U32 const litLength = inSeqs[seqNb].litLength; diff --git a/tests/fullbench.c b/tests/fullbench.c index 5683eca25..739e55ef2 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -687,6 +687,23 @@ local_convertSequences(const void* input, size_t inputSize, return nbSeqs; } +static size_t +check_compressedSequences(const void* compressed, size_t cSize, const void* orig, size_t origSize) +{ + size_t decSize; + int diff; + void* decompressed = malloc(origSize); + if (decompressed == NULL) return 2; + + decSize = ZSTD_decompress(decompressed, origSize, compressed, cSize); + if (decSize != origSize) { free(decompressed); DISPLAY("ZSTD_decompress failed (%zu) ", decSize); return 1; } + + diff = memcmp(decompressed, orig, origSize); + if (diff) { free(decompressed); return 1; } + + free(decompressed); + return 0; +} static PrepResult prepCopy(const void* src, size_t srcSize, int cLevel) { @@ -714,40 +731,43 @@ static PrepResult prepShorterDstCapacity(const void* src, size_t srcSize, int cL * List of Scenarios *********************************************************/ -/* if PrepFunction_f returns 0, benchmarking is cancelled */ +/* if PrepFunction_f returns PrepResult.prepBuffSize == 0, benchmarking is cancelled */ typedef PrepResult (*PrepFunction_f)(const void* src, size_t srcSize, int cLevel); typedef size_t (*BenchedFunction_f)(const void* src, size_t srcSize, void* dst, size_t dstSize, void* opaque); +/* must return 0, otherwise verification is considered failed */ +typedef size_t (*VerifFunction_f)(const void* processed, size_t procSize, const void* input, size_t inputSize); typedef struct { const char* name; PrepFunction_f preparation_f; - BenchedFunction_f benchedFunction; + BenchedFunction_f benched_f; + VerifFunction_f verif_f; /* optional */ } BenchScenario; static BenchScenario kScenarios[] = { - { "compress", NULL, local_ZSTD_compress }, - { "decompress", prepDecompress, local_ZSTD_decompress }, - { "compress_freshCCtx", NULL, local_ZSTD_compress_freshCCtx }, - { "decompressDCtx", prepDecompress, local_ZSTD_decompressDCtx }, - { "compressContinue", NULL, local_ZSTD_compressContinue }, - { "compressContinue_extDict", NULL, local_ZSTD_compressContinue_extDict }, - { "decompressContinue", prepDecompress, local_ZSTD_decompressContinue }, - { "compressStream", NULL, local_ZSTD_compressStream }, - { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx }, - { "decompressStream", prepDecompress, local_ZSTD_decompressStream }, - { "compress2", NULL, local_ZSTD_compress2 }, - { "compressStream2, end", NULL, local_ZSTD_compressStream2_end }, - { "compressStream2, end & short", prepShorterDstCapacity, local_ZSTD_compressStream2_end }, - { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue }, - { "compressStream2, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue }, - { "compressStream2, -T2, end", NULL, local_ZSTD_compress_generic_T2_end }, - { "compressSequences", prepSequences, local_compressSequences }, - { "compressSequencesAndLiterals", prepSequencesAndLiterals, local_compressSequencesAndLiterals }, - { "convertSequences (1st block)", prepConvertSequences, local_convertSequences }, + { "compress", NULL, local_ZSTD_compress, NULL }, + { "decompress", prepDecompress, local_ZSTD_decompress, NULL }, + { "compress_freshCCtx", NULL, local_ZSTD_compress_freshCCtx, NULL }, + { "decompressDCtx", prepDecompress, local_ZSTD_decompressDCtx, NULL }, + { "compressContinue", NULL, local_ZSTD_compressContinue, NULL }, + { "compressContinue_extDict", NULL, local_ZSTD_compressContinue_extDict, NULL }, + { "decompressContinue", prepDecompress, local_ZSTD_decompressContinue, NULL }, + { "compressStream", NULL, local_ZSTD_compressStream, NULL }, + { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx, NULL }, + { "decompressStream", prepDecompress, local_ZSTD_decompressStream, NULL }, + { "compress2", NULL, local_ZSTD_compress2, NULL }, + { "compressStream2, end", NULL, local_ZSTD_compressStream2_end, NULL }, + { "compressStream2, end & short", prepShorterDstCapacity, local_ZSTD_compressStream2_end, NULL }, + { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue, NULL }, + { "compressStream2, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue, NULL }, + { "compressStream2, -T2, end", NULL, local_ZSTD_compress_generic_T2_end, NULL }, + { "compressSequences", prepSequences, local_compressSequences, check_compressedSequences }, + { "compressSequencesAndLiterals", prepSequencesAndLiterals, local_compressSequencesAndLiterals, check_compressedSequences }, + { "convertSequences (1st block)", prepConvertSequences, local_convertSequences, NULL }, #ifndef ZSTD_DLL_IMPORT - { "decodeLiteralsHeader (1st block)", prepLiterals, local_ZSTD_decodeLiteralsHeader }, - { "decodeLiteralsBlock (1st block)", prepLiterals, local_ZSTD_decodeLiteralsBlock }, - { "decodeSeqHeaders (1st block)", prepSequences1stBlock, local_ZSTD_decodeSeqHeaders }, + { "decodeLiteralsHeader (1st block)", prepLiterals, local_ZSTD_decodeLiteralsHeader, NULL }, + { "decodeLiteralsBlock (1st block)", prepLiterals, local_ZSTD_decodeLiteralsBlock, NULL }, + { "decodeSeqHeaders (1st block)", prepSequences1stBlock, local_ZSTD_decodeSeqHeaders, NULL }, #endif }; #define NB_SCENARIOS (sizeof(kScenarios) / sizeof(kScenarios[0])) @@ -767,13 +787,15 @@ static int benchMem(unsigned scenarioID, const char* benchName; BMK_benchFn_t benchFunction; PrepFunction_f prep_f; + VerifFunction_f verif_f; int errorcode = 0; if (scenarioID >= NB_SCENARIOS) return 0; /* scenario doesn't exist */ benchName = kScenarios[scenarioID].name; - benchFunction = kScenarios[scenarioID].benchedFunction; + benchFunction = kScenarios[scenarioID].benched_f; prep_f = kScenarios[scenarioID].preparation_f; + verif_f = kScenarios[scenarioID].verif_f; if (prep_f == NULL) prep_f = prepCopy; /* default */ /* Initialization */ @@ -857,6 +879,14 @@ static int benchMem(unsigned scenarioID, scenarioID, benchName, (double)origSrcSize * TIMELOOP_NANOSEC / bestResult.nanoSecPerRun / MB_UNIT, (unsigned)newResult.sumOfReturn ); + + if (verif_f) { + size_t const vRes = verif_f(dst, newResult.sumOfReturn, origSrc, origSrcSize); + if (vRes) { + DISPLAY(" validation failed ! (%zu)\n", vRes); + break; + } + } } if ( BMK_isCompleted_TimedFn(tfs) ) break; From 8d621645891a8ec8a114fe09e94f967f2049352b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 16:42:36 -0800 Subject: [PATCH 297/405] control long length within AVX2 implementation --- lib/compress/zstd_compress.c | 150 ++++++++++++++--------------------- 1 file changed, 60 insertions(+), 90 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index c8dc86ccf..a52980313 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7121,8 +7121,12 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, * At the end, instead of extracting two __m128i, * we use _mm256_permute4x64_epi64(..., 0xE8) to move lane2 into lane1, * then store the lower 16 bytes in one go. + * + * @returns 0 on succes, with no long length detected + * @returns > 0 if there is one long length (> 65535), + * indicating the position, and type. */ -void convertSequences_noRepcodes( +size_t convertSequences_noRepcodes( SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs, size_t nbSequences) @@ -7136,6 +7140,9 @@ void convertSequences_noRepcodes( ZSTD_REP_NUM, 0, -MINMATCH, 0 /* for sequence i+1 */ ); + /* limit: check if there is a long length */ + const __m256i limit = _mm256_set1_epi32(65535); + /* * shuffle mask for byte-level rearrangement in each 128-bit half: * @@ -7170,16 +7177,20 @@ void convertSequences_noRepcodes( */ #define PERM_LANE_0X_E8 0xE8 /* [0,2,2,3] in lane indices */ - size_t i = 0; + size_t longLen = 0, i = 0; /* Process 2 sequences per loop iteration */ for (; i + 1 < nbSequences; i += 2) { - /* 1) Load 2 ZSTD_Sequence (32 bytes) */ + /* Load 2 ZSTD_Sequence (32 bytes) */ __m256i vin = _mm256_loadu_si256((__m256i const*)&inSeqs[i]); - /* 2) Add {2, 0, -3, 0} in each 128-bit half */ + /* Add {2, 0, -3, 0} in each 128-bit half */ __m256i vadd = _mm256_add_epi32(vin, addition); - /* 3) Shuffle bytes so each half gives us the 8 bytes we need */ + /* Check for long length */ + __m256i cmp = _mm256_cmpgt_epi32(vadd, limit); // 0xFFFFFFFF for element > 65535 + int cmp_res = _mm256_movemask_epi8(cmp); + + /* Shuffle bytes so each half gives us the 8 bytes we need */ __m256i vshf = _mm256_shuffle_epi8(vadd, mask); /* * Now: @@ -7189,20 +7200,44 @@ void convertSequences_noRepcodes( * Lane3 = 0 */ - /* 4) Permute 64-bit lanes => move Lane2 down into Lane1. */ + /* Permute 64-bit lanes => move Lane2 down into Lane1. */ __m256i vperm = _mm256_permute4x64_epi64(vshf, PERM_LANE_0X_E8); /* * Now the lower 16 bytes (Lane0+Lane1) = [seq0, seq1]. * The upper 16 bytes are [Lane2, Lane3] = [seq1, 0], but we won't use them. */ - /* 5) Store only the lower 16 bytes => 2 SeqDef (8 bytes each) */ + /* Store only the lower 16 bytes => 2 SeqDef (8 bytes each) */ _mm_storeu_si128((__m128i *)&dstSeqs[i], _mm256_castsi256_si128(vperm)); /* * This writes out 16 bytes total: * - offset 0..7 => seq0 (offBase, litLength, mlBase) * - offset 8..15 => seq1 (offBase, litLength, mlBase) */ + + /* check (unlikely) long lengths > 65535 + * indices for lengths correspond to bits [4..7], [8..11], [20..23], [24..27] + * => combined mask = 0x0FF00FF0 + */ + if (UNLIKELY((cmp_res & 0x0FF00FF0) != 0)) { + /* long length detected: let's figure out which one*/ + if (inSeqs[i].matchLength > 65535+MINMATCH) { + assert(longLen == 0); + longLen = i + 1; + } + if (inSeqs[i].litLength > 65535) { + assert(longLen == 0); + longLen = i + nbSequences + 1; + } + if (inSeqs[i+1].matchLength > 65535+MINMATCH) { + assert(longLen == 0); + longLen = i + 1 + 1; + } + if (inSeqs[i+1].litLength > 65535) { + assert(longLen == 0); + longLen = i + 1 + nbSequences + 1; + } + } } /* Handle leftover if @nbSequences is odd */ @@ -7213,93 +7248,24 @@ void convertSequences_noRepcodes( /* note: doesn't work if one length is > 65535 */ dstSeqs[i].litLength = (U16)inSeqs[i].litLength; dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH); + if (UNLIKELY(inSeqs[i].matchLength > 65535+MINMATCH)) { + assert(longLen == 0); + longLen = i + 1; + } + if (UNLIKELY(inSeqs[i].litLength > 65535)) { + assert(longLen == 0); + longLen = i + nbSequences + 1; + } } + + return longLen; } -#elif defined(__SSSE3__) +/* the vector implementation could also be ported to SSSE3, + * but since this implementation is targeting modern systems >= Sapphire Rapid, + * it's not useful to develop and maintain code for older platforms (before AVX2) */ -#include /* SSSE3 intrinsics: _mm_shuffle_epi8 */ -#include /* SSE2 intrinsics: _mm_add_epi32, etc. */ - -/* - * Convert sequences with SSE. - * - offset -> offBase = offset + 2 - * - litLength (32-bit) -> (U16) litLength - * - matchLength (32-bit) -> (U16)(matchLength - 3) - * - rep is discarded. - * - * We shuffle so that only the first 8 bytes in the final 128-bit - * register are used. We still store 16 bytes (low 8 are good, high 8 are "don't care"). - */ -static void convertSequences_noRepcodes(SeqDef* dstSeqs, - const ZSTD_Sequence* inSeqs, - size_t nbSequences) -{ - /* - addition = { offset+2, litLength+0, matchLength-3, rep+0 } - setr means the first argument is placed in the lowest 32 bits, - second in next-lower 32 bits, etc. - */ - const __m128i addition = _mm_setr_epi32(2, 0, -3, 0); - - /* - Shuffle mask: we reorder bytes after the addition. - - Input layout in 128-bit register (after addition): - Bytes: [ 0..3 | 4..7 | 8..11 | 12..15 ] - Fields: offset+2 litLength matchLength rep - - We want in output: - Bytes: [ 0..3 | 4..5 | 6..7 | 8..15 ignore ] - Fields: offset+2 (U16)litLength (U16)(matchLength) - - _mm_shuffle_epi8 picks bytes from the source. A byte of 0x80 means “zero out”. - So we want: - out[0] = in[0], out[1] = in[1], out[2] = in[2], out[3] = in[3], // offset+2 (4 bytes) - out[4] = in[4], out[5] = in[5], // (U16) litLength - out[6] = in[8], out[7] = in[9], // (U16) matchLength - out[8..15] = 0x80 => won't matter if we only care about first 8 bytes - */ - const __m128i mask = _mm_setr_epi8( - 0, 1, 2, 3, /* offset (4 bytes) */ - 4, 5, /* litLength (2 bytes) */ - 8, 9, /* matchLength (2 bytes) */ - (char)0x80, (char)0x80, (char)0x80, (char)0x80, - (char)0x80, (char)0x80, (char)0x80, (char)0x80 - ); - size_t i; - - for (i = 0; i + 1 < nbSequences; i += 2) { - /*-------------------------*/ - /* Process inSeqs[i] */ - /*-------------------------*/ - __m128i vin0 = _mm_loadu_si128((const __m128i *)(const void*)&inSeqs[i]); - __m128i vadd0 = _mm_add_epi32(vin0, addition); - __m128i vshf0 = _mm_shuffle_epi8(vadd0, mask); - _mm_storel_epi64((__m128i *)(void*)&dstSeqs[i], vshf0); - - /*-------------------------*/ - /* Process inSeqs[i + 1] */ - /*-------------------------*/ - __m128i vin1 = _mm_loadu_si128((__m128i const *)(const void*)&inSeqs[i + 1]); - __m128i vadd1 = _mm_add_epi32(vin1, addition); - __m128i vshf1 = _mm_shuffle_epi8(vadd1, mask); - _mm_storel_epi64((__m128i *)(void*)&dstSeqs[i + 1], vshf1); - } - - /* Handle leftover if nbSequences is odd */ - if (i < nbSequences) { - /* Fallback: process last sequence */ - assert(i == nbSequences - 1); - dstSeqs[i].offBase = OFFSET_TO_OFFBASE(inSeqs[i].offset); - /* note: doesn't work if one length is > 65535 */ - dstSeqs[i].litLength = (U16)inSeqs[i].litLength; - dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH); - } - -} - -#else /* no SSE */ +#else /* no AVX2 */ static size_t convertSequences_noRepcodes(SeqDef* dstSeqs, @@ -7312,6 +7278,10 @@ convertSequences_noRepcodes(SeqDef* dstSeqs, /* note: doesn't work if one length is > 65535 */ dstSeqs[n].litLength = (U16)inSeqs[n].litLength; dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH); + if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) { + assert(longLen == 0); + longLen = n + 1; + } if (UNLIKELY(inSeqs[n].litLength > 65535)) { assert(longLen == 0); longLen = n + nbSequences + 1; From bfc58f5ba24a3c27edfbc61288e09d2837235456 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 17:04:12 -0800 Subject: [PATCH 298/405] generalize validation function --- tests/fullbench.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 739e55ef2..3cc5c2341 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -745,22 +745,22 @@ typedef struct { } BenchScenario; static BenchScenario kScenarios[] = { - { "compress", NULL, local_ZSTD_compress, NULL }, + { "compress", NULL, local_ZSTD_compress, check_compressedSequences }, { "decompress", prepDecompress, local_ZSTD_decompress, NULL }, - { "compress_freshCCtx", NULL, local_ZSTD_compress_freshCCtx, NULL }, + { "compress_freshCCtx", NULL, local_ZSTD_compress_freshCCtx, check_compressedSequences }, { "decompressDCtx", prepDecompress, local_ZSTD_decompressDCtx, NULL }, - { "compressContinue", NULL, local_ZSTD_compressContinue, NULL }, + { "compressContinue", NULL, local_ZSTD_compressContinue, check_compressedSequences }, { "compressContinue_extDict", NULL, local_ZSTD_compressContinue_extDict, NULL }, { "decompressContinue", prepDecompress, local_ZSTD_decompressContinue, NULL }, - { "compressStream", NULL, local_ZSTD_compressStream, NULL }, - { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx, NULL }, + { "compressStream", NULL, local_ZSTD_compressStream, check_compressedSequences }, + { "compressStream_freshCCtx", NULL, local_ZSTD_compressStream_freshCCtx, check_compressedSequences }, { "decompressStream", prepDecompress, local_ZSTD_decompressStream, NULL }, - { "compress2", NULL, local_ZSTD_compress2, NULL }, - { "compressStream2, end", NULL, local_ZSTD_compressStream2_end, NULL }, - { "compressStream2, end & short", prepShorterDstCapacity, local_ZSTD_compressStream2_end, NULL }, - { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue, NULL }, - { "compressStream2, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue, NULL }, - { "compressStream2, -T2, end", NULL, local_ZSTD_compress_generic_T2_end, NULL }, + { "compress2", NULL, local_ZSTD_compress2, check_compressedSequences }, + { "compressStream2, end", NULL, local_ZSTD_compressStream2_end, check_compressedSequences }, + { "compressStream2, end & short", prepShorterDstCapacity, local_ZSTD_compressStream2_end, check_compressedSequences }, + { "compressStream2, continue", NULL, local_ZSTD_compressStream2_continue, check_compressedSequences }, + { "compressStream2, -T2, continue", NULL, local_ZSTD_compress_generic_T2_continue, check_compressedSequences }, + { "compressStream2, -T2, end", NULL, local_ZSTD_compress_generic_T2_end, check_compressedSequences }, { "compressSequences", prepSequences, local_compressSequences, check_compressedSequences }, { "compressSequencesAndLiterals", prepSequencesAndLiterals, local_compressSequencesAndLiterals, check_compressedSequences }, { "convertSequences (1st block)", prepConvertSequences, local_convertSequences, NULL }, From 8eb2587432d70359f26ff98fd12db7e8c9be7515 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 19:29:06 -0800 Subject: [PATCH 299/405] added benchmark for get1BlockSummary() --- lib/compress/zstd_compress.c | 10 ++-------- lib/compress/zstd_compress_internal.h | 7 +++++++ tests/fullbench.c | 21 +++++++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a52980313..d5e3d1c78 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7395,13 +7395,7 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); } -typedef struct { - size_t nbSequences; - size_t blockSize; - size_t litSize; -} BlockSummary; - -static BlockSummary get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) +BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) { size_t blockSize = 0; size_t litSize = 0; @@ -7456,7 +7450,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, while (nbSequences) { size_t compressedSeqsSize, cBlockSize, conversionStatus; - BlockSummary const block = get1BlockSummary(inSeqs, nbSequences); + BlockSummary const block = ZSTD_get1BlockSummary(inSeqs, nbSequences); U32 const lastBlock = (block.nbSequences == nbSequences); FORWARD_IF_ERROR(block.nbSequences, "Error while trying to determine nb of sequences for a block"); assert(block.nbSequences <= nbSequences); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 2be67a124..ca5e2a4c5 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1525,6 +1525,13 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, const ZSTD_Sequence* const inSeqs, size_t nbSequences, int const repcodeResolution); +typedef struct { + size_t nbSequences; + size_t blockSize; + size_t litSize; +} BlockSummary; + +BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs); /* ============================================================== * Private declarations diff --git a/tests/fullbench.c b/tests/fullbench.c index 3cc5c2341..7d77bd176 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -705,6 +705,26 @@ check_compressedSequences(const void* compressed, size_t cSize, const void* orig return 0; } +static size_t +local_get1BlockSummary(const void* input, size_t inputSize, + void* dst, size_t dstCapacity, + void* payload) +{ + const char* ip = input; + size_t const blockSize = MEM_read32(ip); + size_t const nbSeqs = MEM_read32(ip+=4); + const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4); + ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters); + ZSTD_resetSeqStore(&g_zcc->seqStore); + ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters); + assert(8 + nbSeqs * sizeof(ZSTD_Sequence) == inputSize); (void)inputSize; + (void)dst; (void)dstCapacity; + (void)payload; (void)blockSize; + + (void)ZSTD_get1BlockSummary(seqs, nbSeqs); + return nbSeqs; +} + static PrepResult prepCopy(const void* src, size_t srcSize, int cLevel) { PrepResult r = PREPRESULT_INIT; @@ -764,6 +784,7 @@ static BenchScenario kScenarios[] = { { "compressSequences", prepSequences, local_compressSequences, check_compressedSequences }, { "compressSequencesAndLiterals", prepSequencesAndLiterals, local_compressSequencesAndLiterals, check_compressedSequences }, { "convertSequences (1st block)", prepConvertSequences, local_convertSequences, NULL }, + { "get1BlockSummary (1st block)", prepConvertSequences, local_get1BlockSummary, NULL }, #ifndef ZSTD_DLL_IMPORT { "decodeLiteralsHeader (1st block)", prepLiterals, local_ZSTD_decodeLiteralsHeader, NULL }, { "decodeLiteralsBlock (1st block)", prepLiterals, local_ZSTD_decodeLiteralsBlock, NULL }, From b6a4d5a8ba29bc873c95098103f57f987cfacd23 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 19:34:06 -0800 Subject: [PATCH 300/405] minor +10% speed improvement for scalar ZSTD_get1BlockSummary() --- lib/compress/zstd_compress.c | 61 ++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d5e3d1c78..11933fb3c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7395,14 +7395,68 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); } +#if 0 && defined(__AVX2__) + +/* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ +#if defined(__GNUC__) +# define ALIGNED32 __attribute__((aligned(32))) +#else +# define ALIGNED32 +#endif + BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) { - size_t blockSize = 0; + size_t i; + __m256i sumVec; /* accumulates match+lit in 32-bit lanes */ + __m256i mask; /* shuffling control */ + ALIGNED32 int tmp[8]; /* temporary buffer for reduction */ + uint64_t sum; + int k; + + sumVec = _mm256_setzero_si256(); + mask = _mm256_setr_epi32( + 1,5, /* match(0), match(1) */ + 2,6, /* lit(0), lit(1) */ + 1,5, /* match(0), match(1) */ + 2,6 /* lit(0), lit(1) */ + ); + + /* Process 2 structs (32 bytes) at a time */ + for (i = 0; i + 2 <= count; i += 2) { + /* Load two consecutive MyStructs (8×4 = 32 bytes) */ + __m256i data = _mm256_loadu_si256((const __m256i*)&arr[i]); + /* Shuffle out lanes 1,2,5,6 => match(0), match(1), lit(0), lit(1), repeated */ + __m256i selected = _mm256_permutevar8x32_epi32(data, mask); + /* Accumulate in sumVec */ + sumVec = _mm256_add_epi32(sumVec, selected); + } + + /* Horizontal reduction of sumVec */ + _mm256_store_si256((__m256i*)tmp, sumVec); + sum = 0; + for (k = 0; k < 8; k++) { + sum += (uint64_t)tmp[k]; /* each lane is match+lit from pairs, repeated twice */ + } + + /* Handle the leftover (if count is odd) */ + for (; i < count; i++) { + sum += arr[i].matchLength; + sum += arr[i].litLength; + } + + return sum; +} + +#else + +BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) +{ + size_t totalMatchSize = 0; size_t litSize = 0; size_t n; assert(seqs); for (n=0; n Date: Tue, 7 Jan 2025 23:32:05 -0800 Subject: [PATCH 301/405] AVX2 version of ZSTD_get1BlockSummary() --- lib/compress/zstd_compress.c | 69 ++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 11933fb3c..445c5613a 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7395,56 +7395,65 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); } -#if 0 && defined(__AVX2__) +#if defined(__AVX2__) /* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ #if defined(__GNUC__) # define ALIGNED32 __attribute__((aligned(32))) +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ +# define ALIGNED32 alignas(32) #else + /* this compiler will require its own alignment instruction */ # define ALIGNED32 #endif BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) { size_t i; - __m256i sumVec; /* accumulates match+lit in 32-bit lanes */ - __m256i mask; /* shuffling control */ - ALIGNED32 int tmp[8]; /* temporary buffer for reduction */ - uint64_t sum; - int k; - - sumVec = _mm256_setzero_si256(); - mask = _mm256_setr_epi32( - 1,5, /* match(0), match(1) */ - 2,6, /* lit(0), lit(1) */ - 1,5, /* match(0), match(1) */ - 2,6 /* lit(0), lit(1) */ - ); + __m256i const zeroVec = _mm256_setzero_si256(); + __m256i sumVec = zeroVec; /* accumulates match+lit in 32-bit lanes */ + __m256i shuffle32; /* shuffling control */ + ALIGNED32 U32 tmp[8]; /* temporary buffer for reduction */ + size_t mSum = 0, lSum = 0; /* Process 2 structs (32 bytes) at a time */ - for (i = 0; i + 2 <= count; i += 2) { - /* Load two consecutive MyStructs (8×4 = 32 bytes) */ - __m256i data = _mm256_loadu_si256((const __m256i*)&arr[i]); - /* Shuffle out lanes 1,2,5,6 => match(0), match(1), lit(0), lit(1), repeated */ - __m256i selected = _mm256_permutevar8x32_epi32(data, mask); + for (i = 0; i + 2 <= nbSeqs; i += 2) { + /* Load two consecutive ZSTD_Sequence (8×4 = 32 bytes) */ + __m256i data = _mm256_loadu_si256((const __m256i*)&seqs[i]); + /* check end of block signal */ + __m256i cmp = _mm256_cmpeq_epi32(data, zeroVec); + int cmp_res = _mm256_movemask_epi8(cmp); + /* indices for match lengths correspond to bits [8..11], [24..27] + * => combined mask = 0x0F000F00 */ + if (cmp_res & 0x0F000F00) break; /* Accumulate in sumVec */ - sumVec = _mm256_add_epi32(sumVec, selected); + sumVec = _mm256_add_epi32(sumVec, data); } - /* Horizontal reduction of sumVec */ + /* Horizontal reduction */ _mm256_store_si256((__m256i*)tmp, sumVec); - sum = 0; - for (k = 0; k < 8; k++) { - sum += (uint64_t)tmp[k]; /* each lane is match+lit from pairs, repeated twice */ + lSum = tmp[1] + tmp[5]; + mSum = tmp[2] + tmp[6]; + + /* Handle the leftover */ + for (; i < nbSeqs; i++) { + lSum += seqs[i].litLength; + mSum += seqs[i].matchLength; + if (seqs[i].matchLength == 0) break; /* end of block */ } - /* Handle the leftover (if count is odd) */ - for (; i < count; i++) { - sum += arr[i].matchLength; - sum += arr[i].litLength; + if (i==nbSeqs) { + /* reaching end of sequences: end of block signal was not present */ + BlockSummary bs; + bs.nbSequences = ERROR(externalSequences_invalid); + return bs; + } + { BlockSummary bs; + bs.nbSequences = i+1; + bs.blockSize = lSum + mSum; + bs.litSize = lSum; + return bs; } - - return sum; } #else From cd53924eff684146b67e890d7b48158c37eca32c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 23:34:19 -0800 Subject: [PATCH 302/405] removed erroneous #includes that were automatically added by the editor without notification --- lib/compress/zstd_compress.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 445c5613a..beff0aae6 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -15,9 +15,7 @@ #include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */ #include "../common/mem.h" #include "../common/error_private.h" -#include "compiler.h" #include "hist.h" /* HIST_countFast_wksp */ -#include "zstd_internal.h" #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ #include "../common/fse.h" #include "../common/huf.h" From db3d48823a75a12a5ad9221e5a39191ff0044d3a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 23:40:49 -0800 Subject: [PATCH 303/405] no need for specialized variant the branch is not in the hot loop --- lib/compress/zstd_compress.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index beff0aae6..8e49169b1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7297,7 +7297,7 @@ convertSequences_noRepcodes(SeqDef* dstSeqs, * This is helpful to generate a lean main pipeline, improving performance. * It may be re-inserted later. */ -static size_t ZSTD_convertBlockSequences_internal(ZSTD_CCtx* cctx, +size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, const ZSTD_Sequence* const inSeqs, size_t nbSequences, int repcodeResolution) { @@ -7379,20 +7379,6 @@ static size_t ZSTD_convertBlockSequences_internal(ZSTD_CCtx* cctx, return 0; } -static size_t ZSTD_convertBlockSequences_noRepcode(ZSTD_CCtx* cctx, - const ZSTD_Sequence* const inSeqs, size_t nbSequences) -{ - return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); -} - -size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, - const ZSTD_Sequence* const inSeqs, size_t nbSequences, - int repcodeResolution) -{ - (void)repcodeResolution; - return ZSTD_convertBlockSequences_internal(cctx, inSeqs, nbSequences, 0); -} - #if defined(__AVX2__) /* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ From 4aaf9cefe9bdda1fafb5f6a5ba13294d2b478bd7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 23:45:15 -0800 Subject: [PATCH 304/405] fix minor conversion warning --- lib/compress/zstd_compress.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 8e49169b1..19fb584fb 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7157,15 +7157,15 @@ size_t convertSequences_noRepcodes( 0, 1, 2, 3, /* offset+2 */ 4, 5, /* litLength (16 bits) */ 8, 9, /* matchLength (16 bits) */ - (char)0x80, (char)0x80, (char)0x80, (char)0x80, - (char)0x80, (char)0x80, (char)0x80, (char)0x80, + (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, + (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, /* For the upper 128 bits => sequence i+1 */ 16,17,18,19, /* offset+2 */ 20,21, /* litLength */ 24,25, /* matchLength */ - (char)0x80, (char)0x80, (char)0x80, (char)0x80, - (char)0x80, (char)0x80, (char)0x80, (char)0x80 + (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, + (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80 ); /* From 57a45541927180724712b651ed1fb3e125105f30 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2025 23:59:01 -0800 Subject: [PATCH 305/405] removed unused variable --- lib/compress/zstd_compress.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 19fb584fb..e5b0cd80e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7396,7 +7396,6 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) size_t i; __m256i const zeroVec = _mm256_setzero_si256(); __m256i sumVec = zeroVec; /* accumulates match+lit in 32-bit lanes */ - __m256i shuffle32; /* shuffling control */ ALIGNED32 U32 tmp[8]; /* temporary buffer for reduction */ size_t mSum = 0, lSum = 0; From aa2cdf964f93d96113c09028ad7354ca2debc849 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 8 Jan 2025 10:51:57 -0800 Subject: [PATCH 306/405] added compilation-time checks to ensure AVX2 code is valid since it depends on a specific definition of ZSTD_Sequence structure. --- lib/compress/zstd_compress.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e5b0cd80e..f6cde3d09 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7176,6 +7176,17 @@ size_t convertSequences_noRepcodes( #define PERM_LANE_0X_E8 0xE8 /* [0,2,2,3] in lane indices */ size_t longLen = 0, i = 0; + + /* AVX permutation depends on the specific definition of target structures */ + ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16); + ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0); + ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4); + ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8); + ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8); + ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0); + ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4); + ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6); + /* Process 2 sequences per loop iteration */ for (; i + 1 < nbSequences; i += 2) { /* Load 2 ZSTD_Sequence (32 bytes) */ @@ -7398,6 +7409,7 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) __m256i sumVec = zeroVec; /* accumulates match+lit in 32-bit lanes */ ALIGNED32 U32 tmp[8]; /* temporary buffer for reduction */ size_t mSum = 0, lSum = 0; + ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16); /* Process 2 structs (32 bytes) at a time */ for (i = 0; i + 2 <= nbSeqs; i += 2) { @@ -7408,6 +7420,7 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) int cmp_res = _mm256_movemask_epi8(cmp); /* indices for match lengths correspond to bits [8..11], [24..27] * => combined mask = 0x0F000F00 */ + ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8); if (cmp_res & 0x0F000F00) break; /* Accumulate in sumVec */ sumVec = _mm256_add_epi32(sumVec, data); From e3181cfd325db59dbdeadcaf91b8187f49c5546c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 8 Jan 2025 14:25:03 -0800 Subject: [PATCH 307/405] minor code doc update --- lib/compress/zstd_compress.c | 16 ++++++++-------- lib/zstd.h | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index f6cde3d09..bdf0e8287 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7196,8 +7196,8 @@ size_t convertSequences_noRepcodes( __m256i vadd = _mm256_add_epi32(vin, addition); /* Check for long length */ - __m256i cmp = _mm256_cmpgt_epi32(vadd, limit); // 0xFFFFFFFF for element > 65535 - int cmp_res = _mm256_movemask_epi8(cmp); + __m256i ll_cmp = _mm256_cmpgt_epi32(vadd, limit); /* 0xFFFFFFFF for element > 65535 */ + int ll_res = _mm256_movemask_epi8(ll_cmp); /* Shuffle bytes so each half gives us the 8 bytes we need */ __m256i vshf = _mm256_shuffle_epi8(vadd, mask); @@ -7228,7 +7228,7 @@ size_t convertSequences_noRepcodes( * indices for lengths correspond to bits [4..7], [8..11], [20..23], [24..27] * => combined mask = 0x0FF00FF0 */ - if (UNLIKELY((cmp_res & 0x0FF00FF0) != 0)) { + if (UNLIKELY((ll_res & 0x0FF00FF0) != 0)) { /* long length detected: let's figure out which one*/ if (inSeqs[i].matchLength > 65535+MINMATCH) { assert(longLen == 0); @@ -7251,12 +7251,12 @@ size_t convertSequences_noRepcodes( /* Handle leftover if @nbSequences is odd */ if (i < nbSequences) { - /* Fallback: process last sequence */ + /* process last sequence */ assert(i == nbSequences - 1); dstSeqs[i].offBase = OFFSET_TO_OFFBASE(inSeqs[i].offset); - /* note: doesn't work if one length is > 65535 */ dstSeqs[i].litLength = (U16)inSeqs[i].litLength; dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH); + /* check (unlikely) long lengths > 65535 */ if (UNLIKELY(inSeqs[i].matchLength > 65535+MINMATCH)) { assert(longLen == 0); longLen = i + 1; @@ -7271,8 +7271,8 @@ size_t convertSequences_noRepcodes( } /* the vector implementation could also be ported to SSSE3, - * but since this implementation is targeting modern systems >= Sapphire Rapid, - * it's not useful to develop and maintain code for older platforms (before AVX2) */ + * but since this implementation is targeting modern systems (>= Sapphire Rapid), + * it's not useful to develop and maintain code for older pre-AVX2 platforms */ #else /* no AVX2 */ @@ -7284,9 +7284,9 @@ convertSequences_noRepcodes(SeqDef* dstSeqs, size_t n; for (n=0; n 65535 */ dstSeqs[n].litLength = (U16)inSeqs[n].litLength; dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH); + /* check for long length > 65535 */ if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) { assert(longLen == 0); longLen = n + 1; diff --git a/lib/zstd.h b/lib/zstd.h index 907a377d1..b8c0644a7 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1696,7 +1696,8 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * - Not compatible with frame checksum, which must be disabled * - If any block is incompressible, will fail and return an error * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error. - * - the buffer @literals must have a size @litCapacity which is larger than @litSize by at least 8 bytes. + * - @litBufCapacity is the size of the underlying buffer into which literals are written, starting at address @literals. + * @litBufCapacity must be at least 8 bytes larger than @litSize. * - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error. * @return : final compressed size, or a ZSTD error code. */ @@ -1704,7 +1705,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const ZSTD_Sequence* inSeqs, size_t nbSequences, - const void* literals, size_t litSize, size_t litCapacity, + const void* literals, size_t litSize, size_t litBufCapacity, size_t decompressedSize); From 6f8e6f3c97c8e95527a29c4667edca6b793f798f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 14 Jan 2025 14:44:02 -0800 Subject: [PATCH 308/405] create new compilation macro ZSTD_ARCH_X86_AVX2 --- lib/common/compiler.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index b6cbcee03..f636b7f25 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -224,6 +224,9 @@ /* compile time determination of SIMD support */ #if !defined(ZSTD_NO_INTRINSICS) +# if defined(__AVX2__) +# define ZSTD_ARCH_X86_AVX2 +# endif # if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) # define ZSTD_ARCH_X86_SSE2 # endif @@ -231,6 +234,9 @@ # define ZSTD_ARCH_ARM_NEON # endif # +# if defined(ZSTD_ARCH_X86_AVX2) +# include +# endif # if defined(ZSTD_ARCH_X86_SSE2) # include # elif defined(ZSTD_ARCH_ARM_NEON) From debe3d20d9ea0aaa45fbb692302347d0ece9f2c0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 14 Jan 2025 14:54:02 -0800 Subject: [PATCH 309/405] removed unused branch --- lib/compress/zstd_compress.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bdf0e8287..55622cbd5 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7349,18 +7349,12 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) { U32 const litLength = inSeqs[seqNb].litLength; U32 const matchLength = inSeqs[seqNb].matchLength; - U32 offBase; - - if (!repcodeResolution) { - offBase = OFFSET_TO_OFFBASE(inSeqs[seqNb].offset); - } else { - U32 const ll0 = (litLength == 0); - offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0); - ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); - } + U32 const ll0 = (litLength == 0); + U32 const offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0); DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength); + ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); } } From 2f3ee8b5309958a2bc1fc7477e703fd8195a31ea Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 14 Jan 2025 14:56:10 -0800 Subject: [PATCH 310/405] changed code compilation test to employ ZSTD_ARCH_X86_AVX2 --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 55622cbd5..8e5f369bb 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7384,7 +7384,7 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, return 0; } -#if defined(__AVX2__) +#if defined(ZSTD_ARCH_X86_AVX2) /* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ #if defined(__GNUC__) From 8bff69af869fca1cc44172c2ae5d5f995322509b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 14 Jan 2025 15:54:10 -0800 Subject: [PATCH 311/405] Alignment instruction ZSTD_ALIGNED() in common/compiler.h --- lib/common/compiler.h | 15 ++++++++++++++- lib/compress/zstd_compress.c | 12 +----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index f636b7f25..2a8002288 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -281,7 +281,7 @@ #endif /*-************************************************************** -* Alignment check +* Alignment *****************************************************************/ /* @return 1 if @u is a 2^n value, 0 otherwise @@ -315,6 +315,19 @@ MEM_STATIC int ZSTD_isPower2(size_t u) { # endif #endif /* ZSTD_ALIGNOF */ +#ifndef ZSTD_ALIGNED +/* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ +# if defined(__GNUC__) +# define ZSTD_ALIGNED(a) __attribute__((aligned(a))) +# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ +# define ZSTD_ALIGNED(a) alignas(a) +# else + /* this compiler will require its own alignment instruction */ +# define ZSTD_ALIGNED(...) +# endif +#endif /* ZSTD_ALIGNED */ + + /*-************************************************************** * Sanitizer *****************************************************************/ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 8e5f369bb..eba2d07dc 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7386,22 +7386,12 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, #if defined(ZSTD_ARCH_X86_AVX2) -/* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ -#if defined(__GNUC__) -# define ALIGNED32 __attribute__((aligned(32))) -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ -# define ALIGNED32 alignas(32) -#else - /* this compiler will require its own alignment instruction */ -# define ALIGNED32 -#endif - BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) { size_t i; __m256i const zeroVec = _mm256_setzero_si256(); __m256i sumVec = zeroVec; /* accumulates match+lit in 32-bit lanes */ - ALIGNED32 U32 tmp[8]; /* temporary buffer for reduction */ + ZSTD_ALIGNED(32) U32 tmp[8]; /* temporary buffer for reduction */ size_t mSum = 0, lSum = 0; ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16); From 87f0a4fbe0a1ffcaab4618f2aa76545e225acf07 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 14 Jan 2025 15:57:05 -0800 Subject: [PATCH 312/405] restore full equation do not solve the equation, even though some members cancel each other, this is done for clarity, we'll let the compiler do the resolution at compile time. --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index eba2d07dc..e26e78a8f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7342,7 +7342,7 @@ size_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx, DEBUGLOG(5, "long literals length detected at pos %zu", longl-nbSequences); assert(longl <= 2* (nbSequences-1)); cctx->seqStore.longLengthType = ZSTD_llt_literalLength; - cctx->seqStore.longLengthPos = (U32)(longl-nbSequences); + cctx->seqStore.longLengthPos = (U32)(longl-(nbSequences-1)-1); } } } else { From 78275149ead3bfc068d58a67480653740da5a86b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 17 Jan 2025 19:30:55 -0800 Subject: [PATCH 313/405] Added a final success message at end of tests so that a human reading the test log can determine everything was fine without consulting the shell error code. Also: made `make check` slightly shorter by moving one longer test to `make test` --- .github/workflows/dev-short-tests.yml | 6 +++--- CONTRIBUTING.md | 2 +- Makefile | 8 ++------ tests/Makefile | 13 ++++++++----- tests/playTests.sh | 3 ++- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 25919922d..18c66f4f6 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -144,11 +144,11 @@ jobs: - name: install valgrind run: | sudo apt-get -qqq update - make valgrindinstall + make valgrindinstall V=1 - name: zlib wrapper test - run: make -C zlibWrapper test + run: make -C zlibWrapper test V=1 - name: zlib wrapper test under valgrind - run: make -C zlibWrapper test-valgrind + run: make -C zlibWrapper test-valgrind V=1 lz4-threadpool-libs: runs-on: ubuntu-latest diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 47f5bb8f0..57be94bf5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ Our contribution process works in three main stages: * Note: run local tests to ensure that your changes didn't break existing functionality * Quick check ``` - make shortest + make check ``` * Longer check ``` diff --git a/Makefile b/Makefile index e80505b7f..03ee6fe89 100644 --- a/Makefile +++ b/Makefile @@ -85,14 +85,10 @@ test: $(MAKE) -C $(TESTDIR) $@ ZSTD=../../programs/zstd $(MAKE) -C doc/educational_decoder $@ -## shortest: same as `make check` -.PHONY: shortest -shortest: - $(Q)$(MAKE) -C $(TESTDIR) $@ - ## check: run basic tests for `zstd` cli .PHONY: check -check: shortest +check: + $(Q)$(MAKE) -C $(TESTDIR) $@ .PHONY: automated_benchmarking automated_benchmarking: diff --git a/tests/Makefile b/tests/Makefile index abb0b2b1d..406c7f20b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -312,12 +312,12 @@ endif list: @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs -.PHONY: shortest -shortest: ZSTDRTTEST= # remove long tests -shortest: test-zstd - .PHONY: check -check: shortest +check: ZSTDRTTEST= # remove long tests +check: test-zstd + @echo "\n******************************" + @echo "All tests completed successfully" + @echo "******************************" .PHONY: fuzztest fuzztest: test-fuzzer test-zstream test-decodecorpus @@ -327,6 +327,9 @@ test: test-zstd test-cli-tests test-fullbench test-fuzzer test-zstream test-inva ifeq ($(QEMU_SYS),) test: test-pool endif + @echo "\n******************************" + @echo "All tests completed successfully" + @echo "******************************" .PHONY: test32 test32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32 diff --git a/tests/playTests.sh b/tests/playTests.sh index 692e93e89..5435ff5b3 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1554,7 +1554,6 @@ then roundTripTest -g4M "1 -T0 --auto-threads=physical" roundTripTest -g4M "1 -T0 --auto-threads=logical" roundTripTest -g8M "3 -T2" - roundTripTest -g8M "19 --long" roundTripTest -g8000K "2 --threads=2" fileRoundTripTest -g4M "19 -T2 -B1M" @@ -1850,6 +1849,8 @@ roundTripTest -g18000017 -P88 17 roundTripTest -g18000018 -P94 18 roundTripTest -g18000019 -P96 19 +roundTripTest -g8M "19 --long" + roundTripTest -g5000000000 -P99 "1 --zstd=wlog=25" roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=25" # ensure btlazy2 can survive an overflow rescale From 46e17b805b1bb2982583208da3b9184e377c2dd5 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sat, 18 Jan 2025 05:01:43 +0200 Subject: [PATCH 314/405] [asm] Enable x86_64 asm for windows builds --- lib/common/portability_macros.h | 8 +++----- lib/decompress/huf_decompress_amd64.S | 13 ++++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index b1d9765fb..1ca28af6a 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -93,7 +93,7 @@ * Only enable assembly for GNU C compatible compilers, * because other platforms may not support GAS assembly syntax. * - * Only enable assembly for Linux / MacOS, other platforms may + * Only enable assembly for Linux / MacOS / Win32, other platforms may * work, but they haven't been tested. This could likely be * extended to BSD systems. * @@ -101,10 +101,8 @@ * 100% of code to be instrumented to work. */ #if defined(__GNUC__) -# if defined(__linux__) || defined(__linux) || defined(__APPLE__) -# if ZSTD_MEMORY_SANITIZER -# define ZSTD_ASM_SUPPORTED 0 -# elif ZSTD_DATAFLOW_SANITIZER +# if defined(__linux__) || defined(__linux) || defined(__APPLE__) || defined(_WIN32) +# if ZSTD_MEMORY_SANITIZER || ZSTD_DATAFLOW_SANITIZER # define ZSTD_ASM_SUPPORTED 0 # else # define ZSTD_ASM_SUPPORTED 1 diff --git a/lib/decompress/huf_decompress_amd64.S b/lib/decompress/huf_decompress_amd64.S index 78da291ee..656aada95 100644 --- a/lib/decompress/huf_decompress_amd64.S +++ b/lib/decompress/huf_decompress_amd64.S @@ -42,13 +42,11 @@ /* Calling convention: * - * %rdi contains the first argument: HUF_DecompressAsmArgs*. + * %rdi (or %rcx on Windows) contains the first argument: HUF_DecompressAsmArgs*. * %rbp isn't maintained (no frame pointer). * %rsp contains the stack pointer that grows down. * No red-zone is assumed, only addresses >= %rsp are used. * All register contents are preserved. - * - * TODO: Support Windows calling convention. */ ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_fast_asm_loop) @@ -137,7 +135,11 @@ HUF_decompress4X1_usingDTable_internal_fast_asm_loop: push %r15 /* Read HUF_DecompressAsmArgs* args from %rax */ +#if defined(_WIN32) + movq %rcx, %rax +#else movq %rdi, %rax +#endif movq 0(%rax), %ip0 movq 8(%rax), %ip1 movq 16(%rax), %ip2 @@ -391,7 +393,12 @@ HUF_decompress4X2_usingDTable_internal_fast_asm_loop: push %r14 push %r15 + /* Read HUF_DecompressAsmArgs* args from %rax */ +#if defined(_WIN32) + movq %rcx, %rax +#else movq %rdi, %rax +#endif movq 0(%rax), %ip0 movq 8(%rax), %ip1 movq 16(%rax), %ip2 From ee17f4c6d295e82733673f824e7dba81a33e245b Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sat, 18 Jan 2025 21:32:30 +0200 Subject: [PATCH 315/405] Use _bzhi_u32 for 32-bit builds when building with STATIC_BMI2 `_bzhi_u64` is available only for 64-bit builds, while `BIT_getLowerBits` expects `nbBits` to be less than `BIT_MASK_SIZE` (`BIT_MASK_SIZE` is 32) --- lib/common/bitstream.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index a1dac889d..c9c645416 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -162,7 +162,11 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) - return _bzhi_u64(bitContainer, nbBits); +#if defined(__x86_64__) || defined(_M_X64) + return _bzhi_u64(bitContainer, nbBits); +#else + return _bzhi_u32(bitContainer, nbBits); +#endif #else assert(nbBits < BIT_MASK_SIZE); return bitContainer & BIT_mask[nbBits]; From 4f3311f245fedb99d65baca98cd33f6ec41a6589 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 12:22:52 -0800 Subject: [PATCH 316/405] CI: replaced shortest target by check --- .cirrus.yml | 4 ++-- .github/workflows/commit.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index e3617a960..9461de412 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,9 +1,9 @@ task: - name: FreeBSD (shortest) + name: FreeBSD (make check) freebsd_instance: matrix: image_family: freebsd-14-1 install_script: pkg install -y gmake coreutils script: | MOREFLAGS="-Werror" gmake -j all - gmake shortest + gmake check diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 2aa8a6d86..659072861 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -30,7 +30,7 @@ jobs: make c99build; make clean make c11build; make clean make -j regressiontest; make clean - make shortest; make clean + make check; make clean make cxxtest; make clean short-tests-1: From e8de8085f4a75fe46021b82851b72b07bb824c2b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 13:08:04 -0800 Subject: [PATCH 317/405] minor: assert that state is not null replaces #4016 --- lib/decompress/zstd_decompress.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 402d75349..9eb98327e 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -2096,6 +2096,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB U32 someMoreWork = 1; DEBUGLOG(5, "ZSTD_decompressStream"); + assert(zds != NULL); RETURN_ERROR_IF( input->pos > input->size, srcSize_wrong, From 936927a427704ca21dfd07c666c4123737c8fb03 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sat, 18 Jan 2025 23:27:19 +0200 Subject: [PATCH 318/405] handle 32bit size_t when building for x64 --- lib/common/bitstream.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index c9c645416..c0db11d40 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -162,11 +162,11 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) -#if defined(__x86_64__) || defined(_M_X64) - return _bzhi_u64(bitContainer, nbBits); -#else +# if defined(__x86_64__) || defined(_M_X64) + return sizeof(size_t) == sizeof(U64) ? _bzhi_u64(bitContainer, nbBits) : _bzhi_u32((U32)bitContainer, nbBits); +# else return _bzhi_u32(bitContainer, nbBits); -#endif +# endif #else assert(nbBits < BIT_MASK_SIZE); return bitContainer & BIT_mask[nbBits]; From 26e5fb36149b9d155a3640ca0800199fc13711e8 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sat, 18 Jan 2025 23:37:50 +0200 Subject: [PATCH 319/405] handle 32bit size_t when building for x64 --- lib/common/bitstream.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index c0db11d40..d976c5478 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -162,9 +162,10 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) -# if defined(__x86_64__) || defined(_M_X64) - return sizeof(size_t) == sizeof(U64) ? _bzhi_u64(bitContainer, nbBits) : _bzhi_u32((U32)bitContainer, nbBits); +# if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__) + return _bzhi_u64(bitContainer, nbBits); # else + DEBUG_STATIC_ASSERT(sizeof(size_t) == sizeof(U32)); return _bzhi_u32(bitContainer, nbBits); # endif #else From 462484d5dcbab964474bf4704df4d188e5c31818 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sun, 19 Jan 2025 02:34:23 +0200 Subject: [PATCH 320/405] change to BitContainerType --- lib/common/bitstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index d976c5478..582f9dd72 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -159,7 +159,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, return 0; } -FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) +FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(BitContainerType bitContainer, U32 const nbBits) { #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) # if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__) From d60c4d75e9d29d76cc202f7a8341ab0bda1d6402 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sun, 19 Jan 2025 02:36:00 +0200 Subject: [PATCH 321/405] remove unrelated changes --- lib/common/portability_macros.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index 1ca28af6a..6016aefa5 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -102,7 +102,9 @@ */ #if defined(__GNUC__) # if defined(__linux__) || defined(__linux) || defined(__APPLE__) || defined(_WIN32) -# if ZSTD_MEMORY_SANITIZER || ZSTD_DATAFLOW_SANITIZER +# if ZSTD_MEMORY_SANITIZER +# define ZSTD_ASM_SUPPORTED 0 +# elif ZSTD_DATAFLOW_SANITIZER # define ZSTD_ASM_SUPPORTED 0 # else # define ZSTD_ASM_SUPPORTED 1 From fcd684b9b45917dbb90e8122faf782e4028fdb42 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sun, 19 Jan 2025 02:37:35 +0200 Subject: [PATCH 322/405] update sizeof check --- lib/common/bitstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index 582f9dd72..bc7118b37 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -165,7 +165,7 @@ FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(BitContainerType bitContainer, U32 # if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__) return _bzhi_u64(bitContainer, nbBits); # else - DEBUG_STATIC_ASSERT(sizeof(size_t) == sizeof(U32)); + DEBUG_STATIC_ASSERT(sizeof(bitContainer) == sizeof(U32)); return _bzhi_u32(bitContainer, nbBits); # endif #else From 9efb09749b85acfbc2299fb6dec6146b942c6b2e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 20:19:55 -0800 Subject: [PATCH 323/405] added a CI test for x86 32-bit + avx2 combination which is expected to be quite rare, but nonetheless possible. This test is initially expected to fail, before integration of #4248 fix --- .github/workflows/dev-short-tests.yml | 13 ++++++++++++- lib/common/bitstream.h | 2 +- lib/common/compiler.h | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 18c66f4f6..fa28283f7 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -164,7 +164,7 @@ jobs: make clean bash tests/libzstd_builds.sh - gcc-make-tests-32bit: + gcc-make-all-32bit: runs-on: ubuntu-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 @@ -174,6 +174,17 @@ jobs: make libc6install CFLAGS="-Werror -m32" make -j all32 + gcc-make-all-32bit-avx2: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + - name: Make all, 32bit mode + run: | + sudo apt-get -qqq update + make libc6install + CFLAGS="-Werror -m32 -mavx2" make -j all32 + + gcc-8-make: runs-on: ubuntu-latest steps: diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index bc7118b37..88f448aa6 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -238,7 +238,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) BIT_addBitsFast(bitC, 1, 1); /* endMark */ BIT_flushBits(bitC); if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */ - return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0); + return (size_t)(bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0); } diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 2a8002288..84ce62349 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -210,7 +210,7 @@ /*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ #ifndef STATIC_BMI2 # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) -# ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 +# ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ # define STATIC_BMI2 1 # endif # elif defined(__BMI2__) && defined(__x86_64__) && defined(__GNUC__) From 35edbc20dc31fcc64f7dfe0c256d5005879b1b59 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 20:38:48 -0800 Subject: [PATCH 324/405] added avx2 (x64) compilation test --- .github/workflows/dev-short-tests.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index fa28283f7..6bd311f09 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -164,6 +164,16 @@ jobs: make clean bash tests/libzstd_builds.sh + gcc-make-all-avx2: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + - name: Make all, with AVX2 + run: | + sudo apt-get -qqq update + make libc6install + CFLAGS="-Werror -mavx2" make -j all + gcc-make-all-32bit: runs-on: ubuntu-latest steps: @@ -178,7 +188,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: Make all, 32bit mode + - name: Make all, 32bit + AVX2 mode run: | sudo apt-get -qqq update make libc6install From f0b5f65bca6587f6d9b642e3a95d58ae36b7cdea Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 20:43:30 -0800 Subject: [PATCH 325/405] fixed minor static function declaration issue in AVX2 mode only --- lib/compress/zstd_compress.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 5d5ada0ae..abc75fb2d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7125,7 +7125,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, * @returns > 0 if there is one long length (> 65535), * indicating the position, and type. */ -size_t convertSequences_noRepcodes( +static size_t convertSequences_noRepcodes( SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs, size_t nbSequences) @@ -7277,9 +7277,10 @@ size_t convertSequences_noRepcodes( #else /* no AVX2 */ -static size_t -convertSequences_noRepcodes(SeqDef* dstSeqs, - const ZSTD_Sequence* const inSeqs, size_t nbSequences) +static size_t convertSequences_noRepcodes( + SeqDef* dstSeqs, + const ZSTD_Sequence* inSeqs, + size_t nbSequences) { size_t longLen = 0; size_t n; From 050109589800be49d3840927b9e821d24622e1ea Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 22:40:18 -0800 Subject: [PATCH 326/405] added -DSTATIC_BMI2=1 for the -mavx2 test --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 6bd311f09..71afc0991 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -192,7 +192,7 @@ jobs: run: | sudo apt-get -qqq update make libc6install - CFLAGS="-Werror -m32 -mavx2" make -j all32 + CPPFLAGS="-DSTATIC_BMI2=1" CFLAGS="-Werror -m32 -mavx2" make -j all32 gcc-8-make: From 27d794063162096e3a4be7d2d3f80ce117a5592d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 22:48:49 -0800 Subject: [PATCH 327/405] minor: cosmetic, indentation --- lib/common/compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 84ce62349..7927c4fb6 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -207,7 +207,7 @@ # pragma warning(disable : 4324) /* disable: C4324: padded structure */ #endif -/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ +/* Like DYNAMIC_BMI2 but for compile time determination of BMI2 support */ #ifndef STATIC_BMI2 # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) # ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ @@ -219,7 +219,7 @@ #endif #ifndef STATIC_BMI2 - #define STATIC_BMI2 0 +# define STATIC_BMI2 0 #endif /* compile time determination of SIMD support */ From d2d74616c0bfaf9d76186398a23fffafbb591c52 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 18 Jan 2025 22:58:03 -0800 Subject: [PATCH 328/405] also add `-mbmi2` to the compilation test --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 71afc0991..a84510686 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -192,7 +192,7 @@ jobs: run: | sudo apt-get -qqq update make libc6install - CPPFLAGS="-DSTATIC_BMI2=1" CFLAGS="-Werror -m32 -mavx2" make -j all32 + CPPFLAGS="-DSTATIC_BMI2=1" CFLAGS="-Werror -m32 -mavx2 -mbmi2" make -j all32 gcc-8-make: From a556559841db607ede4e4e0a85773e5b214e66f1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 19 Jan 2025 00:08:57 -0800 Subject: [PATCH 329/405] no longer limit automated BMI2 detection to x64 this was previously no triggered in x86 32-bit mode, due to a limitation in `bitstream.h`, that was fixed in #4248. Now, `bmi2` will be automatically detected and triggered at compilation time, if the corresponding instruction set is enabled, even in 32-bit mode. Also: updated library documentation, to feature STATIC_BMI2 build variable --- lib/README.md | 7 +++++++ lib/common/compiler.h | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/README.md b/lib/README.md index 0f6c64745..b37f5fc4f 100644 --- a/lib/README.md +++ b/lib/README.md @@ -149,6 +149,13 @@ The file structure is designed to make this selection manually achievable for an will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in the shared library, which is now hidden by default. +- The build macro `STATIC_BMI2` can be set to 1 to force usage of `bmi2` instructions. + It is generally not necessary to set this build macro, + because `STATIC_BMI2` will be automatically set to 1 + on detecting the presence of the corresponding instruction set in the compilation target. + It's nonetheless available as an optional manual toggle for better control, + and can also be used to forcefully disable `bmi2` instructions by setting it to 0. + - The build macro `DYNAMIC_BMI2` can be set to 1 or 0 in order to generate binaries which can detect at runtime the presence of BMI2 instructions, and use them only if present. These instructions contribute to better performance, notably on the decoder side. diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 7927c4fb6..6fd2d08e7 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -209,11 +209,11 @@ /* Like DYNAMIC_BMI2 but for compile time determination of BMI2 support */ #ifndef STATIC_BMI2 -# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) +# if defined(_MSC_VER) # ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ # define STATIC_BMI2 1 # endif -# elif defined(__BMI2__) && defined(__x86_64__) && defined(__GNUC__) +# elif defined(__BMI2__) # define STATIC_BMI2 1 # endif #endif From 4bbf4a285d92e4cb5b37e0fd1d4af96c12c2c249 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 19 Jan 2025 07:39:17 -0800 Subject: [PATCH 330/405] enable DYNAMIC_BMI2 by default on x86 (32-bit mode) so far was only enabled for x64 (64-bit mode) --- lib/common/portability_macros.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index 6016aefa5..b52394382 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -78,15 +78,15 @@ * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. */ #ifndef DYNAMIC_BMI2 - #if ((defined(__clang__) && __has_attribute(__target__)) \ +# if ((defined(__clang__) && __has_attribute(__target__)) \ || (defined(__GNUC__) \ && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ - && (defined(__x86_64__) || defined(_M_X64)) \ + && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)) \ && !defined(__BMI2__) - # define DYNAMIC_BMI2 1 - #else - # define DYNAMIC_BMI2 0 - #endif +# define DYNAMIC_BMI2 1 +# else +# define DYNAMIC_BMI2 0 +# endif #endif /** From 82346b92bb5f02dea90907135f74cd77f0c9cb33 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 19 Jan 2025 09:32:01 -0800 Subject: [PATCH 331/405] minor: generalize BitContainerType technically equivalent to `size_t`, but it's the proper type for underlying register representation. This makes it possible to control register type, and therefore size, independently from `size_t`, which can be useful on systems where `size_t` is 32-bit, while the architecture supports 64-bit registers. --- lib/common/bitstream.h | 34 +++++++++++++++++----------------- lib/common/fse.h | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index 88f448aa6..2c4245678 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -48,12 +48,13 @@ /*-****************************************** * bitStream encoding API (write forward) ********************************************/ +typedef size_t BitContainerType; /* bitStream can mix input from multiple sources. * A critical property of these streams is that they encode and decode in **reverse** direction. * So the first bit sequence you add will be the last to be read, like a LIFO stack. */ typedef struct { - size_t bitContainer; + BitContainerType bitContainer; unsigned bitPos; char* startPtr; char* ptr; @@ -61,7 +62,7 @@ typedef struct { } BIT_CStream_t; MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity); -MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits); +MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, BitContainerType value, unsigned nbBits); MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC); MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); @@ -70,7 +71,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); * `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code. * * bits are first added to a local register. -* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems. +* Local register is BitContainerType, 64-bits on 64-bits systems, or 32-bits on 32-bits systems. * Writing data into memory is an explicit operation, performed by the flushBits function. * Hence keep track how many bits are potentially stored into local register to avoid register overflow. * After a flushBits, a maximum of 7 bits might still be stored into local register. @@ -86,7 +87,6 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); /*-******************************************** * bitStream decoding API (read backward) **********************************************/ -typedef size_t BitContainerType; typedef struct { BitContainerType bitContainer; unsigned bitsConsumed; @@ -102,7 +102,7 @@ typedef enum { BIT_DStream_unfinished = 0, /* fully refilled */ } BIT_DStream_status; /* result of BIT_reloadDStream() */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); -MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); +MEM_STATIC BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD); MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); @@ -121,7 +121,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); /*-**************************************** * unsafe API ******************************************/ -MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits); +MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, BitContainerType value, unsigned nbBits); /* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */ MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC); @@ -159,7 +159,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, return 0; } -FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(BitContainerType bitContainer, U32 const nbBits) +FORCE_INLINE_TEMPLATE BitContainerType BIT_getLowerBits(BitContainerType bitContainer, U32 const nbBits) { #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) # if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__) @@ -178,7 +178,7 @@ FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(BitContainerType bitContainer, U32 * can add up to 31 bits into `bitC`. * Note : does not check for register overflow ! */ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, - size_t value, unsigned nbBits) + BitContainerType value, unsigned nbBits) { DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32); assert(nbBits < BIT_MASK_SIZE); @@ -191,7 +191,7 @@ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, * works only if `value` is _clean_, * meaning all high bits above nbBits are 0 */ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, - size_t value, unsigned nbBits) + BitContainerType value, unsigned nbBits) { assert((value>>nbBits) == 0); assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); @@ -299,12 +299,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si return srcSize; } -FORCE_INLINE_TEMPLATE size_t BIT_getUpperBits(BitContainerType bitContainer, U32 const start) +FORCE_INLINE_TEMPLATE BitContainerType BIT_getUpperBits(BitContainerType bitContainer, U32 const start) { return bitContainer >> start; } -FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits) +FORCE_INLINE_TEMPLATE BitContainerType BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits) { U32 const regMask = sizeof(bitContainer)*8 - 1; /* if start > regMask, bitstream is corrupted, and result is undefined */ @@ -327,7 +327,7 @@ FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits(BitContainerType bitContainer, U3 * On 32-bits, maxNbBits==24. * On 64-bits, maxNbBits==56. * @return : value extracted */ -FORCE_INLINE_TEMPLATE size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) +FORCE_INLINE_TEMPLATE BitContainerType BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) { /* arbitrate between double-shift and shift+mask */ #if 1 @@ -343,7 +343,7 @@ FORCE_INLINE_TEMPLATE size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits /*! BIT_lookBitsFast() : * unsafe version; only works if nbBits >= 1 */ -MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC BitContainerType BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) { U32 const regMask = sizeof(bitD->bitContainer)*8 - 1; assert(nbBits >= 1); @@ -359,18 +359,18 @@ FORCE_INLINE_TEMPLATE void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) * Read (consume) next n bits from local register and update. * Pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ -FORCE_INLINE_TEMPLATE size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) +FORCE_INLINE_TEMPLATE BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) { - size_t const value = BIT_lookBits(bitD, nbBits); + BitContainerType const value = BIT_lookBits(bitD, nbBits); BIT_skipBits(bitD, nbBits); return value; } /*! BIT_readBitsFast() : * unsafe version; only works if nbBits >= 1 */ -MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) +MEM_STATIC BitContainerType BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) { - size_t const value = BIT_lookBitsFast(bitD, nbBits); + BitContainerType const value = BIT_lookBitsFast(bitD, nbBits); assert(nbBits >= 1); BIT_skipBits(bitD, nbBits); return value; diff --git a/lib/common/fse.h b/lib/common/fse.h index b1940d942..b6c2a3e9c 100644 --- a/lib/common/fse.h +++ b/lib/common/fse.h @@ -456,13 +456,13 @@ MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, un FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; const U16* const stateTable = (const U16*)(statePtr->stateTable); U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); - BIT_addBits(bitC, (size_t)statePtr->value, nbBitsOut); + BIT_addBits(bitC, (BitContainerType)statePtr->value, nbBitsOut); statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; } MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) { - BIT_addBits(bitC, (size_t)statePtr->value, statePtr->stateLog); + BIT_addBits(bitC, (BitContainerType)statePtr->value, statePtr->stateLog); BIT_flushBits(bitC); } From e39ed414350313e8170d96c8fc82b3d0c2e67a6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 05:46:57 +0000 Subject: [PATCH 332/405] Bump cygwin/cygwin-install-action from 4 to 5 Bumps [cygwin/cygwin-install-action](https://github.com/cygwin/cygwin-install-action) from 4 to 5. - [Release notes](https://github.com/cygwin/cygwin-install-action/releases) - [Commits](https://github.com/cygwin/cygwin-install-action/compare/006ad0b0946ca6d0a3ea2d4437677fa767392401...f61179d72284ceddc397ed07ddb444d82bf9e559) --- updated-dependencies: - dependency-name: cygwin/cygwin-install-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index a84510686..2fccb4d9e 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -582,7 +582,7 @@ jobs: steps: - run: git config --global core.autocrlf input - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: cygwin/cygwin-install-action@006ad0b0946ca6d0a3ea2d4437677fa767392401 # tag=master + - uses: cygwin/cygwin-install-action@f61179d72284ceddc397ed07ddb444d82bf9e559 # tag=master with: platform: x86_64 packages: >- From 5b9c5d4929cea7b3a134f44887bfffeefd448500 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 05:47:03 +0000 Subject: [PATCH 333/405] Bump github/codeql-action from 3.27.1 to 3.28.1 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.1 to 3.28.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4f3212b61783c3c68e8309a0f18a699764811cda...b6a472f63d85b9c78a3ac5e89422239fc15e9b3c) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 0ae40d859..c489ddc91 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4f3212b61783c3c68e8309a0f18a699764811cda # tag=v3.27.1 + uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # tag=v3.28.1 with: sarif_file: results.sarif From 056492e31b80fa746c187a5078e96163437c8739 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 19 Jan 2025 23:14:59 -0800 Subject: [PATCH 334/405] Update dev-short-tests.yml specify cygwin action version --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 2fccb4d9e..dfe1bf584 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -582,7 +582,7 @@ jobs: steps: - run: git config --global core.autocrlf input - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - uses: cygwin/cygwin-install-action@f61179d72284ceddc397ed07ddb444d82bf9e559 # tag=master + - uses: cygwin/cygwin-install-action@f61179d72284ceddc397ed07ddb444d82bf9e559 # tag=v5 with: platform: x86_64 packages: >- From 6c1d1cc600f0cc5dab40e16200f4d23eeaeb0c9f Mon Sep 17 00:00:00 2001 From: Pavel P Date: Tue, 21 Jan 2025 02:27:09 +0200 Subject: [PATCH 335/405] Use _M_X64 only without mixing with _M_AMD64 --- lib/common/compiler.h | 2 +- lib/common/mem.h | 2 +- lib/common/xxhash.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 6fd2d08e7..0dad74c7d 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -227,7 +227,7 @@ # if defined(__AVX2__) # define ZSTD_ARCH_X86_AVX2 # endif -# if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) +# if defined(__SSE2__) || defined(_M_X64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) # define ZSTD_ARCH_X86_SSE2 # endif # if defined(__ARM_NEON) || defined(_M_ARM64) diff --git a/lib/common/mem.h b/lib/common/mem.h index ca756e237..e66a2eaeb 100644 --- a/lib/common/mem.h +++ b/lib/common/mem.h @@ -147,7 +147,7 @@ MEM_STATIC unsigned MEM_isLittleEndian(void) return 1; #elif defined(__clang__) && __BIG_ENDIAN__ return 0; -#elif defined(_MSC_VER) && (_M_AMD64 || _M_IX86) +#elif defined(_MSC_VER) && (_M_X64 || _M_IX86) return 1; #elif defined(__DMC__) && defined(_M_IX86) return 1; diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h index 68ec6b29f..b6af402fd 100644 --- a/lib/common/xxhash.h +++ b/lib/common/xxhash.h @@ -3892,7 +3892,7 @@ enum XXH_VECTOR_TYPE /* fake enum */ { # define XXH_VECTOR XXH_AVX512 # elif defined(__AVX2__) # define XXH_VECTOR XXH_AVX2 -# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) +# elif defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) # define XXH_VECTOR XXH_SSE2 # elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ || (defined(__s390x__) && defined(__VEC__)) \ From a0872a837294ae9b18967e9e80342587f3089fb0 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Tue, 21 Jan 2025 02:33:25 +0200 Subject: [PATCH 336/405] Implement ZSTD_ALIGNED for ms compiler --- lib/common/compiler.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 6fd2d08e7..b12de3edc 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -321,6 +321,8 @@ MEM_STATIC int ZSTD_isPower2(size_t u) { # define ZSTD_ALIGNED(a) __attribute__((aligned(a))) # elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ # define ZSTD_ALIGNED(a) alignas(a) +#elif defined(_MSC_VER) +# define ZSTD_ALIGNED(n) __declspec(align(n)) # else /* this compiler will require its own alignment instruction */ # define ZSTD_ALIGNED(...) From 897cec38760d1bb41e690225ba07b91c568e7cc8 Mon Sep 17 00:00:00 2001 From: Treata11 Date: Tue, 21 Jan 2025 20:58:27 +0330 Subject: [PATCH 337/405] Build: Add support for Apple frameworks Signed-off-by: Treata11 --- build/cmake/CMakeLists.txt | 11 +++++++-- build/cmake/lib/CMakeLists.txt | 45 +++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index b9003c867..f507181dc 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -7,7 +7,7 @@ # in the COPYING file in the root directory of this source tree). # ################################################################ -cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +cmake_minimum_required(VERSION 3.14 FATAL_ERROR) # As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies. # Set and use the newest cmake policies that are validated to work @@ -30,8 +30,11 @@ set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib) include(GetZstdLibraryVersion) GetZstdLibraryVersion(${LIBRARY_DIR}/zstd.h zstd_VERSION_MAJOR zstd_VERSION_MINOR zstd_VERSION_PATCH) +set(ZSTD_SHORT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}") +set(ZSTD_FULL_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}") + project(zstd - VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}" + VERSION "${ZSTD_FULL_VERSION}" LANGUAGES C # Main library is in C ASM # And ASM CXX # Testing contributed code also utilizes CXX @@ -82,6 +85,10 @@ else () add_definitions(-DZSTD_LEGACY_SUPPORT=0) endif () +if (APPLE) + option(ZSTD_FRAMEWORK "Build as Apple Frameworks" OFF) +endif () + if (ANDROID) set(ZSTD_MULTITHREAD_SUPPORT_DEFAULT OFF) # Old versions of bionic libc don't have fseeko/ftello diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index d07b1f5ff..c02822296 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -205,8 +205,28 @@ if (ZSTD_BUILD_SHARED) libzstd_shared PROPERTIES OUTPUT_NAME zstd - VERSION ${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH} + VERSION ${ZSTD_FULL_VERSION} SOVERSION ${zstd_VERSION_MAJOR}) + + if (ZSTD_FRAMEWORK) + set_target_properties( + libzstd_shared + PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION "${ZSTD_FULL_VERSION}" + PRODUCT_BUNDLE_IDENTIFIER "github.com/facebook/zstd" + XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" + PUBLIC_HEADER "${PublicHeaders}" + OUTPUT_NAME "zstd" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" + MACOSX_FRAMEWORK_IDENTIFIER "github.com/facebook/zstd" + MACOSX_FRAMEWORK_BUNDLE_VERSION "${ZSTD_FULL_VERSION}" + MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${ZSTD_SHORT_VERSION}" + MACOSX_RPATH TRUE + RESOURCE ${PublicHeaders}) + endif () endif () if (ZSTD_BUILD_STATIC) @@ -215,6 +235,26 @@ if (ZSTD_BUILD_STATIC) PROPERTIES POSITION_INDEPENDENT_CODE On OUTPUT_NAME ${STATIC_LIBRARY_BASE_NAME}) + + if (ZSTD_FRAMEWORK) + set_target_properties( + libzstd_static + PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION "${ZSTD_FULL_VERSION}" + PRODUCT_BUNDLE_IDENTIFIER "github.com/facebook/zstd/${STATIC_LIBRARY_BASE_NAME}" + XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" + PUBLIC_HEADER "${PublicHeaders}" + OUTPUT_NAME "${STATIC_LIBRARY_BASE_NAME}" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" + MACOSX_FRAMEWORK_IDENTIFIER "github.com/facebook/zstd/${STATIC_LIBRARY_BASE_NAME}" + MACOSX_FRAMEWORK_BUNDLE_VERSION "${ZSTD_FULL_VERSION}" + MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${ZSTD_SHORT_VERSION}" + MACOSX_RPATH TRUE + RESOURCE ${PublicHeaders}) + endif () endif () # pkg-config @@ -239,6 +279,9 @@ install(TARGETS ${library_targets} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" + FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT runtime OPTIONAL + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) # uninstall target From 03d5ad6fed5882a300289e5fa8a238f2fec29300 Mon Sep 17 00:00:00 2001 From: Treata11 Date: Tue, 21 Jan 2025 21:06:54 +0330 Subject: [PATCH 338/405] Ignore generated framework artifacts Signed-off-by: Treata11 --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 34e18b443..4b50bb186 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ *.so *.so.* *.dylib +*.framework +*.xcframework # Executables /zstd From becef672bb7c22af0fd723a4f8e4d279cf2a780a Mon Sep 17 00:00:00 2001 From: Treata11 Date: Wed, 22 Jan 2025 22:53:41 +0330 Subject: [PATCH 339/405] Build: Revert min version to 3.10 --- build/cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index f507181dc..347d41c0f 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -7,7 +7,7 @@ # in the COPYING file in the root directory of this source tree). # ################################################################ -cmake_minimum_required(VERSION 3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) # As of 2018-12-26 ZSTD has been validated to build with cmake version 3.13.2 new policies. # Set and use the newest cmake policies that are validated to work From 45c0e72c0a481be824cc12fe6032ac685205d187 Mon Sep 17 00:00:00 2001 From: Treata11 Date: Wed, 22 Jan 2025 22:54:03 +0330 Subject: [PATCH 340/405] Instructions for Apple Framework builds --- build/cmake/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build/cmake/README.md b/build/cmake/README.md index 4c9d3a08b..6baa5974b 100644 --- a/build/cmake/README.md +++ b/build/cmake/README.md @@ -41,6 +41,16 @@ cmake -DZSTD_BUILD_TESTS=ON -DZSTD_LEGACY_SUPPORT=OFF .. make ``` +**Apple Frameworks** +It's generally recommended to have CMake with versions higher than 3.14 for [iOS-derived platforms](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#id27). +```sh +cmake -S. -B build-cmake -DZSTD_FRAMEWORK=ON -DCMAKE_SYSTEM_NAME=iOS +``` +Or you can utilize [iOS-CMake](https://github.com/leetal/ios-cmake) toolchain for CMake versions lower than 3.14 +```sh +cmake -B build -G Xcode -DCMAKE_TOOLCHAIN_FILE= -DPLATFORM=OS64 -DZSTD_FRAMEWORK=ON +``` + ### how to use it with CMake FetchContent For all options available, you can see it on From 12046261382422494d7423cd39df553f236270ee Mon Sep 17 00:00:00 2001 From: Pavel P Date: Thu, 23 Jan 2025 23:58:50 +0200 Subject: [PATCH 341/405] Check `DYNAMIC_BMI2` instead of `DYNAMIC_BMI2 != 0` `#if DYNAMIC_BMI2` is consistent with the rest of the code. + use spaces instead of tabs --- lib/decompress/zstd_decompress_internal.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 7d1f1053b..e4bffdbc6 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -154,7 +154,7 @@ struct ZSTD_DCtx_s size_t rleSize; size_t staticSize; int isFrameDecompression; -#if DYNAMIC_BMI2 != 0 +#if DYNAMIC_BMI2 int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */ #endif @@ -211,11 +211,11 @@ struct ZSTD_DCtx_s }; /* typedef'd to ZSTD_DCtx within "zstd.h" */ MEM_STATIC int ZSTD_DCtx_get_bmi2(const struct ZSTD_DCtx_s *dctx) { -#if DYNAMIC_BMI2 != 0 - return dctx->bmi2; +#if DYNAMIC_BMI2 + return dctx->bmi2; #else (void)dctx; - return 0; + return 0; #endif } From 59afb28c977ab743b4430e8c284c41d209ac49eb Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 24 Jan 2025 02:13:20 +0200 Subject: [PATCH 342/405] Remove unused ZSTD_decompressSequences_t typedef --- lib/decompress/zstd_decompress_block.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index ca5044376..862785a49 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -1935,12 +1935,6 @@ ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx, #endif /* DYNAMIC_BMI2 */ -typedef size_t (*ZSTD_decompressSequences_t)( - ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset); - #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG static size_t ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, From 1b15e888fc1a2f5f84583b0df014c6032eb3a162 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 24 Jan 2025 00:05:03 +0200 Subject: [PATCH 343/405] Move STATIC_BMI2 block as-is to portability_macros.h --- lib/common/compiler.h | 15 --------------- lib/common/portability_macros.h | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index c942b984c..5ad212383 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -207,21 +207,6 @@ # pragma warning(disable : 4324) /* disable: C4324: padded structure */ #endif -/* Like DYNAMIC_BMI2 but for compile time determination of BMI2 support */ -#ifndef STATIC_BMI2 -# if defined(_MSC_VER) -# ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ -# define STATIC_BMI2 1 -# endif -# elif defined(__BMI2__) -# define STATIC_BMI2 1 -# endif -#endif - -#ifndef STATIC_BMI2 -# define STATIC_BMI2 0 -#endif - /* compile time determination of SIMD support */ #if !defined(ZSTD_NO_INTRINSICS) # if defined(__AVX2__) diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index b52394382..b4da8a744 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -74,6 +74,21 @@ # define ZSTD_HIDE_ASM_FUNCTION(func) #endif +/* Like DYNAMIC_BMI2 but for compile time determination of BMI2 support */ +#ifndef STATIC_BMI2 +# if defined(_MSC_VER) +# ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ +# define STATIC_BMI2 1 +# endif +# elif defined(__BMI2__) +# define STATIC_BMI2 1 +# endif +#endif + +#ifndef STATIC_BMI2 +# define STATIC_BMI2 0 +#endif + /* Enable runtime BMI2 dispatch based on the CPU. * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. */ From d486ccc9e90a9d2e0095f9a81cbf29f72bac4f37 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 24 Jan 2025 00:06:13 +0200 Subject: [PATCH 344/405] Update comment for STATIC_BMI2 macro --- lib/common/portability_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index b4da8a744..70964ba01 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -74,7 +74,7 @@ # define ZSTD_HIDE_ASM_FUNCTION(func) #endif -/* Like DYNAMIC_BMI2 but for compile time determination of BMI2 support */ +/* Compile time determination of BMI2 support */ #ifndef STATIC_BMI2 # if defined(_MSC_VER) # ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ From 0a183620a3c21bce4ca3b10a12aba7d7f84c12b2 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 24 Jan 2025 00:09:44 +0200 Subject: [PATCH 345/405] Reorder __BMI2__ check + if `__BMI2__` defined, then set STATIC_BMI2 for all compilers + use `defined(_MSC_VER) && defined(__AVX2__)` as fallback for ms compiler --- lib/common/portability_macros.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/common/portability_macros.h b/lib/common/portability_macros.h index 70964ba01..860734141 100644 --- a/lib/common/portability_macros.h +++ b/lib/common/portability_macros.h @@ -76,12 +76,10 @@ /* Compile time determination of BMI2 support */ #ifndef STATIC_BMI2 -# if defined(_MSC_VER) -# ifdef __AVX2__ /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ -# define STATIC_BMI2 1 -# endif -# elif defined(__BMI2__) +# if defined(__BMI2__) # define STATIC_BMI2 1 +# elif defined(_MSC_VER) && defined(__AVX2__) +# define STATIC_BMI2 1 /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */ # endif #endif From f7e8fc339b1ce64bbbfe3dc149b8cc0a13644844 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 24 Jan 2025 01:25:07 +0200 Subject: [PATCH 346/405] Check `STATIC_BMI2` instead of `STATIC_BMI2 == 1` --- lib/common/bits.h | 8 ++++---- lib/common/bitstream.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/common/bits.h b/lib/common/bits.h index 992cc6925..8e09535a4 100644 --- a/lib/common/bits.h +++ b/lib/common/bits.h @@ -29,7 +29,7 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val) { assert(val != 0); # if defined(_MSC_VER) -# if STATIC_BMI2 == 1 +# if STATIC_BMI2 return (unsigned)_tzcnt_u32(val); # else if (val != 0) { @@ -70,7 +70,7 @@ MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val) { assert(val != 0); # if defined(_MSC_VER) -# if STATIC_BMI2 == 1 +# if STATIC_BMI2 return (unsigned)_lzcnt_u32(val); # else if (val != 0) { @@ -95,7 +95,7 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val) { assert(val != 0); # if defined(_MSC_VER) && defined(_WIN64) -# if STATIC_BMI2 == 1 +# if STATIC_BMI2 return (unsigned)_tzcnt_u64(val); # else if (val != 0) { @@ -128,7 +128,7 @@ MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val) { assert(val != 0); # if defined(_MSC_VER) && defined(_WIN64) -# if STATIC_BMI2 == 1 +# if STATIC_BMI2 return (unsigned)_lzcnt_u64(val); # else if (val != 0) { diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index 2c4245678..3b7ad483d 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -161,7 +161,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, FORCE_INLINE_TEMPLATE BitContainerType BIT_getLowerBits(BitContainerType bitContainer, U32 const nbBits) { -#if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) +#if STATIC_BMI2 && !defined(ZSTD_NO_INTRINSICS) # if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__) return _bzhi_u64(bitContainer, nbBits); # else From 0cda0100ea4b9d87eeaaf68e7d192fbbff4f2ab2 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 24 Jan 2025 01:26:13 +0200 Subject: [PATCH 347/405] fix formatting --- lib/common/bits.h | 187 +++++++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 95 deletions(-) diff --git a/lib/common/bits.h b/lib/common/bits.h index 8e09535a4..f452f0889 100644 --- a/lib/common/bits.h +++ b/lib/common/bits.h @@ -28,29 +28,29 @@ MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val) MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val) { assert(val != 0); -# if defined(_MSC_VER) -# if STATIC_BMI2 - return (unsigned)_tzcnt_u32(val); -# else - if (val != 0) { - unsigned long r; - _BitScanForward(&r, val); - return (unsigned)r; - } else { - /* Should not reach this code path */ - __assume(0); - } -# endif -# elif defined(__GNUC__) && (__GNUC__ >= 4) - return (unsigned)__builtin_ctz(val); -# elif defined(__ICCARM__) - return (unsigned)__builtin_ctz(val); -# else - return ZSTD_countTrailingZeros32_fallback(val); -# endif +#if defined(_MSC_VER) +# if STATIC_BMI2 + return (unsigned)_tzcnt_u32(val); +# else + if (val != 0) { + unsigned long r; + _BitScanForward(&r, val); + return (unsigned)r; + } else { + __assume(0); /* Should not reach this code path */ + } +# endif +#elif defined(__GNUC__) && (__GNUC__ >= 4) + return (unsigned)__builtin_ctz(val); +#elif defined(__ICCARM__) + return (unsigned)__builtin_ctz(val); +#else + return ZSTD_countTrailingZeros32_fallback(val); +#endif } -MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val) { +MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val) +{ assert(val != 0); { static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29, @@ -69,92 +69,89 @@ MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val) { MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val) { assert(val != 0); -# if defined(_MSC_VER) -# if STATIC_BMI2 - return (unsigned)_lzcnt_u32(val); -# else - if (val != 0) { - unsigned long r; - _BitScanReverse(&r, val); - return (unsigned)(31 - r); - } else { - /* Should not reach this code path */ - __assume(0); - } -# endif -# elif defined(__GNUC__) && (__GNUC__ >= 4) - return (unsigned)__builtin_clz(val); -# elif defined(__ICCARM__) - return (unsigned)__builtin_clz(val); -# else - return ZSTD_countLeadingZeros32_fallback(val); -# endif +#if defined(_MSC_VER) +# if STATIC_BMI2 + return (unsigned)_lzcnt_u32(val); +# else + if (val != 0) { + unsigned long r; + _BitScanReverse(&r, val); + return (unsigned)(31 - r); + } else { + __assume(0); /* Should not reach this code path */ + } +# endif +#elif defined(__GNUC__) && (__GNUC__ >= 4) + return (unsigned)__builtin_clz(val); +#elif defined(__ICCARM__) + return (unsigned)__builtin_clz(val); +#else + return ZSTD_countLeadingZeros32_fallback(val); +#endif } MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val) { assert(val != 0); -# if defined(_MSC_VER) && defined(_WIN64) -# if STATIC_BMI2 - return (unsigned)_tzcnt_u64(val); -# else - if (val != 0) { - unsigned long r; - _BitScanForward64(&r, val); - return (unsigned)r; - } else { - /* Should not reach this code path */ - __assume(0); - } -# endif -# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__) - return (unsigned)__builtin_ctzll(val); -# elif defined(__ICCARM__) - return (unsigned)__builtin_ctzll(val); -# else - { - U32 mostSignificantWord = (U32)(val >> 32); - U32 leastSignificantWord = (U32)val; - if (leastSignificantWord == 0) { - return 32 + ZSTD_countTrailingZeros32(mostSignificantWord); - } else { - return ZSTD_countTrailingZeros32(leastSignificantWord); - } +#if defined(_MSC_VER) && defined(_WIN64) +# if STATIC_BMI2 + return (unsigned)_tzcnt_u64(val); +# else + if (val != 0) { + unsigned long r; + _BitScanForward64(&r, val); + return (unsigned)r; + } else { + __assume(0); /* Should not reach this code path */ + } +# endif +#elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__) + return (unsigned)__builtin_ctzll(val); +#elif defined(__ICCARM__) + return (unsigned)__builtin_ctzll(val); +#else + { + U32 mostSignificantWord = (U32)(val >> 32); + U32 leastSignificantWord = (U32)val; + if (leastSignificantWord == 0) { + return 32 + ZSTD_countTrailingZeros32(mostSignificantWord); + } else { + return ZSTD_countTrailingZeros32(leastSignificantWord); } -# endif + } +#endif } MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val) { assert(val != 0); -# if defined(_MSC_VER) && defined(_WIN64) -# if STATIC_BMI2 - return (unsigned)_lzcnt_u64(val); -# else - if (val != 0) { - unsigned long r; - _BitScanReverse64(&r, val); - return (unsigned)(63 - r); - } else { - /* Should not reach this code path */ - __assume(0); - } -# endif -# elif defined(__GNUC__) && (__GNUC__ >= 4) - return (unsigned)(__builtin_clzll(val)); -# elif defined(__ICCARM__) - return (unsigned)(__builtin_clzll(val)); -# else - { - U32 mostSignificantWord = (U32)(val >> 32); - U32 leastSignificantWord = (U32)val; - if (mostSignificantWord == 0) { - return 32 + ZSTD_countLeadingZeros32(leastSignificantWord); - } else { - return ZSTD_countLeadingZeros32(mostSignificantWord); - } +#if defined(_MSC_VER) && defined(_WIN64) +# if STATIC_BMI2 + return (unsigned)_lzcnt_u64(val); +# else + if (val != 0) { + unsigned long r; + _BitScanReverse64(&r, val); + return (unsigned)(63 - r); + } else { + __assume(0); /* Should not reach this code path */ + } +# endif +#elif defined(__GNUC__) && (__GNUC__ >= 4) + return (unsigned)(__builtin_clzll(val)); +#elif defined(__ICCARM__) + return (unsigned)(__builtin_clzll(val)); +#else + { + U32 mostSignificantWord = (U32)(val >> 32); + U32 leastSignificantWord = (U32)val; + if (mostSignificantWord == 0) { + return 32 + ZSTD_countLeadingZeros32(leastSignificantWord); + } else { + return ZSTD_countLeadingZeros32(mostSignificantWord); } -# endif + } +#endif } MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val) From 6cd4204ee30c9d3a1ae00ca4082bf4b5c7e3dd7d Mon Sep 17 00:00:00 2001 From: luau-project Date: Sun, 26 Jan 2025 16:50:39 -0300 Subject: [PATCH 348/405] CI: build with CMake on source directory with spaces to reproduce #4268 --- .github/workflows/dev-short-tests.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index dfe1bf584..8648d777e 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -92,6 +92,31 @@ jobs: sudo apt install liblzma-dev FUZZERTEST=-T1mn ZSTREAM_TESTTIME=-T1mn make cmakebuild V=1 + cmake-source-directory-with-spaces: + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + generator: "Unix Makefiles" + - os: windows-latest + generator: "NMake Makefiles" + - os: macos-latest + generator: "Unix Makefiles" + env: + SRC_DIR: "source directory with spaces" + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + with: + path: "${{ env.SRC_DIR }}" + - uses: ilammy/msvc-dev-cmd@v1 + if: ${{ matrix.generator == 'NMake Makefiles' }} + - name: cmake build on a source directory with spaces + run: | + cmake -S "${{ env.SRC_DIR }}/build/cmake" -B build -DBUILD_TESTING=ON -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release --install-prefix "${{ runner.temp }}/install" + cmake --build build --config Release + cmake --install build --config Release + cpp-gnu90-c99-compatibility: runs-on: ubuntu-latest steps: From 92be4be8102eecedaa0d2a7c65b2d1088e01622a Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Tue, 21 Jan 2025 18:52:46 +0000 Subject: [PATCH 349/405] [linux] Expose ZSTD_compressSequencesAndLiterals() in the kernel Make the function ZSTD_compressSequencesAndLiterals() available in kernel space. This will be used by Intel QAT driver. Additionally, (1) expose the function ZSTD_CCtx_setParameter(), which is required to set parameters before calling ZSTD_compressSequencesAndLiterals(), (2) update the build process to include `compress/zstd_preSplit.o` and (3) replace `asm/unaligned.h` with `linux/unaligned.h`. Signed-off-by: Giovanni Cabiddu --- contrib/linux-kernel/linux.mk | 1 + contrib/linux-kernel/linux_zstd.h | 46 ++++++++++++++++++- contrib/linux-kernel/mem.h | 2 +- .../test/include/{asm => linux}/unaligned.h | 0 .../linux-kernel/test/include/linux/xxhash.h | 2 +- contrib/linux-kernel/zstd_compress_module.c | 17 +++++++ 6 files changed, 64 insertions(+), 4 deletions(-) rename contrib/linux-kernel/test/include/{asm => linux}/unaligned.h (100%) diff --git a/contrib/linux-kernel/linux.mk b/contrib/linux-kernel/linux.mk index 464c410b2..be218b5e0 100644 --- a/contrib/linux-kernel/linux.mk +++ b/contrib/linux-kernel/linux.mk @@ -26,6 +26,7 @@ zstd_compress-y := \ compress/zstd_lazy.o \ compress/zstd_ldm.o \ compress/zstd_opt.o \ + compress/zstd_preSplit.o \ zstd_decompress-y := \ zstd_decompress_module.o \ diff --git a/contrib/linux-kernel/linux_zstd.h b/contrib/linux-kernel/linux_zstd.h index 2daf5d25a..dda8a2d7d 100644 --- a/contrib/linux-kernel/linux_zstd.h +++ b/contrib/linux-kernel/linux_zstd.h @@ -136,9 +136,20 @@ typedef ZSTD_parameters zstd_parameters; zstd_parameters zstd_get_params(int level, unsigned long long estimated_src_size); -/* ====== Single-pass Compression ====== */ - typedef ZSTD_CCtx zstd_cctx; +typedef ZSTD_cParameter zstd_cparameter; + +/** + * zstd_cctx_set_param() - sets a compression parameter + * @cctx: The context. Must have been initialized with zstd_init_cctx(). + * @param: The parameter to set. + * @value: The value to set the parameter to. + * + * Return: Zero or an error, which can be checked using zstd_is_error(). + */ +size_t zstd_cctx_set_param(zstd_cctx *cctx, zstd_cparameter param, int value); + +/* ====== Single-pass Compression ====== */ /** * zstd_cctx_workspace_bound() - max memory needed to initialize a zstd_cctx @@ -480,4 +491,35 @@ typedef ZSTD_FrameHeader zstd_frame_header; size_t zstd_get_frame_header(zstd_frame_header *params, const void *src, size_t src_size); +/** + * struct zstd_sequence - a sequence of literals or a match + * + * @offset: The offset of the match + * @litLength: The literal length of the sequence + * @matchLength: The match length of the sequence + * @rep: Represents which repeat offset is used + */ +typedef ZSTD_Sequence zstd_sequence; + +/** + * zstd_compress_sequences_and_literals() - compress an array of zstd_sequence and literals + * + * @cctx: The zstd compression context. + * @dst: The buffer to compress the data into. + * @dst_capacity: The size of the destination buffer. + * @in_seqs: The array of zstd_sequence to compress. + * @in_seqs_size: The number of sequences in in_seqs. + * @literals: The literals associated to the sequences to be compressed. + * @lit_size: The size of the literals in the literals buffer. + * @lit_capacity: The size of the literals buffer. + * @decompressed_size: The size of the input data + * + * Return: The compressed size or an error, which can be checked using + * zstd_is_error(). + */ +size_t zstd_compress_sequences_and_literals(zstd_cctx *cctx, void* dst, size_t dst_capacity, + const zstd_sequence *in_seqs, size_t in_seqs_size, + const void* literals, size_t lit_size, size_t lit_capacity, + size_t decompressed_size); + #endif /* LINUX_ZSTD_H */ diff --git a/contrib/linux-kernel/mem.h b/contrib/linux-kernel/mem.h index 2e91e7780..d9bd752fe 100644 --- a/contrib/linux-kernel/mem.h +++ b/contrib/linux-kernel/mem.h @@ -15,7 +15,7 @@ /*-**************************************** * Dependencies ******************************************/ -#include /* get_unaligned, put_unaligned* */ +#include /* get_unaligned, put_unaligned* */ #include /* inline */ #include /* swab32, swab64 */ #include /* size_t, ptrdiff_t */ diff --git a/contrib/linux-kernel/test/include/asm/unaligned.h b/contrib/linux-kernel/test/include/linux/unaligned.h similarity index 100% rename from contrib/linux-kernel/test/include/asm/unaligned.h rename to contrib/linux-kernel/test/include/linux/unaligned.h diff --git a/contrib/linux-kernel/test/include/linux/xxhash.h b/contrib/linux-kernel/test/include/linux/xxhash.h index d41cbd933..f993eb9ee 100644 --- a/contrib/linux-kernel/test/include/linux/xxhash.h +++ b/contrib/linux-kernel/test/include/linux/xxhash.h @@ -296,7 +296,7 @@ XXH_API void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state * - xxHash source repository: https://github.com/Cyan4973/xxHash */ -#include +#include #include #include #include diff --git a/contrib/linux-kernel/zstd_compress_module.c b/contrib/linux-kernel/zstd_compress_module.c index 039db55f9..804efe6d5 100644 --- a/contrib/linux-kernel/zstd_compress_module.c +++ b/contrib/linux-kernel/zstd_compress_module.c @@ -80,6 +80,12 @@ zstd_parameters zstd_get_params(int level, } EXPORT_SYMBOL(zstd_get_params); +size_t zstd_cctx_set_param(zstd_cctx *cctx, ZSTD_cParameter param, int value) +{ + return ZSTD_CCtx_setParameter(cctx, param, value); +} +EXPORT_SYMBOL(zstd_cctx_set_param); + size_t zstd_cctx_workspace_bound(const zstd_compression_parameters *cparams) { return ZSTD_estimateCCtxSize_usingCParams(*cparams); @@ -216,5 +222,16 @@ void zstd_register_sequence_producer( } EXPORT_SYMBOL(zstd_register_sequence_producer); +size_t zstd_compress_sequences_and_literals(zstd_cctx *cctx, void* dst, size_t dst_capacity, + const zstd_sequence *in_seqs, size_t in_seqs_size, + const void* literals, size_t lit_size, size_t lit_capacity, + size_t decompressed_size) +{ + return ZSTD_compressSequencesAndLiterals(cctx, dst, dst_capacity, in_seqs, + in_seqs_size, literals, lit_size, + lit_capacity, decompressed_size); +} +EXPORT_SYMBOL(zstd_compress_sequences_and_literals); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Zstd Compressor"); From be1bf2469e44952efb318f80b781e82e8e9e5183 Mon Sep 17 00:00:00 2001 From: luau-project Date: Mon, 27 Jan 2025 15:18:55 -0300 Subject: [PATCH 350/405] fix: quote include directory for resource compiler --- build/cmake/lib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index c02822296..2dcd249c6 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -118,7 +118,7 @@ endmacro () # Define directories containing the library's public headers set(PUBLIC_INCLUDE_DIRS ${LIBRARY_DIR}) -set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} /I ${LIBRARY_DIR}") +set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} /I \"${LIBRARY_DIR}\"") # Split project to static and shared libraries build set(library_targets) if (ZSTD_BUILD_SHARED) From de7c8b984236654a567b7b743913849fa6806e8e Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 28 Jan 2025 00:22:35 +0100 Subject: [PATCH 351/405] cmake: Remove duplicated line --- build/cmake/lib/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 2dcd249c6..4e902a1fb 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -280,7 +280,6 @@ install(TARGETS ${library_targets} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT runtime OPTIONAL - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) From 8df6155495548d5db02b494fd8be23fad8c6cdfc Mon Sep 17 00:00:00 2001 From: luau-project Date: Thu, 30 Jan 2025 06:08:21 -0300 Subject: [PATCH 352/405] CI: enable Intel LLVM C compiler (icx) check --- .github/workflows/dev-short-tests.yml | 41 +++++++++++++-------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 8648d777e..ec9eff57e 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -709,26 +709,23 @@ jobs: run: | sde-external-9.33.0-2024-01-07-lin/sde -cet -cet-raise 0 -cet-endbr-exe -cet-stderr -cet-abort -- ./zstd -b3 + icx: + # install instructions: https://www.intel.com/content/www/us/en/docs/oneapi/installation-guide-linux/2025-0/apt-005.html + name: icx-check + runs-on: ubuntu-latest + steps: + - name: install icx + run: | + # download the key to system keyring + wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \ + | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null -# Failing tests, for reference - -# icc tests are currently failing on Github Actions, likely to issues during installation stage -# -# icc: -# name: icc-check -# runs-on: ubuntu-latest -# steps: -# - name: install icc -# run: | -# export DEBIAN_FRONTEND=noninteractive -# sudo apt-get -qqq update -# sudo apt-get install -y wget build-essential pkg-config cmake ca-certificates gnupg -# sudo wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB -# sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB -# sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main" -# sudo apt-get update -# sudo apt-get install -y intel-basekit intel-hpckit -# - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 -# - name: make check -# run: | -# make CC=/opt/intel/oneapi/compiler/latest/linux/bin/intel64/icc check + # add signed entry to apt sources and configure the APT client to use Intel repository: + echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list + sudo apt-get update + sudo apt-get install -y intel-basekit intel-hpckit + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + - name: make check + run: | + source /opt/intel/oneapi/setvars.sh + make CC=icx check \ No newline at end of file From 60f84f73fed4cb94c166e1dadf3f96ec71a7792c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 30 Jan 2025 21:30:48 -0800 Subject: [PATCH 353/405] bench: better result alignment when displaying ratios > x100 --- programs/benchzstd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 5ea7bb72e..f9274a517 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -633,7 +633,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc( } { - int const ratioAccuracy = (ratio < 10.) ? 3 : 2; + int const ratioDigits = 1 + (ratio < 100.) + (ratio < 10.); assert(cSize < UINT_MAX); OUTPUTLEVEL( 2, @@ -642,7 +642,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc( displayName, (unsigned)srcSize, (unsigned)cSize, - ratioAccuracy, + ratioDigits, ratio, benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT); @@ -669,7 +669,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc( } { - int const ratioAccuracy = (ratio < 10.) ? 3 : 2; + int const ratioDigits = 1 + (ratio < 100.) + (ratio < 10.); OUTPUTLEVEL( 2, "%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\r", @@ -677,7 +677,7 @@ static BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc( displayName, (unsigned)srcSize, (unsigned)cSize, - ratioAccuracy, + ratioDigits, ratio, benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT, From 7b856e3028518109eb34019e215802cda7cbafc1 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Tue, 4 Feb 2025 15:20:39 -0800 Subject: [PATCH 354/405] Add noexecstack flag for gcc/clang C and CPP in Meson The `-Wl,-z,noexecstack` and `-Wa,--noexecstack` flags are already set for CMake, but not for Meson. This brings the flags to the Meson build as well. Note that this maintains the discrepancy in behavior between CMake and Meson when it comes to enabling ASM: on CMake, the ZSTD_HAS_NOEXECSTACK variable is set and these flags added for GCC/Clang and MinGW. Then later, the ZSTD_HAS_NOEXECSTACK variable is checked (along with some other conditions) to enable or disable ASM. However on Meson, this logic is restricted to simply checking for GCC/Clang. This patch maintains this behavior; noexecstack is dependent on GCC/Clang only. --- build/meson/meson.build | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build/meson/meson.build b/build/meson/meson.build index 7ddca2e79..5c35478d5 100644 --- a/build/meson/meson.build +++ b/build/meson/meson.build @@ -116,10 +116,16 @@ if [compiler_gcc, compiler_clang].contains(cc_id) if cc_id == compiler_clang common_warning_flags += ['-Wconversion', '-Wno-sign-conversion', '-Wdocumentation'] endif - cc_compile_flags = cc.get_supported_arguments(common_warning_flags + ['-Wstrict-prototypes']) - cxx_compile_flags = cxx.get_supported_arguments(common_warning_flags) + noexecstack_flags = ['-Wa,--noexecstack' ] + noexecstack_link_flags = ['-Wl,-z,noexecstack'] + cc_compile_flags = cc.get_supported_arguments(common_warning_flags + noexecstack_flags + ['-Wstrict-prototypes']) + cxx_compile_flags = cxx.get_supported_arguments(common_warning_flags + noexecstack_flags) add_project_arguments(cc_compile_flags, language : 'c') add_project_arguments(cxx_compile_flags, language : 'cpp') + cc_link_flags = cc.get_supported_link_arguments(noexecstack_link_flags) + cxx_link_flags = cxx.get_supported_link_arguments(noexecstack_link_flags) + add_project_link_arguments(cc_link_flags, language: 'c') + add_project_link_arguments(cxx_link_flags, language: 'cpp') elif cc_id == compiler_msvc msvc_compile_flags = [ '/D_UNICODE', '/DUNICODE' ] if use_multi_thread From 6e1d02f1f04f9c255108f84cc788b709e7871c2e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 12:06:14 -0800 Subject: [PATCH 355/405] adding a Visual + ClangCL + AVX2 compilation test --- .github/workflows/dev-short-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 8648d777e..26c175994 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -362,6 +362,8 @@ jobs: - generator: "MinGW Makefiles" - generator: "Visual Studio 17 2022" flags: "-T ClangCL" + - generator: "Visual Studio 17 2022" + flags: "-T ClangCL -A x64 -DCMAKE_C_FLAGS=/arch:AVX2" runs-on: windows-2022 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 From bcf404c0ab73cb6cc822a1412b78ba7965f9d74d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 13:25:14 -0800 Subject: [PATCH 356/405] changed C11 keyword to _Alignas so that it doesn't depend on #include --- lib/common/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 5ad212383..66792463b 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -305,7 +305,7 @@ MEM_STATIC int ZSTD_isPower2(size_t u) { # if defined(__GNUC__) # define ZSTD_ALIGNED(a) __attribute__((aligned(a))) # elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ -# define ZSTD_ALIGNED(a) alignas(a) +# define ZSTD_ALIGNED(a) _Alignas(a) #elif defined(_MSC_VER) # define ZSTD_ALIGNED(n) __declspec(align(n)) # else From 54e9d46db44c4832d031100800f54a397358f896 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 13:48:24 -0800 Subject: [PATCH 357/405] added __clang__ to compiler-specific alignment attribute when clang is used within msvc, `__GNUC__` isn't defined, so testing `__clang__` explicitly is required. --- lib/common/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 66792463b..1f7da50e6 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -302,7 +302,7 @@ MEM_STATIC int ZSTD_isPower2(size_t u) { #ifndef ZSTD_ALIGNED /* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */ -# if defined(__GNUC__) +# if defined(__GNUC__) || defined(__clang__) # define ZSTD_ALIGNED(a) __attribute__((aligned(a))) # elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ # define ZSTD_ALIGNED(a) _Alignas(a) From 5883ee6cc2303259f6a5ca824d9b9786c223df54 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 15:38:39 -0800 Subject: [PATCH 358/405] make visual studio tests error out on warnings --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 26c175994..2b35354d2 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -375,7 +375,7 @@ jobs: cd build\cmake mkdir build cd build - cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZSTREAM_FLAGS=-T30s -DZSTD_FUZZER_FLAGS=-T30s -DZSTD_FULLBENCH_FLAGS=-i0 .. + cmake.exe -G "${{matrix.generator}}" ${{matrix.flags}} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZSTREAM_FLAGS=-T30s -DZSTD_FUZZER_FLAGS=-T30s -DZSTD_FULLBENCH_FLAGS=-i0 .. cmake.exe --build . ctest.exe -V -C Debug From 32dff04d320c2dc667380076dff5d575fcf73207 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 15:46:44 -0800 Subject: [PATCH 359/405] fix one minor alignment warning seems like a prototype interface error: input parameter should have been `const void*`, since the documentation is explicit that input doesn't have to be aligned, but `const __m256i*` makes the compiler enforce it. --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index abc75fb2d..356397605 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7191,7 +7191,7 @@ static size_t convertSequences_noRepcodes( /* Process 2 sequences per loop iteration */ for (; i + 1 < nbSequences; i += 2) { /* Load 2 ZSTD_Sequence (32 bytes) */ - __m256i vin = _mm256_loadu_si256((__m256i const*)&inSeqs[i]); + __m256i vin = _mm256_loadu_si256((const __m256i*)(const void*)&inSeqs[i]); /* Add {2, 0, -3, 0} in each 128-bit half */ __m256i vadd = _mm256_add_epi32(vin, addition); From c39424ea87288aec400305c3bc3cf1ec6ef7d803 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 16:11:54 -0800 Subject: [PATCH 360/405] fix minor alignment warning this is a prototype definition error: `_mm_storeu_si128()` should accept a `void*` pointer, since it explicitly states that it accepts unaligned addresses yet requiring a `__m128i*` tells otherwise, and requires the compiler the enforce this alignment. --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 356397605..f9600ff71 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7218,7 +7218,7 @@ static size_t convertSequences_noRepcodes( */ /* Store only the lower 16 bytes => 2 SeqDef (8 bytes each) */ - _mm_storeu_si128((__m128i *)&dstSeqs[i], _mm256_castsi256_si128(vperm)); + _mm_storeu_si128((__m128i *)(void*)&dstSeqs[i], _mm256_castsi256_si128(vperm)); /* * This writes out 16 bytes total: * - offset 0..7 => seq0 (offBase, litLength, mlBase) From e117d79e22ae98be24d1867b0f2b8730e952c835 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 16:13:58 -0800 Subject: [PATCH 361/405] fix minor alignment warning --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index f9600ff71..b755c6bc2 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -7400,7 +7400,7 @@ BlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs) /* Process 2 structs (32 bytes) at a time */ for (i = 0; i + 2 <= nbSeqs; i += 2) { /* Load two consecutive ZSTD_Sequence (8×4 = 32 bytes) */ - __m256i data = _mm256_loadu_si256((const __m256i*)&seqs[i]); + __m256i data = _mm256_loadu_si256((const __m256i*)(const void*)&seqs[i]); /* check end of block signal */ __m256i cmp = _mm256_cmpeq_epi32(data, zeroVec); int cmp_res = _mm256_movemask_epi8(cmp); From f9c1850aa2df6024e930b257067401108fa268ef Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 16:28:52 -0800 Subject: [PATCH 362/405] fix minor printf argument limitation on older mingw which do not support `%zu` fields --- tests/fullbench.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 7d77bd176..12a27f48c 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -696,7 +696,7 @@ check_compressedSequences(const void* compressed, size_t cSize, const void* orig if (decompressed == NULL) return 2; decSize = ZSTD_decompress(decompressed, origSize, compressed, cSize); - if (decSize != origSize) { free(decompressed); DISPLAY("ZSTD_decompress failed (%zu) ", decSize); return 1; } + if (decSize != origSize) { free(decompressed); DISPLAY("ZSTD_decompress failed (%u) ", (unsigned)decSize); return 1; } diff = memcmp(decompressed, orig, origSize); if (diff) { free(decompressed); return 1; } @@ -904,7 +904,7 @@ static int benchMem(unsigned scenarioID, if (verif_f) { size_t const vRes = verif_f(dst, newResult.sumOfReturn, origSrc, origSrcSize); if (vRes) { - DISPLAY(" validation failed ! (%zu)\n", vRes); + DISPLAY(" validation failed ! (%u)\n", (unsigned)vRes); break; } } From 590c22454e24c0247f60a5fd939a1c4f1d49e896 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 16:36:54 -0800 Subject: [PATCH 363/405] fix more %zu warnings --- tests/fuzzer.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index b457c2171..b74460bb5 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1918,7 +1918,7 @@ static int basicUnitTests(U32 const seed, double compressibility) params.fParams.contentSizeFlag = 0; params.cParams.windowLog = ZSTD_WINDOWLOG_MAX; for (cnb = 0; cnb < nbCompressions; ++cnb) { - DISPLAYLEVEL(6, "run %zu / %zu \n", cnb, nbCompressions); + DISPLAYLEVEL(6, "run %u / %u \n", (unsigned)cnb, (unsigned)nbCompressions); CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) ); /* reuse same parameters */ CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize) ); } @@ -1936,8 +1936,8 @@ static int basicUnitTests(U32 const seed, double compressibility) assert(smallCCtx != NULL); CHECK_Z(ZSTD_compressCCtx(smallCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1)); { size_t const smallCCtxSize = ZSTD_sizeof_CCtx(smallCCtx); - DISPLAYLEVEL(5, "(large) %zuKB > 32*%zuKB (small) : ", - largeCCtxSize>>10, smallCCtxSize>>10); + DISPLAYLEVEL(5, "(large) %uKB > 32*%uKB (small) : ", + (unsigned)(largeCCtxSize>>10), (unsigned)(smallCCtxSize>>10)); assert(largeCCtxSize > 32* smallCCtxSize); /* note : "too large" definition is handled within zstd_compress.c . * make this test case extreme, so that it doesn't depend on a possibly fluctuating definition */ } @@ -3480,7 +3480,7 @@ static int basicUnitTests(U32 const seed, double compressibility) { size_t const compressionResult = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize); - DISPLAYLEVEL(5, "simple=%zu vs %zu=advanced : ", cSize_1pass, compressionResult); + DISPLAYLEVEL(5, "simple=%u vs %u=advanced : ", (unsigned)cSize_1pass, (unsigned)compressionResult); if (ZSTD_isError(compressionResult)) goto _output_error; if (compressionResult != cSize_1pass) goto _output_error; } } @@ -4361,8 +4361,8 @@ static int basicUnitTests(U32 const seed, double compressibility) for (; level < ZSTD_maxCLevel(); ++level) { size_t const currSize = ZSTD_estimateCCtxSize(level); if (prevSize > currSize) { - DISPLAYLEVEL(3, "Error! previous cctx size: %zu at level: %d is larger than current cctx size: %zu at level: %d", - prevSize, level-1, currSize, level); + DISPLAYLEVEL(3, "Error! previous cctx size: %u at level: %d is larger than current cctx size: %u at level: %d", + (unsigned)prevSize, level-1, (unsigned)currSize, level); goto _output_error; } prevSize = currSize; @@ -4386,8 +4386,8 @@ static int basicUnitTests(U32 const seed, double compressibility) if (cctxSizeUsingLevel < cctxSizeUsingCParams || ZSTD_isError(cctxSizeUsingCParams) || ZSTD_isError(cctxSizeUsingLevel)) { - DISPLAYLEVEL(3, "error! l: %d dict: %zu srcSize: %zu cctx size cpar: %zu, cctx size level: %zu\n", - level, dictSize, srcSize, cctxSizeUsingCParams, cctxSizeUsingLevel); + DISPLAYLEVEL(3, "error! l: %d dict: %u srcSize: %u cctx size cpar: %u, cctx size level: %u\n", + level, (unsigned)dictSize, (unsigned)srcSize, (unsigned)cctxSizeUsingCParams, (unsigned)cctxSizeUsingLevel); goto _output_error; } } } } } DISPLAYLEVEL(3, "OK \n"); From e87d15938c888011cdcc7aa6d45a85ea055a5da8 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 16:48:19 -0800 Subject: [PATCH 364/405] more %zu warnings fixes --- tests/zstreamtest.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index b8290fefc..b50984f3f 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -537,7 +537,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) outBuff.size = compressedBufferSize; outBuff.pos = 0; { size_t const r = ZSTD_endStream(zc, &outBuff); - CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); + CHECK(r != 0, "Error or some data not flushed (ret=%i)", ZSTD_getErrorCode(r)); } inBuff.src = outBuff.dst; inBuff.size = outBuff.pos; @@ -567,7 +567,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) outBuff.size = compressedBufferSize; outBuff.pos = 0; { size_t const r = ZSTD_endStream(zc, &outBuff); - CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); + CHECK(r != 0, "Error or some data not flushed (ret=%i)", ZSTD_getErrorCode(r)); } inBuff.src = outBuff.dst; inBuff.size = outBuff.pos; @@ -595,7 +595,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed"); { size_t const r = ZSTD_endStream(zc, &outBuff); - CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); + CHECK(r != 0, "Error or some data not flushed (ret=%i)", ZSTD_getErrorCode(r)); } { unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos); CHECK(origSize == ZSTD_CONTENTSIZE_UNKNOWN, "Unknown!"); @@ -777,7 +777,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) CHECK(streamingSize < singlePassSize + (1 << 18) + 3 * ZSTD_BLOCKSIZE_MAX, "Streaming doesn't use the right amount of memory"); CHECK(streamingSize != streaming2KSize + 3 * (ZSTD_BLOCKSIZE_MAX - 2048), "ZSTD_d_blockSizeMax didn't save the right amount of memory"); - DISPLAYLEVEL(3, "| %zu | %zu | %zu | ", singlePassSize, streaming2KSize, streamingSize); + DISPLAYLEVEL(3, "| %u | %u | %u | ", (unsigned)singlePassSize, (unsigned)streaming2KSize, (unsigned)streamingSize); ZSTD_freeDCtx(dctx); } @@ -999,7 +999,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) void* const verifBuf = (char*)outBuf.dst + outBuf.pos; const size_t decSize = ZSTD_decompress(verifBuf, inputSize, outBuf.dst, outBuf.pos); CHECK_Z(decSize); - CHECK(decSize != inputSize, "regenerated %zu bytes, instead of %zu", decSize, inputSize); + CHECK(decSize != inputSize, "regenerated %u bytes, instead of %u", (unsigned)decSize, (unsigned)inputSize); CHECK(memcmp(realSrcStart, verifBuf, inputSize) != 0, "regenerated data different from original"); } } DISPLAYLEVEL(3, "OK \n"); @@ -1029,14 +1029,14 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) void* const verifBuf = (char*)outBuf.dst + outBuf.pos; const size_t decSize = ZSTD_decompress(verifBuf, inputSize, outBuf.dst, outBuf.pos); CHECK_Z(decSize); - CHECK(decSize != inputSize, "regenerated %zu bytes, instead of %zu", decSize, inputSize); + CHECK(decSize != inputSize, "regenerated %u bytes, instead of %u", (unsigned)decSize, (unsigned)inputSize); CHECK(memcmp(realSrcStart, verifBuf, inputSize) != 0, "regenerated data different from original"); } } DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer: context size : ", testNb++); { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); - DISPLAYLEVEL(4, "cctxSize1=%zu; cctxSize=%zu; cctxSize2=%zu : ", cctxSize1, cctxSize, cctxSize2); + DISPLAYLEVEL(4, "cctxSize1=%u; cctxSize=%u; cctxSize2=%u : ", (unsigned)cctxSize1, (unsigned)cctxSize, (unsigned)cctxSize2); CHECK(!(cctxSize1 < cctxSize), "Must be bigger than single-pass"); CHECK(!(cctxSize < cctxSize2), "Must be smaller than streaming"); cctxSize1 = cctxSize; @@ -1071,7 +1071,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() with ZSTD_c_stableOutBuffer: context size : ", testNb++); { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); - DISPLAYLEVEL(4, "cctxSize1=%zu; cctxSize=%zu; cctxSize2=%zu : ", cctxSize1, cctxSize, cctxSize2); + DISPLAYLEVEL(4, "cctxSize1=%u; cctxSize=%u; cctxSize2=%u : ", (unsigned)cctxSize1, (unsigned)cctxSize, (unsigned)cctxSize2); CHECK(!(cctxSize1 < cctxSize), "Must be bigger than single-pass and stableInBuffer"); CHECK(!(cctxSize < cctxSize2), "Must be smaller than streaming"); } @@ -2983,7 +2983,7 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest, const U32 windowLogMax = bigTests ? 24 : 20; const U32 searchLogMax = bigTests ? 15 : 13; if (dictSize) - DISPLAYLEVEL(5, "t%u: with dictionary of size : %zu \n", testNb, dictSize); + DISPLAYLEVEL(5, "t%u: with dictionary of size : %u \n", testNb, (unsigned)dictSize); /* mess with compression parameters */ cParams.windowLog += (FUZ_rand(&lseed) & 3) - 1; @@ -3178,7 +3178,7 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest, } cSize = outBuff.pos; compressedCrcs[iter] = XXH64(cBuffer, cSize, 0); - DISPLAYLEVEL(5, "Frame completed : %zu bytes \n", cSize); + DISPLAYLEVEL(5, "Frame completed : %u bytes \n", (unsigned)cSize); } CHECK(!(compressedCrcs[0] == compressedCrcs[1]), "Compression is not deterministic!"); } @@ -3194,7 +3194,7 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest, CHECK_Z( ZSTD_resetDStream(zd) ); } else { if (dictSize) - DISPLAYLEVEL(5, "using dictionary of size %zu \n", dictSize); + DISPLAYLEVEL(5, "using dictionary of size %u \n", (unsigned)dictSize); CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) ); } if (FUZ_rand(&lseed) & 1) { From 294925292304b3c5b5e975f9036a684881dba469 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 17:01:19 -0800 Subject: [PATCH 365/405] fix minor conversion warnings --- tests/zstreamtest.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index b50984f3f..760d9f26c 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -1505,7 +1505,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : compress %u bytes with multiple threads + dictionary : ", testNb++, (unsigned)srcSize); CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 3) ); CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, nbWorkers) ); - CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_jobSize, jobSize) ); + CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_jobSize, (int)jobSize) ); assert(start > offset); assert(start + segLength < COMPRESSIBLE_NOISE_LENGTH); memcpy(dst, srcToCopy, segLength); /* create a long repetition at long distance for job 2 */ @@ -1654,7 +1654,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) int windowLog; int const kMaxWindowLog = bigTests ? 29 : 26; size_t const kNbSequences = 10000; - size_t const kMaxSrcSize = (1u << kMaxWindowLog) + 10 * kNbSequences; + size_t const kMaxSrcSize = ((size_t)1 << kMaxWindowLog) + 10 * kNbSequences; char* src = calloc(kMaxSrcSize, 1); ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences); for (windowLog = ZSTD_WINDOWLOG_MIN; windowLog <= kMaxWindowLog; ++windowLog) { @@ -1902,7 +1902,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_flush)); CHECK(in.pos != in.size, "input not fully consumed"); - remainingInput -= kSmallBlockSize; + remainingInput -= (int)kSmallBlockSize; } /* Write several very long offset matches into the dictionary */ for (offset = 1024; offset >= 0; offset -= 128) { @@ -2582,13 +2582,13 @@ static int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double co static const U32 maxSampleLog = 19; size_t const srcBufferSize = (size_t)1< Date: Thu, 30 Jan 2025 15:58:20 -0800 Subject: [PATCH 366/405] fix speed of --patch-from at high compression mode --- lib/compress/zstd_compress.c | 69 ++++++++++++++++++---------------- lib/compress/zstdmt_compress.c | 4 +- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b755c6bc2..bd7667d4a 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3117,7 +3117,7 @@ ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_Para ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat)); - DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder); + DEBUGLOG(5, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder); if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) { static const ZSTD_BlockCompressor_f rowBasedBlockCompressors[4][3] = { { @@ -3141,7 +3141,7 @@ ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_Para ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW } }; - DEBUGLOG(4, "Selecting a row-based matchfinder"); + DEBUGLOG(5, "Selecting a row-based matchfinder"); assert(useRowMatchFinder != ZSTD_ps_auto); selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy]; } else { @@ -3619,7 +3619,7 @@ writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock) lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); MEM_writeLE24(op, cBlockHeader); - DEBUGLOG(3, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock); + DEBUGLOG(5, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock); } /** ZSTD_buildBlockEntropyStats_literals() : @@ -4151,18 +4151,18 @@ ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, if (cSeqsSize == 0) { cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock); FORWARD_IF_ERROR(cSize, "Nocompress block failed"); - DEBUGLOG(4, "Writing out nocompress block, size: %zu", cSize); + DEBUGLOG(5, "Writing out nocompress block, size: %zu", cSize); *dRep = dRepOriginal; /* reset simulated decompression repcode history */ } else if (cSeqsSize == 1) { cSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, srcSize, lastBlock); FORWARD_IF_ERROR(cSize, "RLE compress block failed"); - DEBUGLOG(4, "Writing out RLE block, size: %zu", cSize); + DEBUGLOG(5, "Writing out RLE block, size: %zu", cSize); *dRep = dRepOriginal; /* reset simulated decompression repcode history */ } else { ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); writeBlockHeader(op, cSeqsSize, srcSize, lastBlock); cSize = ZSTD_blockHeaderSize + cSeqsSize; - DEBUGLOG(4, "Writing out compressed block, size: %zu", cSize); + DEBUGLOG(5, "Writing out compressed block, size: %zu", cSize); } if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) @@ -4357,7 +4357,7 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc, { U32 nbSeq; size_t cSize; - DEBUGLOG(4, "ZSTD_compressBlock_splitBlock"); + DEBUGLOG(5, "ZSTD_compressBlock_splitBlock"); assert(zc->appliedParams.postBlockSplitter == ZSTD_ps_enable); { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); @@ -4368,7 +4368,7 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc, RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block"); cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); - DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block"); + DEBUGLOG(5, "ZSTD_compressBlock_splitBlock: Nocompress block"); return cSize; } nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart); @@ -4603,7 +4603,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSizeMax=%u)", (unsigned)blockSizeMax); + DEBUGLOG(5, "ZSTD_compress_frameChunk (srcSize=%u, blockSizeMax=%u)", (unsigned)srcSize, (unsigned)blockSizeMax); if (cctx->appliedParams.fParams.checksumFlag && srcSize) XXH64_update(&cctx->xxhState, src, srcSize); @@ -4898,13 +4898,14 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const /*! ZSTD_loadDictionaryContent() : * @return : 0, or an error code */ -static size_t ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, - ldmState_t* ls, - ZSTD_cwksp* ws, - ZSTD_CCtx_params const* params, - const void* src, size_t srcSize, - ZSTD_dictTableLoadMethod_e dtlm, - ZSTD_tableFillPurpose_e tfp) +static size_t +ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, + ldmState_t* ls, + ZSTD_cwksp* ws, + ZSTD_CCtx_params const* params, + const void* src, size_t srcSize, + ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp) { const BYTE* ip = (const BYTE*) src; const BYTE* const iend = ip + srcSize; @@ -4948,17 +4949,18 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, } ZSTD_window_update(&ms->window, src, srcSize, /* forceNonContiguous */ 0); - DEBUGLOG(4, "ZSTD_loadDictionaryContent(): useRowMatchFinder=%d", (int)params->useRowMatchFinder); + DEBUGLOG(4, "ZSTD_loadDictionaryContent: useRowMatchFinder=%d", (int)params->useRowMatchFinder); if (loadLdmDict) { /* Load the entire dict into LDM matchfinders. */ + DEBUGLOG(4, "ZSTD_loadDictionaryContent: Trigger loadLdmDict"); ZSTD_window_update(&ls->window, src, srcSize, /* forceNonContiguous */ 0); ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base); ZSTD_ldm_fillHashTable(ls, ip, iend, ¶ms->ldmParams); + DEBUGLOG(4, "ZSTD_loadDictionaryContent: ZSTD_ldm_fillHashTable completes"); } /* If the dict is larger than we can reasonably index in our tables, only load the suffix. */ - if (params->cParams.strategy < ZSTD_btultra) { - U32 maxDictSize = 8U << MIN(MAX(params->cParams.hashLog, params->cParams.chainLog), 28); + { U32 maxDictSize = 2U << MIN(MAX(params->cParams.hashLog, params->cParams.chainLog), 30); if (srcSize > maxDictSize) { ip = iend - maxDictSize; src = ip; @@ -5022,6 +5024,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \ || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR) assert(srcSize >= HASH_READ_SIZE); + DEBUGLOG(4, "Fill %u bytes into the Binary Tree", (unsigned)srcSize); ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend); #else assert(0); /* shouldn't be called: cparams should've been adjusted. */ @@ -5598,14 +5601,16 @@ static size_t ZSTD_initCDict_internal( return 0; } -static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_compressionParameters cParams, - ZSTD_ParamSwitch_e useRowMatchFinder, - int enableDedicatedDictSearch, - ZSTD_customMem customMem) +static ZSTD_CDict* +ZSTD_createCDict_advanced_internal(size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_compressionParameters cParams, + ZSTD_ParamSwitch_e useRowMatchFinder, + int enableDedicatedDictSearch, + ZSTD_customMem customMem) { if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + DEBUGLOG(3, "ZSTD_createCDict_advanced_internal (dictSize=%u)", (unsigned)dictSize); { size_t const workspaceSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + @@ -5642,6 +5647,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, { ZSTD_CCtx_params cctxParams; ZSTD_memset(&cctxParams, 0, sizeof(cctxParams)); + DEBUGLOG(3, "ZSTD_createCDict_advanced, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); ZSTD_CCtxParams_init(&cctxParams, 0); cctxParams.cParams = cParams; cctxParams.customMem = customMem; @@ -5662,7 +5668,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_compressionParameters cParams; ZSTD_CDict* cdict; - DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType); + DEBUGLOG(3, "ZSTD_createCDict_advanced2, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); if (!customMem.customAlloc ^ !customMem.customFree) return NULL; if (cctxParams.enableDedicatedDictSearch) { @@ -5681,7 +5687,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); } - DEBUGLOG(3, "ZSTD_createCDict_advanced2: DDS: %u", cctxParams.enableDedicatedDictSearch); + DEBUGLOG(3, "ZSTD_createCDict_advanced2: DedicatedDictSearch=%u", cctxParams.enableDedicatedDictSearch); cctxParams.cParams = cParams; cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); @@ -5767,6 +5773,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict( ZSTD_CDict* cdict; ZSTD_CCtx_params params; + DEBUGLOG(4, "ZSTD_initStaticCDict (dictSize==%u)", (unsigned)dictSize); if ((size_t)workspace & 7) return NULL; /* 8-aligned */ { @@ -5777,8 +5784,6 @@ const ZSTD_CDict* ZSTD_initStaticCDict( ZSTD_cwksp_move(&cdict->workspace, &ws); } - DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u", - (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize)); if (workspaceSize < neededSize) return NULL; ZSTD_CCtxParams_init(¶ms, 0); @@ -6357,7 +6362,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, */ params.compressionLevel = cctx->cdict->compressionLevel; } - DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); + DEBUGLOG(4, "ZSTD_CCtx_init_compressStream2 : transparent init stage"); if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-determine pledgedSrcSize */ { size_t const dictSize = prefixDict.dict @@ -6388,9 +6393,9 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ } if (params.nbWorkers > 0) { -#if ZSTD_TRACE +# if ZSTD_TRACE cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0; -#endif +# endif /* mt context creation */ if (cctx->mtctx == NULL) { DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index e8fef5144..86ca05315 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1245,13 +1245,11 @@ size_t ZSTDMT_initCStream_internal( /* init */ if (params.nbWorkers != mtctx->params.nbWorkers) - FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) , ""); + FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, (unsigned)params.nbWorkers) , ""); if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX; - DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers); - if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */ ZSTDMT_waitForAllJobsCompleted(mtctx); ZSTDMT_releaseAllJobResources(mtctx); From 34ba14437aeeb5e678ae7f1dbdfa6333beb2723b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 30 Jan 2025 18:05:58 -0800 Subject: [PATCH 367/405] minor boundary change improves compression ratio at low levels --- Makefile | 6 +++--- lib/compress/zstd_compress.c | 2 +- tests/regression/results.csv | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 03ee6fe89..e8e6bcffe 100644 --- a/Makefile +++ b/Makefile @@ -296,9 +296,9 @@ msanregressiontest: update_regressionResults : REGRESS_RESULTS_DIR := /tmp/regress_results_dir/ update_regressionResults: - $(MAKE) -C programs zstd - $(MAKE) -C tests/regression test - $(RM) -rf $(REGRESS_RESULTS_DIR) + $(MAKE) -j -C programs zstd + $(MAKE) -j -C tests/regression test + $(RM) -r $(REGRESS_RESULTS_DIR) $(MKDIR) $(REGRESS_RESULTS_DIR) ./tests/regression/test \ --cache tests/regression/cache \ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bd7667d4a..d394617bc 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4960,7 +4960,7 @@ ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, } /* If the dict is larger than we can reasonably index in our tables, only load the suffix. */ - { U32 maxDictSize = 2U << MIN(MAX(params->cParams.hashLog, params->cParams.chainLog), 30); + { U32 maxDictSize = 1U << MIN(MAX(params->cParams.hashLog + 3, params->cParams.chainLog + 1), 31); if (srcSize > maxDictSize) { ip = iend - maxDictSize; src = ip; diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 94d113578..505f4755b 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -395,19 +395,19 @@ github, level 13 with dict, advanced github, level 13 with dict dms, advanced one pass, 39900 github, level 13 with dict dds, advanced one pass, 39900 github, level 13 with dict copy, advanced one pass, 39948 -github, level 13 with dict load, advanced one pass, 42624 +github, level 13 with dict load, advanced one pass, 42643 github, level 16, advanced one pass, 133209 github, level 16 with dict, advanced one pass, 37902 github, level 16 with dict dms, advanced one pass, 37902 github, level 16 with dict dds, advanced one pass, 37902 github, level 16 with dict copy, advanced one pass, 37892 -github, level 16 with dict load, advanced one pass, 42402 +github, level 16 with dict load, advanced one pass, 42434 github, level 19, advanced one pass, 132879 github, level 19 with dict, advanced one pass, 37916 github, level 19 with dict dms, advanced one pass, 37916 github, level 19 with dict dds, advanced one pass, 37916 github, level 19 with dict copy, advanced one pass, 37906 -github, level 19 with dict load, advanced one pass, 39770 +github, level 19 with dict load, advanced one pass, 40405 github, no source size, advanced one pass, 136331 github, no source size with dict, advanced one pass, 41118 github, long distance mode, advanced one pass, 136331 @@ -713,19 +713,19 @@ github, level 13 with dict, advanced github, level 13 with dict dms, advanced one pass small out, 39900 github, level 13 with dict dds, advanced one pass small out, 39900 github, level 13 with dict copy, advanced one pass small out, 39948 -github, level 13 with dict load, advanced one pass small out, 42624 +github, level 13 with dict load, advanced one pass small out, 42643 github, level 16, advanced one pass small out, 133209 github, level 16 with dict, advanced one pass small out, 37902 github, level 16 with dict dms, advanced one pass small out, 37902 github, level 16 with dict dds, advanced one pass small out, 37902 github, level 16 with dict copy, advanced one pass small out, 37892 -github, level 16 with dict load, advanced one pass small out, 42402 +github, level 16 with dict load, advanced one pass small out, 42434 github, level 19, advanced one pass small out, 132879 github, level 19 with dict, advanced one pass small out, 37916 github, level 19 with dict dms, advanced one pass small out, 37916 github, level 19 with dict dds, advanced one pass small out, 37916 github, level 19 with dict copy, advanced one pass small out, 37906 -github, level 19 with dict load, advanced one pass small out, 39770 +github, level 19 with dict load, advanced one pass small out, 40405 github, no source size, advanced one pass small out, 136331 github, no source size with dict, advanced one pass small out, 41118 github, long distance mode, advanced one pass small out, 136331 @@ -1031,19 +1031,19 @@ github, level 13 with dict, advanced github, level 13 with dict dms, advanced streaming, 39900 github, level 13 with dict dds, advanced streaming, 39900 github, level 13 with dict copy, advanced streaming, 39948 -github, level 13 with dict load, advanced streaming, 42624 +github, level 13 with dict load, advanced streaming, 42643 github, level 16, advanced streaming, 133209 github, level 16 with dict, advanced streaming, 37902 github, level 16 with dict dms, advanced streaming, 37902 github, level 16 with dict dds, advanced streaming, 37902 github, level 16 with dict copy, advanced streaming, 37892 -github, level 16 with dict load, advanced streaming, 42402 +github, level 16 with dict load, advanced streaming, 42434 github, level 19, advanced streaming, 132879 github, level 19 with dict, advanced streaming, 37916 github, level 19 with dict dms, advanced streaming, 37916 github, level 19 with dict dds, advanced streaming, 37916 github, level 19 with dict copy, advanced streaming, 37906 -github, level 19 with dict load, advanced streaming, 39770 +github, level 19 with dict load, advanced streaming, 40405 github, no source size, advanced streaming, 136331 github, no source size with dict, advanced streaming, 41118 github, long distance mode, advanced streaming, 136331 From e637fc64c5f918e316146fb1d78c1cb587b1134c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 Jan 2025 15:00:36 -0800 Subject: [PATCH 368/405] update type naming convention --- lib/compress/zstdmt_compress.c | 102 ++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 86ca05315..fe98dab1c 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -90,9 +90,9 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void) typedef struct buffer_s { void* start; size_t capacity; -} buffer_t; +} Buffer; -static const buffer_t g_nullBuffer = { NULL, 0 }; +static const Buffer g_nullBuffer = { NULL, 0 }; typedef struct ZSTDMT_bufferPool_s { ZSTD_pthread_mutex_t poolMutex; @@ -100,7 +100,7 @@ typedef struct ZSTDMT_bufferPool_s { unsigned totalBuffers; unsigned nbBuffers; ZSTD_customMem cMem; - buffer_t* buffers; + Buffer* buffers; } ZSTDMT_bufferPool; static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool) @@ -128,7 +128,7 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_cu ZSTD_customFree(bufPool, cMem); return NULL; } - bufPool->buffers = (buffer_t*)ZSTD_customCalloc(maxNbBuffers * sizeof(buffer_t), cMem); + bufPool->buffers = (Buffer*)ZSTD_customCalloc(maxNbBuffers * sizeof(Buffer), cMem); if (bufPool->buffers==NULL) { ZSTDMT_freeBufferPool(bufPool); return NULL; @@ -144,7 +144,7 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_cu static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool) { size_t const poolSize = sizeof(*bufPool); - size_t const arraySize = bufPool->totalBuffers * sizeof(buffer_t); + size_t const arraySize = bufPool->totalBuffers * sizeof(Buffer); unsigned u; size_t totalBufferSize = 0; ZSTD_pthread_mutex_lock(&bufPool->poolMutex); @@ -189,13 +189,13 @@ static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, * assumption : bufPool must be valid * @return : a buffer, with start pointer and size * note: allocation may fail, in this case, start==NULL and size==0 */ -static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) +static Buffer ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) { size_t const bSize = bufPool->bufferSize; DEBUGLOG(5, "ZSTDMT_getBuffer: bSize = %u", (U32)bufPool->bufferSize); ZSTD_pthread_mutex_lock(&bufPool->poolMutex); if (bufPool->nbBuffers) { /* try to use an existing buffer */ - buffer_t const buf = bufPool->buffers[--(bufPool->nbBuffers)]; + Buffer const buf = bufPool->buffers[--(bufPool->nbBuffers)]; size_t const availBufferSize = buf.capacity; bufPool->buffers[bufPool->nbBuffers] = g_nullBuffer; if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) { @@ -212,7 +212,7 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); /* create new buffer */ DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer"); - { buffer_t buffer; + { Buffer buffer; void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); buffer.start = start; /* note : start can be NULL if malloc fails ! */ buffer.capacity = (start==NULL) ? 0 : bSize; @@ -231,12 +231,12 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) * @return : a buffer that is at least the buffer pool buffer size. * If a reallocation happens, the data in the input buffer is copied. */ -static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer) +static Buffer ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, Buffer buffer) { size_t const bSize = bufPool->bufferSize; if (buffer.capacity < bSize) { void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); - buffer_t newBuffer; + Buffer newBuffer; newBuffer.start = start; newBuffer.capacity = start == NULL ? 0 : bSize; if (start != NULL) { @@ -252,7 +252,7 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer) #endif /* store buffer for later re-use, up to pool capacity */ -static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf) +static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, Buffer buf) { DEBUGLOG(5, "ZSTDMT_releaseBuffer"); if (buf.start == NULL) return; /* compatible with release on NULL */ @@ -290,7 +290,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) return ZSTDMT_sizeof_bufferPool(seqPool); } -static RawSeqStore_t bufferToSeq(buffer_t buffer) +static RawSeqStore_t bufferToSeq(Buffer buffer) { RawSeqStore_t seq = kNullRawSeqStore; seq.seq = (rawSeq*)buffer.start; @@ -298,9 +298,9 @@ static RawSeqStore_t bufferToSeq(buffer_t buffer) return seq; } -static buffer_t seqToBuffer(RawSeqStore_t seq) +static Buffer seqToBuffer(RawSeqStore_t seq) { - buffer_t buffer; + Buffer buffer; buffer.start = seq.seq; buffer.capacity = seq.capacity * sizeof(rawSeq); return buffer; @@ -466,7 +466,7 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx) typedef struct { void const* start; size_t size; -} range_t; +} Range; typedef struct { /* All variables in the struct are protected by mutex. */ @@ -482,10 +482,10 @@ typedef struct { ZSTD_pthread_mutex_t ldmWindowMutex; ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */ ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */ -} serialState_t; +} SerialState; static int -ZSTDMT_serialState_reset(serialState_t* serialState, +ZSTDMT_serialState_reset(SerialState* serialState, ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params, size_t jobSize, @@ -555,7 +555,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState, return 0; } -static int ZSTDMT_serialState_init(serialState_t* serialState) +static int ZSTDMT_serialState_init(SerialState* serialState) { int initError = 0; ZSTD_memset(serialState, 0, sizeof(*serialState)); @@ -566,7 +566,7 @@ static int ZSTDMT_serialState_init(serialState_t* serialState) return initError; } -static void ZSTDMT_serialState_free(serialState_t* serialState) +static void ZSTDMT_serialState_free(SerialState* serialState) { ZSTD_customMem cMem = serialState->params.customMem; ZSTD_pthread_mutex_destroy(&serialState->mutex); @@ -577,9 +577,9 @@ static void ZSTDMT_serialState_free(serialState_t* serialState) ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); } -static void ZSTDMT_serialState_update(serialState_t* serialState, +static void ZSTDMT_serialState_update(SerialState* serialState, ZSTD_CCtx* jobCCtx, RawSeqStore_t seqStore, - range_t src, unsigned jobID) + Range src, unsigned jobID) { /* Wait for our turn */ ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex); @@ -623,7 +623,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState, } } -static void ZSTDMT_serialState_ensureFinished(serialState_t* serialState, +static void ZSTDMT_serialState_ensureFinished(SerialState* serialState, unsigned jobID, size_t cSize) { ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex); @@ -647,7 +647,7 @@ static void ZSTDMT_serialState_ensureFinished(serialState_t* serialState, /* ===== Worker thread ===== */ /* ------------------------------------------ */ -static const range_t kNullRange = { NULL, 0 }; +static const Range kNullRange = { NULL, 0 }; typedef struct { size_t consumed; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */ @@ -657,10 +657,10 @@ typedef struct { ZSTDMT_CCtxPool* cctxPool; /* Thread-safe - used by mtctx and (all) workers */ ZSTDMT_bufferPool* bufPool; /* Thread-safe - used by mtctx and (all) workers */ ZSTDMT_seqPool* seqPool; /* Thread-safe - used by mtctx and (all) workers */ - serialState_t* serial; /* Thread-safe - used by mtctx and (all) workers */ - buffer_t dstBuff; /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */ - range_t prefix; /* set by mtctx, then read by worker & mtctx => no barrier */ - range_t src; /* set by mtctx, then read by worker & mtctx => no barrier */ + SerialState* serial; /* Thread-safe - used by mtctx and (all) workers */ + Buffer dstBuff; /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */ + Range prefix; /* set by mtctx, then read by worker & mtctx => no barrier */ + Range src; /* set by mtctx, then read by worker & mtctx => no barrier */ unsigned jobID; /* set by mtctx, then read by worker => no barrier */ unsigned firstJob; /* set by mtctx, then read by worker => no barrier */ unsigned lastJob; /* set by mtctx, then read by worker => no barrier */ @@ -686,7 +686,7 @@ static void ZSTDMT_compressionJob(void* jobDescription) ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */ ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool); RawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool); - buffer_t dstBuff = job->dstBuff; + Buffer dstBuff = job->dstBuff; size_t lastCBlockSize = 0; /* resources */ @@ -809,10 +809,10 @@ _endJob: /* ------------------------------------------ */ typedef struct { - range_t prefix; /* read-only non-owned prefix buffer */ - buffer_t buffer; + Range prefix; /* read-only non-owned prefix buffer */ + Buffer buffer; size_t filled; -} inBuff_t; +} InBuff_t; typedef struct { BYTE* buffer; /* The round input buffer. All jobs get references @@ -826,9 +826,9 @@ typedef struct { * the inBuff is sent to the worker thread. * pos <= capacity. */ -} roundBuff_t; +} RoundBuff_t; -static const roundBuff_t kNullRoundBuff = {NULL, 0, 0}; +static const RoundBuff_t kNullRoundBuff = {NULL, 0, 0}; #define RSYNC_LENGTH 32 /* Don't create chunks smaller than the zstd block size. @@ -845,7 +845,7 @@ typedef struct { U64 hash; U64 hitMask; U64 primePower; -} rsyncState_t; +} RSyncState_t; struct ZSTDMT_CCtx_s { POOL_ctx* factory; @@ -857,10 +857,10 @@ struct ZSTDMT_CCtx_s { size_t targetSectionSize; size_t targetPrefixSize; int jobReady; /* 1 => one job is already prepared, but pool has shortage of workers. Don't create a new job. */ - inBuff_t inBuff; - roundBuff_t roundBuff; - serialState_t serial; - rsyncState_t rsync; + InBuff_t inBuff; + RoundBuff_t roundBuff; + SerialState serial; + RSyncState_t rsync; unsigned jobIDMask; unsigned doneJobID; unsigned nextJobID; @@ -1538,7 +1538,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u * If the data of the first job is broken up into two segments, we cover both * sections. */ -static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx) +static Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx) { unsigned const firstJobID = mtctx->doneJobID; unsigned const lastJobID = mtctx->nextJobID; @@ -1553,7 +1553,7 @@ static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx) ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex); if (consumed < mtctx->jobs[wJobID].src.size) { - range_t range = mtctx->jobs[wJobID].prefix; + Range range = mtctx->jobs[wJobID].prefix; if (range.size == 0) { /* Empty prefix */ range = mtctx->jobs[wJobID].src; @@ -1569,7 +1569,7 @@ static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx) /** * Returns non-zero iff buffer and range overlap. */ -static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range) +static int ZSTDMT_isOverlapped(Buffer buffer, Range range) { BYTE const* const bufferStart = (BYTE const*)buffer.start; BYTE const* const rangeStart = (BYTE const*)range.start; @@ -1589,10 +1589,10 @@ static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range) } } -static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window) +static int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window) { - range_t extDict; - range_t prefix; + Range extDict; + Range prefix; DEBUGLOG(5, "ZSTDMT_doesOverlapWindow"); extDict.start = window.dictBase + window.lowLimit; @@ -1611,7 +1611,7 @@ static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window) || ZSTDMT_isOverlapped(buffer, prefix); } -static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer) +static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, Buffer buffer) { if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) { ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex; @@ -1636,10 +1636,10 @@ static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer) */ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) { - range_t const inUse = ZSTDMT_getInputDataInUse(mtctx); + Range const inUse = ZSTDMT_getInputDataInUse(mtctx); size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos; size_t const target = mtctx->targetSectionSize; - buffer_t buffer; + Buffer buffer; DEBUGLOG(5, "ZSTDMT_tryGetInputRange"); assert(mtctx->inBuff.buffer.start == NULL); @@ -1691,7 +1691,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) typedef struct { size_t toLoad; /* The number of bytes to load from the input. */ int flush; /* Boolean declaring if we must flush because we found a synchronization point. */ -} syncPoint_t; +} SyncPoint; /** * Searches through the input for a synchronization point. If one is found, we @@ -1699,14 +1699,14 @@ typedef struct { * Otherwise, we will load as many bytes as possible and instruct the caller * to continue as normal. */ -static syncPoint_t +static SyncPoint findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input) { BYTE const* const istart = (BYTE const*)input.src + input.pos; U64 const primePower = mtctx->rsync.primePower; U64 const hitMask = mtctx->rsync.hitMask; - syncPoint_t syncPoint; + SyncPoint syncPoint; U64 hash; BYTE const* prev; size_t pos; @@ -1838,7 +1838,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, DEBUGLOG(5, "ZSTDMT_tryGetInputRange completed successfully : mtctx->inBuff.buffer.start = %p", mtctx->inBuff.buffer.start); } if (mtctx->inBuff.buffer.start != NULL) { - syncPoint_t const syncPoint = findSynchronizationPoint(mtctx, *input); + SyncPoint const syncPoint = findSynchronizationPoint(mtctx, *input); if (syncPoint.flush && endOp == ZSTD_e_continue) { endOp = ZSTD_e_flush; } From 85a44b233accb544d89c85b804182e3f34e8d4b1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 Jan 2025 15:53:25 -0800 Subject: [PATCH 369/405] always free .cdictLocal --- lib/compress/zstdmt_compress.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index fe98dab1c..dbaffe536 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1258,15 +1258,14 @@ size_t ZSTDMT_initCStream_internal( mtctx->params = params; mtctx->frameContentSize = pledgedSrcSize; + ZSTD_freeCDict(mtctx->cdictLocal); if (dict) { - ZSTD_freeCDict(mtctx->cdictLocal); mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ params.cParams, mtctx->cMem); mtctx->cdict = mtctx->cdictLocal; if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); } else { - ZSTD_freeCDict(mtctx->cdictLocal); mtctx->cdictLocal = NULL; mtctx->cdict = cdict; } @@ -1401,7 +1400,7 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZS mtctx->roundBuff.pos += srcSize; mtctx->inBuff.buffer = g_nullBuffer; mtctx->inBuff.filled = 0; - /* Set the prefix */ + /* Set the prefix for next job */ if (!endFrame) { size_t const newPrefixSize = MIN(srcSize, mtctx->targetPrefixSize); mtctx->inBuff.prefix.start = src + srcSize - newPrefixSize; From 220abe6da857142305ab7337b346c826856bcfd1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 Jan 2025 18:19:45 -0800 Subject: [PATCH 370/405] reduced memory usage by avoiding to duplicate in memory a dictionary that was passed by reference. --- lib/compress/zstd_compress.c | 12 +++++++----- lib/compress/zstd_compress_internal.h | 27 ++++++++++++++------------- lib/compress/zstd_lazy.c | 16 ++++++++-------- lib/compress/zstd_opt.c | 14 +++++++------- lib/compress/zstdmt_compress.c | 4 ++-- lib/compress/zstdmt_compress.h | 2 +- 6 files changed, 39 insertions(+), 36 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d394617bc..d7585c884 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1354,10 +1354,12 @@ size_t ZSTD_CCtx_refPrefix_advanced( RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, "Can't ref a prefix when ctx not in init stage."); ZSTD_clearAllDicts(cctx); - if (prefix != NULL && prefixSize > 0) { + if (prefixSize > 0) { + RETURN_ERROR_IF(prefix == NULL, dictionary_wrong, "Invalid prefix pointer"); cctx->prefixDict.dict = prefix; cctx->prefixDict.dictSize = prefixSize; cctx->prefixDict.dictContentType = dictContentType; + cctx->prefixDict.loadMethod = ZSTD_dlm_byRef; } return 0; } @@ -3066,7 +3068,7 @@ ZSTD_entropyCompressSeqStore( /* ZSTD_selectBlockCompressor() : * Not static, but internal use only (used by long distance matcher) * assumption : strat is a valid strategy */ -ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode) +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_DictMode_e dictMode) { static const ZSTD_BlockCompressor_f blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { { ZSTD_compressBlock_fast /* default for 0 */, @@ -3298,7 +3300,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) } /* select and store sequences */ - { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms); + { ZSTD_DictMode_e const dictMode = ZSTD_matchState_dictMode(ms); size_t lastLLSize; { int i; for (i = 0; i < ZSTD_REP_NUM; ++i) @@ -6351,7 +6353,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, size_t inSize) { ZSTD_CCtx_params params = cctx->requestedParams; - ZSTD_prefixDict const prefixDict = cctx->prefixDict; + ZSTD_PrefixDict const prefixDict = cctx->prefixDict; FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ @@ -6407,7 +6409,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( cctx->mtctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, prefixDict.loadMethod, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0; cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ca5e2a4c5..f71c47e88 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -12,8 +12,8 @@ * that shall **only** be used by modules within lib/compress. */ -#ifndef ZSTD_COMPRESS_H -#define ZSTD_COMPRESS_H +#ifndef ZSTD_COMPRESS_INTERNAL_H +#define ZSTD_COMPRESS_INTERNAL_H /*-************************************* * Dependencies @@ -21,10 +21,10 @@ #include "../common/zstd_internal.h" #include "zstd_cwksp.h" #ifdef ZSTD_MULTITHREAD -# include "zstdmt_compress.h" +# include "zstdmt_compress.h" /* ZSTDMT_CCtx */ #endif #include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */ -#include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */ +#include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */ /*-************************************* * Constants @@ -46,11 +46,12 @@ typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e; typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage; -typedef struct ZSTD_prefixDict_s { +typedef struct { const void* dict; size_t dictSize; ZSTD_dictContentType_e dictContentType; -} ZSTD_prefixDict; + ZSTD_dictLoadMethod_e loadMethod; +} ZSTD_PrefixDict; typedef struct { void* dictBuffer; @@ -467,7 +468,7 @@ typedef struct { U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS]; ZSTD_entropyCTablesMetadata_t entropyMetadata; -} ZSTD_blockSplitCtx; +} ZSTD_BlockSplitCtx; struct ZSTD_CCtx_s { ZSTD_compressionStage_e stage; @@ -525,7 +526,7 @@ struct ZSTD_CCtx_s { /* Dictionary */ ZSTD_localDict localDict; const ZSTD_CDict* cdict; - ZSTD_prefixDict prefixDict; /* single-usage dictionary */ + ZSTD_PrefixDict prefixDict; /* single-usage dictionary */ /* Multi-threading */ #ifdef ZSTD_MULTITHREAD @@ -538,7 +539,7 @@ struct ZSTD_CCtx_s { #endif /* Workspace for block splitter */ - ZSTD_blockSplitCtx blockSplitCtx; + ZSTD_BlockSplitCtx blockSplitCtx; /* Buffer for output from external sequence producer */ ZSTD_Sequence* extSeqBuf; @@ -553,7 +554,7 @@ typedef enum { ZSTD_extDict = 1, ZSTD_dictMatchState = 2, ZSTD_dedicatedDictSearch = 3 -} ZSTD_dictMode_e; +} ZSTD_DictMode_e; typedef enum { ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict. @@ -578,7 +579,7 @@ typedef enum { typedef size_t (*ZSTD_BlockCompressor_f) ( ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_DictMode_e dictMode); MEM_STATIC U32 ZSTD_LLcode(U32 litLength) @@ -1068,7 +1069,7 @@ MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window) * Inspects the provided matchState and figures out what dictMode should be * passed to the compressor. */ -MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) +MEM_STATIC ZSTD_DictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) { return ZSTD_window_hasExtDict(ms->window) ? ZSTD_extDict : @@ -1633,4 +1634,4 @@ size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx, size_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -#endif /* ZSTD_COMPRESS_H */ +#endif /* ZSTD_COMPRESS_INTERNAL_H */ diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 272ebe0ec..1d5b37c20 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -74,7 +74,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 curr, const BYTE* inputEnd, U32 nbCompares, U32 btLow, - const ZSTD_dictMode_e dictMode) + const ZSTD_DictMode_e dictMode) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const bt = ms->chainTable; @@ -168,7 +168,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( size_t bestLength, U32 nbCompares, U32 const mls, - const ZSTD_dictMode_e dictMode) + const ZSTD_DictMode_e dictMode) { const ZSTD_MatchState_t * const dms = ms->dictMatchState; const ZSTD_compressionParameters* const dmsCParams = &dms->cParams; @@ -244,7 +244,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, size_t* offBasePtr, U32 const mls, - const ZSTD_dictMode_e dictMode) + const ZSTD_DictMode_e dictMode) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; @@ -396,7 +396,7 @@ size_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offBasePtr, const U32 mls /* template */, - const ZSTD_dictMode_e dictMode) + const ZSTD_DictMode_e dictMode) { DEBUGLOG(7, "ZSTD_BtFindBestMatch"); if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */ @@ -668,7 +668,7 @@ size_t ZSTD_HcFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offsetPtr, - const U32 mls, const ZSTD_dictMode_e dictMode) + const U32 mls, const ZSTD_DictMode_e dictMode) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const chainTable = ms->chainTable; @@ -1142,7 +1142,7 @@ size_t ZSTD_RowFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offsetPtr, - const U32 mls, const ZSTD_dictMode_e dictMode, + const U32 mls, const ZSTD_DictMode_e dictMode, const U32 rowLog) { U32* const hashTable = ms->hashTable; @@ -1492,7 +1492,7 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax( U32 const mls, U32 const rowLog, searchMethod_e const searchMethod, - ZSTD_dictMode_e const dictMode) + ZSTD_DictMode_e const dictMode) { if (dictMode == ZSTD_noDict) { ZSTD_SWITCH_SEARCH_METHOD(noDict) @@ -1518,7 +1518,7 @@ size_t ZSTD_compressBlock_lazy_generic( U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const searchMethod_e searchMethod, const U32 depth, - ZSTD_dictMode_e const dictMode) + ZSTD_DictMode_e const dictMode) { const BYTE* const istart = (const BYTE*)src; const BYTE* ip = istart; diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 3d7171b75..09de5a9d9 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -562,7 +562,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_updateTree_internal( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, - const U32 mls, const ZSTD_dictMode_e dictMode) + const U32 mls, const ZSTD_DictMode_e dictMode) { const BYTE* const base = ms->window.base; U32 const target = (U32)(ip - base); @@ -592,7 +592,7 @@ ZSTD_insertBtAndGetAllMatches ( ZSTD_MatchState_t* ms, U32* nextToUpdate3, const BYTE* const ip, const BYTE* const iLimit, - const ZSTD_dictMode_e dictMode, + const ZSTD_DictMode_e dictMode, const U32 rep[ZSTD_REP_NUM], const U32 ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */ const U32 lengthToBeat, @@ -838,7 +838,7 @@ U32 ZSTD_btGetAllMatches_internal( const U32 rep[ZSTD_REP_NUM], U32 const ll0, U32 const lengthToBeat, - const ZSTD_dictMode_e dictMode, + const ZSTD_DictMode_e dictMode, const U32 mls) { assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls); @@ -886,7 +886,7 @@ GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState) } static ZSTD_getAllMatchesFn -ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const dictMode) +ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_DictMode_e const dictMode) { ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = { ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict), @@ -1079,7 +1079,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const int optLevel, - const ZSTD_dictMode_e dictMode) + const ZSTD_DictMode_e dictMode) { optState_t* const optStatePtr = &ms->opt; const BYTE* const istart = (const BYTE*)src; @@ -1445,7 +1445,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt0( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) + const void* src, size_t srcSize, const ZSTD_DictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode); } @@ -1454,7 +1454,7 @@ static size_t ZSTD_compressBlock_opt0( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt2( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) + const void* src, size_t srcSize, const ZSTD_DictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode); } diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index dbaffe536..4de637513 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1232,7 +1232,7 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params) size_t ZSTDMT_initCStream_internal( ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_dictLoadMethod_e dictLoadMethod, const ZSTD_CDict* cdict, ZSTD_CCtx_params params, unsigned long long pledgedSrcSize) { @@ -1261,7 +1261,7 @@ size_t ZSTDMT_initCStream_internal( ZSTD_freeCDict(mtctx->cdictLocal); if (dict) { mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, - ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ + dictLoadMethod, dictContentType, /* note : a loadPrefix becomes an internal CDict */ params.cParams, mtctx->cMem); mtctx->cdict = mtctx->cdictLocal; if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index 91b489b9c..2158d614f 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -64,7 +64,7 @@ size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); * even if they are not needed for the current compression. * @return : 0, or an error code */ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_dictLoadMethod_e dictLoadMethod, const ZSTD_CDict* cdict, ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); From 7406d2b6eb91851db6a1cef10121de2a4c5a794a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 Jan 2025 20:57:21 -0800 Subject: [PATCH 371/405] skips the need to create a temporary cdict for --patch-from thus saving a bit of memory and a little bit of cpu time --- lib/compress/zstdmt_compress.c | 81 ++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 4de637513..210ff63fa 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -650,25 +650,25 @@ static void ZSTDMT_serialState_ensureFinished(SerialState* serialState, static const Range kNullRange = { NULL, 0 }; typedef struct { - size_t consumed; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */ - size_t cSize; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx, then set0 by mtctx */ - ZSTD_pthread_mutex_t job_mutex; /* Thread-safe - used by mtctx and worker */ - ZSTD_pthread_cond_t job_cond; /* Thread-safe - used by mtctx and worker */ - ZSTDMT_CCtxPool* cctxPool; /* Thread-safe - used by mtctx and (all) workers */ - ZSTDMT_bufferPool* bufPool; /* Thread-safe - used by mtctx and (all) workers */ - ZSTDMT_seqPool* seqPool; /* Thread-safe - used by mtctx and (all) workers */ + size_t consumed; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */ + size_t cSize; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx, then set0 by mtctx */ + ZSTD_pthread_mutex_t job_mutex; /* Thread-safe - used by mtctx and worker */ + ZSTD_pthread_cond_t job_cond; /* Thread-safe - used by mtctx and worker */ + ZSTDMT_CCtxPool* cctxPool; /* Thread-safe - used by mtctx and (all) workers */ + ZSTDMT_bufferPool* bufPool; /* Thread-safe - used by mtctx and (all) workers */ + ZSTDMT_seqPool* seqPool; /* Thread-safe - used by mtctx and (all) workers */ SerialState* serial; /* Thread-safe - used by mtctx and (all) workers */ Buffer dstBuff; /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */ Range prefix; /* set by mtctx, then read by worker & mtctx => no barrier */ Range src; /* set by mtctx, then read by worker & mtctx => no barrier */ - unsigned jobID; /* set by mtctx, then read by worker => no barrier */ - unsigned firstJob; /* set by mtctx, then read by worker => no barrier */ - unsigned lastJob; /* set by mtctx, then read by worker => no barrier */ - ZSTD_CCtx_params params; /* set by mtctx, then read by worker => no barrier */ - const ZSTD_CDict* cdict; /* set by mtctx, then read by worker => no barrier */ - unsigned long long fullFrameSize; /* set by mtctx, then read by worker => no barrier */ - size_t dstFlushed; /* used only by mtctx */ - unsigned frameChecksumNeeded; /* used only by mtctx */ + unsigned jobID; /* set by mtctx, then read by worker => no barrier */ + unsigned firstJob; /* set by mtctx, then read by worker => no barrier */ + unsigned lastJob; /* set by mtctx, then read by worker => no barrier */ + ZSTD_CCtx_params params; /* set by mtctx, then read by worker => no barrier */ + const ZSTD_CDict* cdict; /* set by mtctx, then read by worker => no barrier */ + unsigned long long fullFrameSize; /* set by mtctx, then read by worker => no barrier */ + size_t dstFlushed; /* used only by mtctx */ + unsigned frameChecksumNeeded; /* used only by mtctx */ } ZSTDMT_jobDescription; #define JOB_ERROR(e) \ @@ -714,7 +714,7 @@ static void ZSTDMT_compressionJob(void* jobDescription) size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, &jobParams, job->fullFrameSize); assert(job->firstJob); /* only allowed for first job */ if (ZSTD_isError(initError)) JOB_ERROR(initError); - } else { /* srcStart points at reloaded section */ + } else { U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size; { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob); if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError); @@ -741,7 +741,7 @@ static void ZSTDMT_compressionJob(void* jobDescription) ZSTD_invalidateRepCodes(cctx); } - /* compress */ + /* compress the entire job by smaller chunks, for better granularity */ { size_t const chunkSize = 4*ZSTD_BLOCKSIZE_MAX; int const nbChunks = (int)((job->src.size + (chunkSize-1)) / chunkSize); const BYTE* ip = (const BYTE*) job->src.start; @@ -1258,18 +1258,6 @@ size_t ZSTDMT_initCStream_internal( mtctx->params = params; mtctx->frameContentSize = pledgedSrcSize; - ZSTD_freeCDict(mtctx->cdictLocal); - if (dict) { - mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, - dictLoadMethod, dictContentType, /* note : a loadPrefix becomes an internal CDict */ - params.cParams, mtctx->cMem); - mtctx->cdict = mtctx->cdictLocal; - if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); - } else { - mtctx->cdictLocal = NULL; - mtctx->cdict = cdict; - } - mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(¶ms); DEBUGLOG(4, "overlapLog=%i => %u KB", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10)); mtctx->targetSectionSize = params.jobSize; @@ -1331,9 +1319,31 @@ size_t ZSTDMT_initCStream_internal( mtctx->allJobsCompleted = 0; mtctx->consumed = 0; mtctx->produced = 0; + + /* update dictionary */ + ZSTD_freeCDict(mtctx->cdictLocal); + mtctx->cdictLocal = NULL; + if (dict) { + if (dictContentType == ZSTD_dct_rawContent) { + mtctx->inBuff.prefix.start = (const BYTE*)dict; + mtctx->inBuff.prefix.size = dictSize; + } else { + /* note : a loadPrefix becomes an internal CDict */ + mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, + dictLoadMethod, dictContentType, + params.cParams, mtctx->cMem); + mtctx->cdict = mtctx->cdictLocal; + if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); + } + } else { + mtctx->cdict = cdict; + } + if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize, dict, dictSize, dictContentType)) return ERROR(memory_allocation); + + return 0; } @@ -1543,6 +1553,11 @@ static Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx) unsigned const lastJobID = mtctx->nextJobID; unsigned jobID; + /* no need to check during first round */ + size_t roundBuffCapacity = mtctx->roundBuff.capacity; + size_t nbJobs1stRoundMin = roundBuffCapacity / mtctx->targetSectionSize; + if (lastJobID < nbJobs1stRoundMin) return kNullRange; + for (jobID = firstJobID; jobID < lastJobID; ++jobID) { unsigned const wJobID = jobID & mtctx->jobIDMask; size_t consumed; @@ -1637,14 +1652,14 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) { Range const inUse = ZSTDMT_getInputDataInUse(mtctx); size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos; - size_t const target = mtctx->targetSectionSize; + size_t const spaceNeeded = mtctx->targetSectionSize; Buffer buffer; DEBUGLOG(5, "ZSTDMT_tryGetInputRange"); assert(mtctx->inBuff.buffer.start == NULL); - assert(mtctx->roundBuff.capacity >= target); + assert(mtctx->roundBuff.capacity >= spaceNeeded); - if (spaceLeft < target) { + if (spaceLeft < spaceNeeded) { /* ZSTD_invalidateRepCodes() doesn't work for extDict variants. * Simply copy the prefix to the beginning in that case. */ @@ -1663,7 +1678,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) mtctx->roundBuff.pos = prefixSize; } buffer.start = mtctx->roundBuff.buffer + mtctx->roundBuff.pos; - buffer.capacity = target; + buffer.capacity = spaceNeeded; if (ZSTDMT_isOverlapped(buffer, inUse)) { DEBUGLOG(5, "Waiting for buffer..."); From f11bd19c7f7899840585a260688e969eb705a008 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 1 Feb 2025 00:55:52 -0800 Subject: [PATCH 372/405] ensure cdict is properly reset to NULL --- .github/workflows/dev-long-tests.yml | 4 ++-- lib/compress/zstdmt_compress.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index 0adfed914..899a57b75 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -67,11 +67,11 @@ jobs: - name: thread sanitizer zstreamtest run: CC=clang ZSTREAM_TESTTIME=-T3mn make tsan-test-zstream - ubsan-zstreamtest: + uasan-zstreamtest: runs-on: ubuntu-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: undefined behavior sanitizer zstreamtest + - name: ub + address sanitizer on zstreamtest run: CC=clang make uasan-test-zstream # lasts ~15mn diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 210ff63fa..1840ad855 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1323,6 +1323,7 @@ size_t ZSTDMT_initCStream_internal( /* update dictionary */ ZSTD_freeCDict(mtctx->cdictLocal); mtctx->cdictLocal = NULL; + mtctx->cdict = NULL; if (dict) { if (dictContentType == ZSTD_dct_rawContent) { mtctx->inBuff.prefix.start = (const BYTE*)dict; From c7cd7dc04bede050475da32fa019c2d0712ed6cf Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 1 Feb 2025 00:41:36 -0800 Subject: [PATCH 373/405] better MT fluidity --patch-from no longer blocked on first job dictionary loading --- lib/compress/zstd_compress.c | 4 ++-- lib/compress/zstdmt_compress.c | 40 ++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d7585c884..c560c902a 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4900,7 +4900,7 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const /*! ZSTD_loadDictionaryContent() : * @return : 0, or an error code */ -static size_t +static size_t ZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms, ldmState_t* ls, ZSTD_cwksp* ws, @@ -5603,7 +5603,7 @@ static size_t ZSTD_initCDict_internal( return 0; } -static ZSTD_CDict* +static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_compressionParameters cParams, diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 1840ad855..8725b9071 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -577,9 +577,10 @@ static void ZSTDMT_serialState_free(SerialState* serialState) ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); } -static void ZSTDMT_serialState_update(SerialState* serialState, - ZSTD_CCtx* jobCCtx, RawSeqStore_t seqStore, - Range src, unsigned jobID) +static void +ZSTDMT_serialState_genSequences(SerialState* serialState, + RawSeqStore_t* seqStore, + Range src, unsigned jobID) { /* Wait for our turn */ ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex); @@ -592,12 +593,13 @@ static void ZSTDMT_serialState_update(SerialState* serialState, /* It is now our turn, do any processing necessary */ if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) { size_t error; - assert(seqStore.seq != NULL && seqStore.pos == 0 && - seqStore.size == 0 && seqStore.capacity > 0); + DEBUGLOG(6, "ZSTDMT_serialState_genSequences: LDM update"); + assert(seqStore->seq != NULL && seqStore->pos == 0 && + seqStore->size == 0 && seqStore->capacity > 0); assert(src.size <= serialState->params.jobSize); ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0); error = ZSTD_ldm_generateSequences( - &serialState->ldmState, &seqStore, + &serialState->ldmState, seqStore, &serialState->params.ldmParams, src.start, src.size); /* We provide a large enough buffer to never fail. */ assert(!ZSTD_isError(error)); (void)error; @@ -616,10 +618,18 @@ static void ZSTDMT_serialState_update(SerialState* serialState, serialState->nextJobID++; ZSTD_pthread_cond_broadcast(&serialState->cond); ZSTD_pthread_mutex_unlock(&serialState->mutex); +} - if (seqStore.size > 0) { - ZSTD_referenceExternalSequences(jobCCtx, seqStore.seq, seqStore.size); - assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable); +static void +ZSTDMT_serialState_applySequences(const SerialState* serialState, /* just for an assert() check */ + ZSTD_CCtx* jobCCtx, + const RawSeqStore_t* seqStore) +{ + if (seqStore->size > 0) { + DEBUGLOG(5, "ZSTDMT_serialState_applySequences: uploading %u external sequences", (unsigned)seqStore->size); + assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable); (void)serialState; + assert(jobCCtx); + ZSTD_referenceExternalSequences(jobCCtx, seqStore->seq, seqStore->size); } } @@ -689,6 +699,7 @@ static void ZSTDMT_compressionJob(void* jobDescription) Buffer dstBuff = job->dstBuff; size_t lastCBlockSize = 0; + DEBUGLOG(5, "ZSTDMT_compressionJob: job %u", job->jobID); /* resources */ if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation)); if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */ @@ -710,6 +721,10 @@ static void ZSTDMT_compressionJob(void* jobDescription) /* init */ + + /* Perform serial step as early as possible */ + ZSTDMT_serialState_genSequences(job->serial, &rawSeqStore, job->src, job->jobID); + if (job->cdict) { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, &jobParams, job->fullFrameSize); assert(job->firstJob); /* only allowed for first job */ @@ -723,16 +738,17 @@ static void ZSTDMT_compressionJob(void* jobDescription) size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0); if (ZSTD_isError(err)) JOB_ERROR(err); } + DEBUGLOG(6, "ZSTDMT_compressionJob: job %u: loading prefix of size %zu", job->jobID, job->prefix.size); { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, - job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */ + job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, ZSTD_dtlm_fast, NULL, /*cdict*/ &jobParams, pledgedSrcSize); if (ZSTD_isError(initError)) JOB_ERROR(initError); } } - /* Perform serial step as early as possible, but after CCtx initialization */ - ZSTDMT_serialState_update(job->serial, cctx, rawSeqStore, job->src, job->jobID); + /* External Sequences can only be applied after CCtx initialization */ + ZSTDMT_serialState_applySequences(job->serial, cctx, &rawSeqStore); if (!job->firstJob) { /* flush and overwrite frame header when it's not first job */ size_t const hSize = ZSTD_compressContinue_public(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0); From 23e5f80390db9a3a65485933d255e163d2dab519 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 5 Feb 2025 18:47:26 -0800 Subject: [PATCH 374/405] Revert "pass dictionary loading method as parameter" This reverts commit 821fc567f93a415e9fbe856271ccd452ee7acf07. --- lib/compress/zstd_compress.c | 12 +++++------- lib/compress/zstd_compress_internal.h | 27 +++++++++++++-------------- lib/compress/zstd_lazy.c | 16 ++++++++-------- lib/compress/zstd_opt.c | 14 +++++++------- lib/compress/zstdmt_compress.c | 16 ++++++++++++++-- lib/compress/zstdmt_compress.h | 2 +- 6 files changed, 48 insertions(+), 39 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index c560c902a..d928b1d3e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1354,12 +1354,10 @@ size_t ZSTD_CCtx_refPrefix_advanced( RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, "Can't ref a prefix when ctx not in init stage."); ZSTD_clearAllDicts(cctx); - if (prefixSize > 0) { - RETURN_ERROR_IF(prefix == NULL, dictionary_wrong, "Invalid prefix pointer"); + if (prefix != NULL && prefixSize > 0) { cctx->prefixDict.dict = prefix; cctx->prefixDict.dictSize = prefixSize; cctx->prefixDict.dictContentType = dictContentType; - cctx->prefixDict.loadMethod = ZSTD_dlm_byRef; } return 0; } @@ -3068,7 +3066,7 @@ ZSTD_entropyCompressSeqStore( /* ZSTD_selectBlockCompressor() : * Not static, but internal use only (used by long distance matcher) * assumption : strat is a valid strategy */ -ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_DictMode_e dictMode) +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode) { static const ZSTD_BlockCompressor_f blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { { ZSTD_compressBlock_fast /* default for 0 */, @@ -3300,7 +3298,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) } /* select and store sequences */ - { ZSTD_DictMode_e const dictMode = ZSTD_matchState_dictMode(ms); + { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms); size_t lastLLSize; { int i; for (i = 0; i < ZSTD_REP_NUM; ++i) @@ -6353,7 +6351,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, size_t inSize) { ZSTD_CCtx_params params = cctx->requestedParams; - ZSTD_PrefixDict const prefixDict = cctx->prefixDict; + ZSTD_prefixDict const prefixDict = cctx->prefixDict; FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ @@ -6409,7 +6407,7 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( cctx->mtctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, prefixDict.loadMethod, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0; cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index f71c47e88..ca5e2a4c5 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -12,8 +12,8 @@ * that shall **only** be used by modules within lib/compress. */ -#ifndef ZSTD_COMPRESS_INTERNAL_H -#define ZSTD_COMPRESS_INTERNAL_H +#ifndef ZSTD_COMPRESS_H +#define ZSTD_COMPRESS_H /*-************************************* * Dependencies @@ -21,10 +21,10 @@ #include "../common/zstd_internal.h" #include "zstd_cwksp.h" #ifdef ZSTD_MULTITHREAD -# include "zstdmt_compress.h" /* ZSTDMT_CCtx */ +# include "zstdmt_compress.h" #endif #include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */ -#include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */ +#include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */ /*-************************************* * Constants @@ -46,12 +46,11 @@ typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e; typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage; -typedef struct { +typedef struct ZSTD_prefixDict_s { const void* dict; size_t dictSize; ZSTD_dictContentType_e dictContentType; - ZSTD_dictLoadMethod_e loadMethod; -} ZSTD_PrefixDict; +} ZSTD_prefixDict; typedef struct { void* dictBuffer; @@ -468,7 +467,7 @@ typedef struct { U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS]; ZSTD_entropyCTablesMetadata_t entropyMetadata; -} ZSTD_BlockSplitCtx; +} ZSTD_blockSplitCtx; struct ZSTD_CCtx_s { ZSTD_compressionStage_e stage; @@ -526,7 +525,7 @@ struct ZSTD_CCtx_s { /* Dictionary */ ZSTD_localDict localDict; const ZSTD_CDict* cdict; - ZSTD_PrefixDict prefixDict; /* single-usage dictionary */ + ZSTD_prefixDict prefixDict; /* single-usage dictionary */ /* Multi-threading */ #ifdef ZSTD_MULTITHREAD @@ -539,7 +538,7 @@ struct ZSTD_CCtx_s { #endif /* Workspace for block splitter */ - ZSTD_BlockSplitCtx blockSplitCtx; + ZSTD_blockSplitCtx blockSplitCtx; /* Buffer for output from external sequence producer */ ZSTD_Sequence* extSeqBuf; @@ -554,7 +553,7 @@ typedef enum { ZSTD_extDict = 1, ZSTD_dictMatchState = 2, ZSTD_dedicatedDictSearch = 3 -} ZSTD_DictMode_e; +} ZSTD_dictMode_e; typedef enum { ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict. @@ -579,7 +578,7 @@ typedef enum { typedef size_t (*ZSTD_BlockCompressor_f) ( ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_DictMode_e dictMode); +ZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); MEM_STATIC U32 ZSTD_LLcode(U32 litLength) @@ -1069,7 +1068,7 @@ MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window) * Inspects the provided matchState and figures out what dictMode should be * passed to the compressor. */ -MEM_STATIC ZSTD_DictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) +MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms) { return ZSTD_window_hasExtDict(ms->window) ? ZSTD_extDict : @@ -1634,4 +1633,4 @@ size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx, size_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -#endif /* ZSTD_COMPRESS_INTERNAL_H */ +#endif /* ZSTD_COMPRESS_H */ diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 1d5b37c20..272ebe0ec 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -74,7 +74,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms, U32 curr, const BYTE* inputEnd, U32 nbCompares, U32 btLow, - const ZSTD_DictMode_e dictMode) + const ZSTD_dictMode_e dictMode) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const bt = ms->chainTable; @@ -168,7 +168,7 @@ size_t ZSTD_DUBT_findBetterDictMatch ( size_t bestLength, U32 nbCompares, U32 const mls, - const ZSTD_DictMode_e dictMode) + const ZSTD_dictMode_e dictMode) { const ZSTD_MatchState_t * const dms = ms->dictMatchState; const ZSTD_compressionParameters* const dmsCParams = &dms->cParams; @@ -244,7 +244,7 @@ size_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, size_t* offBasePtr, U32 const mls, - const ZSTD_DictMode_e dictMode) + const ZSTD_dictMode_e dictMode) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; @@ -396,7 +396,7 @@ size_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offBasePtr, const U32 mls /* template */, - const ZSTD_DictMode_e dictMode) + const ZSTD_dictMode_e dictMode) { DEBUGLOG(7, "ZSTD_BtFindBestMatch"); if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */ @@ -668,7 +668,7 @@ size_t ZSTD_HcFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offsetPtr, - const U32 mls, const ZSTD_DictMode_e dictMode) + const U32 mls, const ZSTD_dictMode_e dictMode) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const chainTable = ms->chainTable; @@ -1142,7 +1142,7 @@ size_t ZSTD_RowFindBestMatch( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, size_t* offsetPtr, - const U32 mls, const ZSTD_DictMode_e dictMode, + const U32 mls, const ZSTD_dictMode_e dictMode, const U32 rowLog) { U32* const hashTable = ms->hashTable; @@ -1492,7 +1492,7 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax( U32 const mls, U32 const rowLog, searchMethod_e const searchMethod, - ZSTD_DictMode_e const dictMode) + ZSTD_dictMode_e const dictMode) { if (dictMode == ZSTD_noDict) { ZSTD_SWITCH_SEARCH_METHOD(noDict) @@ -1518,7 +1518,7 @@ size_t ZSTD_compressBlock_lazy_generic( U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const searchMethod_e searchMethod, const U32 depth, - ZSTD_DictMode_e const dictMode) + ZSTD_dictMode_e const dictMode) { const BYTE* const istart = (const BYTE*)src; const BYTE* ip = istart; diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 09de5a9d9..3d7171b75 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -562,7 +562,7 @@ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_updateTree_internal( ZSTD_MatchState_t* ms, const BYTE* const ip, const BYTE* const iend, - const U32 mls, const ZSTD_DictMode_e dictMode) + const U32 mls, const ZSTD_dictMode_e dictMode) { const BYTE* const base = ms->window.base; U32 const target = (U32)(ip - base); @@ -592,7 +592,7 @@ ZSTD_insertBtAndGetAllMatches ( ZSTD_MatchState_t* ms, U32* nextToUpdate3, const BYTE* const ip, const BYTE* const iLimit, - const ZSTD_DictMode_e dictMode, + const ZSTD_dictMode_e dictMode, const U32 rep[ZSTD_REP_NUM], const U32 ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */ const U32 lengthToBeat, @@ -838,7 +838,7 @@ U32 ZSTD_btGetAllMatches_internal( const U32 rep[ZSTD_REP_NUM], U32 const ll0, U32 const lengthToBeat, - const ZSTD_DictMode_e dictMode, + const ZSTD_dictMode_e dictMode, const U32 mls) { assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls); @@ -886,7 +886,7 @@ GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState) } static ZSTD_getAllMatchesFn -ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_DictMode_e const dictMode) +ZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const dictMode) { ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = { ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict), @@ -1079,7 +1079,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize, const int optLevel, - const ZSTD_DictMode_e dictMode) + const ZSTD_dictMode_e dictMode) { optState_t* const optStatePtr = &ms->opt; const BYTE* const istart = (const BYTE*)src; @@ -1445,7 +1445,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ #ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt0( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize, const ZSTD_DictMode_e dictMode) + const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode); } @@ -1454,7 +1454,7 @@ static size_t ZSTD_compressBlock_opt0( #ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR static size_t ZSTD_compressBlock_opt2( ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize, const ZSTD_DictMode_e dictMode) + const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) { return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode); } diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 8725b9071..0f1fe6d74 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1248,7 +1248,7 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params) size_t ZSTDMT_initCStream_internal( ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_dictLoadMethod_e dictLoadMethod, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, const ZSTD_CDict* cdict, ZSTD_CCtx_params params, unsigned long long pledgedSrcSize) { @@ -1274,6 +1274,18 @@ size_t ZSTDMT_initCStream_internal( mtctx->params = params; mtctx->frameContentSize = pledgedSrcSize; + ZSTD_freeCDict(mtctx->cdictLocal); + if (dict) { + mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ + params.cParams, mtctx->cMem); + mtctx->cdict = mtctx->cdictLocal; + if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); + } else { + mtctx->cdictLocal = NULL; + mtctx->cdict = cdict; + } + mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(¶ms); DEBUGLOG(4, "overlapLog=%i => %u KB", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10)); mtctx->targetSectionSize = params.jobSize; @@ -1347,7 +1359,7 @@ size_t ZSTDMT_initCStream_internal( } else { /* note : a loadPrefix becomes an internal CDict */ mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, - dictLoadMethod, dictContentType, + ZSTD_dlm_byRef, dictContentType, params.cParams, mtctx->cMem); mtctx->cdict = mtctx->cdictLocal; if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index 2158d614f..91b489b9c 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -64,7 +64,7 @@ size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); * even if they are not needed for the current compression. * @return : 0, or an error code */ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_dictLoadMethod_e dictLoadMethod, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, const ZSTD_CDict* cdict, ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); From aebffd66ec43a721b9d07e67e18f353bf2082430 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 8 Feb 2025 22:47:05 -0800 Subject: [PATCH 375/405] --ultra automatically triggered with --long and --patch-from the purpose of --ultra is to make the user explicitly opt-in to generate very large window size (> 8 MB). The agreement to generate very large window size is already implicit when selecting --long or --patch-from. Consequently, `--ultra ` is automatically enabled when `--long` or `--patch-from` is set. --- programs/zstdcli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 7d00a94b2..8569896c0 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1082,10 +1082,11 @@ int main(int argCount, const char* argv[]) #ifndef ZSTD_NOTRACE if (longCommandWArg(&argument, "--trace")) { char const* traceFile; NEXT_FIELD(traceFile); TRACE_enable(traceFile); continue; } #endif - if (longCommandWArg(&argument, "--patch-from")) { NEXT_FIELD(patchFromDictFileName); continue; } + if (longCommandWArg(&argument, "--patch-from")) { NEXT_FIELD(patchFromDictFileName); ultra = 1; continue; } if (longCommandWArg(&argument, "--long")) { unsigned ldmWindowLog = 0; ldmFlag = 1; + ultra = 1; /* Parse optional window log */ if (*argument == '=') { ++argument; From 630b47a158cc22002045494c7e0dc0f0672c2fca Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 11:38:44 -0800 Subject: [PATCH 376/405] added a new --max command set parameters to maximum compression (even more than -22) --- programs/zstdcli.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 7d00a94b2..0bb384b20 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -639,6 +639,22 @@ static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressi return 1; } +static void setMaxCompression(ZSTD_compressionParameters* params) +{ + params->windowLog = ZSTD_WINDOWLOG_MAX; + params->chainLog = ZSTD_CHAINLOG_MAX; + params->hashLog = ZSTD_HASHLOG_MAX; + params->searchLog = ZSTD_SEARCHLOG_MAX; + params->minMatch = ZSTD_MINMATCH_MIN; + params->targetLength = ZSTD_TARGETLENGTH_MAX; + params->strategy = ZSTD_STRATEGY_MAX; + g_overlapLog = ZSTD_OVERLAPLOG_MAX; + g_ldmHashLog = ZSTD_LDM_HASHLOG_MAX; + g_ldmHashRateLog = 0; /* automatically derived */ + g_ldmMinMatch = 32; /* heuristic */ + g_ldmBucketSizeLog = ZSTD_LDM_BUCKETSIZELOG_MAX; +} + static void printVersion(void) { if (g_displayLevel < DISPLAY_LEVEL_DEFAULT) { @@ -957,6 +973,7 @@ int main(int argCount, const char* argv[]) if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; } if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; continue; } if (!strcmp(argument, "--ultra")) { ultra=1; continue; } + if (!strcmp(argument, "--max")) { ultra=1; ldmFlag = 1; setMaxCompression(&compressionParams); continue; } if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; } if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; } if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(prefs, 2); continue; } From 8ae1330708b42c7f5751e94e02970e7ccb5d9731 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 11:51:25 -0800 Subject: [PATCH 377/405] add man entry for --max --- programs/zstd.1.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index b4e848640..184db049f 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -161,6 +161,9 @@ the last one takes effect. Note: If `windowLog` is set to larger than 27, `--long=windowLog` or `--memory=windowSize` needs to be passed to the decompressor. +* `--max`: + set advanced parameters to maximum compression. + warning: this setting uses a lot of resources and is very slow. * `-D DICT`: use `DICT` as Dictionary to compress or decompress FILE(s) * `--patch-from FILE`: From 41b719375778ca92978f406b44bdea06cffbf108 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 12:26:36 -0800 Subject: [PATCH 378/405] added --max to test suite --- tests/cli-tests/compression/levels.sh | 4 +++- tests/cli-tests/compression/levels.sh.stderr.exact | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/cli-tests/compression/levels.sh b/tests/cli-tests/compression/levels.sh index cc2700a30..db3baba6d 100755 --- a/tests/cli-tests/compression/levels.sh +++ b/tests/cli-tests/compression/levels.sh @@ -10,9 +10,11 @@ zstd --fast=10 file -o file-f10.zst -q zstd --fast=1 file -o file-f1.zst -q zstd -1 file -o file-1.zst -q zstd -19 file -o file-19.zst -q +zstd --max file -o file-max.zst -q -zstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst +zstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst file-max.zst +cmp_size -le file-max.zst file-19.zst cmp_size -lt file-19.zst file-1.zst cmp_size -lt file-1.zst file-f1.zst cmp_size -lt file-f1.zst file-f10.zst diff --git a/tests/cli-tests/compression/levels.sh.stderr.exact b/tests/cli-tests/compression/levels.sh.stderr.exact index c8fb79c68..ddec06467 100644 --- a/tests/cli-tests/compression/levels.sh.stderr.exact +++ b/tests/cli-tests/compression/levels.sh.stderr.exact @@ -6,10 +6,12 @@ zstd --fast=10 file -o file-f10.zst -q zstd --fast=1 file -o file-f1.zst -q zstd -1 file -o file-1.zst -q zstd -19 file -o file-19.zst -q +zstd --max file -o file-max.zst -q -zstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst -4 files decompressed : 262148 bytes total +zstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst file-max.zst +5 files decompressed : 327685 bytes total +cmp_size -le file-max.zst file-19.zst cmp_size -lt file-19.zst file-1.zst cmp_size -lt file-1.zst file-f1.zst cmp_size -lt file-f1.zst file-f10.zst From 39d1d82fa80bfbec6d894ccf8bf18137cedad5d6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 17:24:12 -0800 Subject: [PATCH 379/405] adjusted mml heuristic --- programs/zstdcli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 0bb384b20..b69d6bf99 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -651,7 +651,7 @@ static void setMaxCompression(ZSTD_compressionParameters* params) g_overlapLog = ZSTD_OVERLAPLOG_MAX; g_ldmHashLog = ZSTD_LDM_HASHLOG_MAX; g_ldmHashRateLog = 0; /* automatically derived */ - g_ldmMinMatch = 32; /* heuristic */ + g_ldmMinMatch = 16; /* heuristic */ g_ldmBucketSizeLog = ZSTD_LDM_BUCKETSIZELOG_MAX; } From f86024ccd2b2fc4608be336594e073096405ac13 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 17:25:35 -0800 Subject: [PATCH 380/405] reinforce man page warning 32-bit is unsuitable for --max --- programs/zstd.1.md | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 184db049f..f56110100 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -164,6 +164,7 @@ the last one takes effect. * `--max`: set advanced parameters to maximum compression. warning: this setting uses a lot of resources and is very slow. + note that the amount of resource required is typically too large for 32-bit. * `-D DICT`: use `DICT` as Dictionary to compress or decompress FILE(s) * `--patch-from FILE`: From 7a2fce5a1fabcd28cc8c8ea5ef039dab32b24f0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 05:36:44 +0000 Subject: [PATCH 381/405] Bump github/codeql-action from 3.28.1 to 3.28.9 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.1 to 3.28.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b6a472f63d85b9c78a3ac5e89422239fc15e9b3c...9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index c489ddc91..e532b03bf 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # tag=v3.28.1 + uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # tag=v3.28.9 with: sarif_file: results.sarif From 1603cbe83ef7140f0cd0412bea50e5bfc9dd6d1c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 23:02:14 -0800 Subject: [PATCH 382/405] update test for 32-bit mode --max doesn't work in 32-bit mode, due to address space limitation --- tests/cli-tests/compression/levels.sh | 10 +++++++++- tests/cli-tests/compression/levels.sh.stderr.exact | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/cli-tests/compression/levels.sh b/tests/cli-tests/compression/levels.sh index db3baba6d..8da3b4e74 100755 --- a/tests/cli-tests/compression/levels.sh +++ b/tests/cli-tests/compression/levels.sh @@ -5,12 +5,20 @@ set -v datagen > file +# Retrieve the program's version information +version_info=$(zstd -V) + # Compress with various levels and ensure that their sizes are ordered zstd --fast=10 file -o file-f10.zst -q zstd --fast=1 file -o file-f1.zst -q zstd -1 file -o file-1.zst -q zstd -19 file -o file-19.zst -q -zstd --max file -o file-max.zst -q +if echo "$version_info" | grep -q '32-bit'; then + # skip --max test: not enough address space + cp file-19.zst file-max.zst +else + zstd --max file -o file-max.zst -q +fi zstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst file-max.zst diff --git a/tests/cli-tests/compression/levels.sh.stderr.exact b/tests/cli-tests/compression/levels.sh.stderr.exact index ddec06467..dff9784dd 100644 --- a/tests/cli-tests/compression/levels.sh.stderr.exact +++ b/tests/cli-tests/compression/levels.sh.stderr.exact @@ -1,12 +1,20 @@ datagen > file +# Retrieve the program's version information +version_info=$(zstd -V) + # Compress with various levels and ensure that their sizes are ordered zstd --fast=10 file -o file-f10.zst -q zstd --fast=1 file -o file-f1.zst -q zstd -1 file -o file-1.zst -q zstd -19 file -o file-19.zst -q -zstd --max file -o file-max.zst -q +if echo "$version_info" | grep -q '32-bit'; then + # skip --max test: not enough address space + cp file-19.zst file-max.zst +else + zstd --max file -o file-max.zst -q +fi zstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst file-max.zst 5 files decompressed : 327685 bytes total From 468e1453a55d119c914843bff73af809cbe4ba79 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 23:14:16 -0800 Subject: [PATCH 383/405] disable --max in 32-bit mode --- programs/zstd.1.md | 4 ++-- programs/zstdcli.c | 31 ++++++++++++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index f56110100..29b7a5bb7 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -163,8 +163,8 @@ the last one takes effect. `--memory=windowSize` needs to be passed to the decompressor. * `--max`: set advanced parameters to maximum compression. - warning: this setting uses a lot of resources and is very slow. - note that the amount of resource required is typically too large for 32-bit. + warning: this setting is very slow and uses a lot of resources. + It's inappropriate for 32-bit mode and therefore disabled in this mode. * `-D DICT`: use `DICT` as Dictionary to compress or decompress FILE(s) * `--patch-from FILE`: diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b69d6bf99..feab4f944 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -810,22 +810,22 @@ static unsigned default_nbThreads(void) { CLEAN_RETURN(1); \ } } } -#define NEXT_UINT32(val32) { \ - const char* __nb; \ - NEXT_FIELD(__nb); \ +#define NEXT_UINT32(val32) { \ + const char* __nb; \ + NEXT_FIELD(__nb); \ val32 = readU32FromChar(&__nb); \ - if(*__nb != 0) { \ + if(*__nb != 0) { \ errorOut("error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB are allowed"); \ - } \ + } \ } -#define NEXT_TSIZE(valTsize) { \ - const char* __nb; \ - NEXT_FIELD(__nb); \ +#define NEXT_TSIZE(valTsize) { \ + const char* __nb; \ + NEXT_FIELD(__nb); \ valTsize = readSizeTFromChar(&__nb); \ - if(*__nb != 0) { \ + if(*__nb != 0) { \ errorOut("error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB are allowed"); \ - } \ + } \ } typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode; @@ -973,7 +973,6 @@ int main(int argCount, const char* argv[]) if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; } if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; continue; } if (!strcmp(argument, "--ultra")) { ultra=1; continue; } - if (!strcmp(argument, "--max")) { ultra=1; ldmFlag = 1; setMaxCompression(&compressionParams); continue; } if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; } if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; } if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(prefs, 2); continue; } @@ -1024,6 +1023,16 @@ int main(int argCount, const char* argv[]) if (!strcmp(argument, "--fake-stderr-is-console")) { UTIL_fakeStderrIsConsole(); continue; } if (!strcmp(argument, "--trace-file-stat")) { UTIL_traceFileStat(); continue; } + if (!strcmp(argument, "--max")) { + if (sizeof(void*)==4) { + DISPLAYLEVEL(2, "--max is incompatible with 32-bit mode \n"); + badUsage(programName, originalArgument); + CLEAN_RETURN(1); + } + ultra=1; ldmFlag = 1; setMaxCompression(&compressionParams); + continue; + } + /* long commands with arguments */ #ifndef ZSTD_NODICT if (longCommandWArg(&argument, "--train-cover")) { From 613901b6d3ea198ac051f63e16c6ea9cd088a6e4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 23:41:32 -0800 Subject: [PATCH 384/405] modifies command echoing for macos / linux compatibility --- tests/cli-tests/compression/levels.sh | 3 +++ tests/cli-tests/compression/levels.sh.stderr.exact | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/cli-tests/compression/levels.sh b/tests/cli-tests/compression/levels.sh index 8da3b4e74..b8230f2a3 100755 --- a/tests/cli-tests/compression/levels.sh +++ b/tests/cli-tests/compression/levels.sh @@ -6,7 +6,10 @@ set -v datagen > file # Retrieve the program's version information +# Note: command echoing differs between macos and linux, so it's disabled below +set +v version_info=$(zstd -V) +set -v # Compress with various levels and ensure that their sizes are ordered zstd --fast=10 file -o file-f10.zst -q diff --git a/tests/cli-tests/compression/levels.sh.stderr.exact b/tests/cli-tests/compression/levels.sh.stderr.exact index dff9784dd..fd7c076d2 100644 --- a/tests/cli-tests/compression/levels.sh.stderr.exact +++ b/tests/cli-tests/compression/levels.sh.stderr.exact @@ -2,7 +2,8 @@ datagen > file # Retrieve the program's version information -version_info=$(zstd -V) +# Note: command echoing differs between macos and linux, so it's disabled below +set +v # Compress with various levels and ensure that their sizes are ordered zstd --fast=10 file -o file-f10.zst -q From 4609a40b89b94cc61cc6a6a833725d6f89bf9de6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 7 Feb 2025 15:58:42 -0800 Subject: [PATCH 385/405] dynamically adjust hratelog and ldmml based on strategy --- lib/compress/zstd_ldm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 42b38c0d0..6f866ea16 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -139,15 +139,19 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; - if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH; + if (params->hashRateLog == 0) { + assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); + /* mapping: strat1 -> rate8 ... strat9 -> rate4*/ + params->hashRateLog = 9 - ((cParams->strategy+1)/2); + } if (params->hashLog == 0) { - params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG); + params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog); assert(params->hashLog <= ZSTD_HASHLOG_MAX); } - if (params->hashRateLog == 0) { - params->hashRateLog = params->windowLog < params->hashLog - ? 0 - : params->windowLog - params->hashLog; + if (params->minMatchLength == 0) { + params->minMatchLength = (params->hashRateLog < 6) ? + LDM_MIN_MATCH_LENGTH : + LDM_MIN_MATCH_LENGTH * 2; } params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog); } From f26cc54f37c614d3351b6873f0ee6e3fff00f6f6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 7 Feb 2025 16:59:34 -0800 Subject: [PATCH 386/405] dynamic bucket sizes --- lib/compress/zstd_ldm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 6f866ea16..39f23c565 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -16,7 +16,7 @@ #include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */ #include "zstd_ldm_geartab.h" -#define LDM_BUCKET_SIZE_LOG 3 +#define LDM_BUCKET_SIZE_LOG 4 #define LDM_MIN_MATCH_LENGTH 64 #define LDM_HASH_RLOG 7 @@ -138,7 +138,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, params->windowLog = cParams->windowLog; ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); - if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; if (params->hashRateLog == 0) { assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); /* mapping: strat1 -> rate8 ... strat9 -> rate4*/ @@ -152,6 +151,15 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, params->minMatchLength = (params->hashRateLog < 6) ? LDM_MIN_MATCH_LENGTH : LDM_MIN_MATCH_LENGTH * 2; + if (cParams->strategy >= ZSTD_btultra2) + params->minMatchLength /= 2; + } + if (params->bucketSizeLog==0) { + params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; + if (cParams->strategy > ZSTD_lazy) { + params->bucketSizeLog += (U32)cParams->strategy - (U32)ZSTD_lazy; + } + params->bucketSizeLog = MIN(params->bucketSizeLog, ZSTD_LDM_BUCKETSIZELOG_MAX); } params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog); } From bf218c142aade4aa842205e93bc8260dcbfb372d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 7 Feb 2025 17:15:24 -0800 Subject: [PATCH 387/405] updated LDM documentation --- programs/fileio.c | 11 ++++++----- programs/zstd.1.md | 27 ++++++++++++++------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 1b8aa8a99..0ecca40d2 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1100,11 +1100,12 @@ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, FIO_setLdmFlag(prefs, 1); } if (cParams.strategy >= ZSTD_btopt) { - DISPLAYLEVEL(3, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n"); - DISPLAYLEVEL(3, "- Use --single-thread mode in the zstd cli\n"); - DISPLAYLEVEL(3, "- Set a larger targetLength (e.g. --zstd=targetLength=4096)\n"); - DISPLAYLEVEL(3, "- Set a larger chainLog (e.g. --zstd=chainLog=%u)\n", ZSTD_CHAINLOG_MAX); - DISPLAYLEVEL(3, "Also consider playing around with searchLog and hashLog\n"); + DISPLAYLEVEL(4, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n"); + DISPLAYLEVEL(4, "- Set a larger targetLength (e.g. --zstd=targetLength=4096)\n"); + DISPLAYLEVEL(4, "- Set a larger chainLog (e.g. --zstd=chainLog=%u)\n", ZSTD_CHAINLOG_MAX); + DISPLAYLEVEL(4, "- Set a larger LDM hashLog (e.g. --zstd=ldmHashLog=%u)\n", ZSTD_LDM_HASHLOG_MAX); + DISPLAYLEVEL(4, "- Set a smaller LDM rateLog (e.g. --zstd=ldmHashRateLog=%u)\n", ZSTD_LDM_HASHRATELOG_MIN); + DISPLAYLEVEL(4, "Also consider playing around with searchLog and hashLog\n"); } } diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 29b7a5bb7..be2179e5d 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -455,6 +455,17 @@ The list of available _options_: Value 0 is special and means "default": _ovlog_ is automatically determined by `zstd`. In which case, _ovlog_ will range from 6 to 9, depending on selected _strat_. +- `ldmHashRateLog`=_lhrlog_, `lhrlog`=_lhrlog_: + Specify the frequency of inserting entries into the long distance matching + hash table. + + This option is ignored unless long distance matching is enabled. + + Larger values will improve compression speed. Deviating far from the + default value will likely result in a decrease in compression ratio. + + The default value varies between 4 and 8, depending on `strategy`. + - `ldmHashLog`=_lhlog_, `lhlog`=_lhlog_: Specify the maximum size for a hash table used for long distance matching. @@ -463,7 +474,7 @@ The list of available _options_: Bigger hash tables usually improve compression ratio at the expense of more memory during compression and a decrease in compression speed. - The minimum _lhlog_ is 6 and the maximum is 30 (default: 20). + The minimum _lhlog_ is 6 and the maximum is 30 (default: `windowLog - ldmHashRateLog`). - `ldmMinMatch`=_lmml_, `lmml`=_lmml_: Specify the minimum searched length of a match for long distance matching. @@ -472,7 +483,7 @@ The list of available _options_: Larger/very small values usually decrease compression ratio. - The minimum _lmml_ is 4 and the maximum is 4096 (default: 64). + The minimum _lmml_ is 4 and the maximum is 4096 (default: 32 to 128, depending on `strategy`). - `ldmBucketSizeLog`=_lblog_, `lblog`=_lblog_: Specify the size of each bucket for the hash table used for long distance @@ -483,18 +494,8 @@ The list of available _options_: Larger bucket sizes improve collision resolution but decrease compression speed. - The minimum _lblog_ is 1 and the maximum is 8 (default: 3). + The minimum _lblog_ is 1 and the maximum is 8 (default: 4 to 8, depending on `strategy`). -- `ldmHashRateLog`=_lhrlog_, `lhrlog`=_lhrlog_: - Specify the frequency of inserting entries into the long distance matching - hash table. - - This option is ignored unless long distance matching is enabled. - - Larger values will improve compression speed. Deviating far from the - default value will likely result in a decrease in compression ratio. - - The default value is `wlog - lhlog`. ### Example The following parameters sets advanced compression options to something From 7c5b6002c9c40936fbfd13bd6e7737b059f16d4a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 7 Feb 2025 17:40:54 -0800 Subject: [PATCH 388/405] update results from the --long mode --- tests/regression/results.csv | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 505f4755b..467073ebf 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -111,9 +111,9 @@ silesia, level 9, zstdcli, silesia, level 13, zstdcli, 4488438 silesia, level 16, zstdcli, 4358150 silesia, level 19, zstdcli, 4265929 -silesia, long distance mode, zstdcli, 4824875 +silesia, long distance mode, zstdcli, 4828930 silesia, multithreaded, zstdcli, 4833113 -silesia, multithreaded long distance mode, zstdcli, 4824875 +silesia, multithreaded long distance mode, zstdcli, 4828930 silesia, small window log, zstdcli, 7094528 silesia, small hash log, zstdcli, 6527214 silesia, small chain log, zstdcli, 4911647 @@ -137,9 +137,9 @@ silesia.tar, level 13, zstdcli, silesia.tar, level 16, zstdcli, 4357018 silesia.tar, level 19, zstdcli, 4259593 silesia.tar, no source size, zstdcli, 4836000 -silesia.tar, long distance mode, zstdcli, 4828171 +silesia.tar, long distance mode, zstdcli, 4833141 silesia.tar, multithreaded, zstdcli, 4836004 -silesia.tar, multithreaded long distance mode, zstdcli, 4828171 +silesia.tar, multithreaded long distance mode, zstdcli, 4833141 silesia.tar, small window log, zstdcli, 7100110 silesia.tar, small hash log, zstdcli, 6530127 silesia.tar, small chain log, zstdcli, 4915865 @@ -217,9 +217,9 @@ github.tar, level 19, zstdcli, github.tar, level 19 with dict, zstdcli, 32705 github.tar, no source size, zstdcli, 38885 github.tar, no source size with dict, zstdcli, 38115 -github.tar, long distance mode, zstdcli, 40227 +github.tar, long distance mode, zstdcli, 38801 github.tar, multithreaded, zstdcli, 38888 -github.tar, multithreaded long distance mode, zstdcli, 40227 +github.tar, multithreaded long distance mode, zstdcli, 38801 github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 @@ -251,9 +251,9 @@ silesia, level 13, advanced silesia, level 16, advanced one pass, 4356799 silesia, level 19, advanced one pass, 4265851 silesia, no source size, advanced one pass, 4832054 -silesia, long distance mode, advanced one pass, 4823833 +silesia, long distance mode, advanced one pass, 4827748 silesia, multithreaded, advanced one pass, 4833065 -silesia, multithreaded long distance mode, advanced one pass, 4824827 +silesia, multithreaded long distance mode, advanced one pass, 4828882 silesia, small window log, advanced one pass, 7094480 silesia, small hash log, advanced one pass, 6525510 silesia, small chain log, advanced one pass, 4912248 @@ -285,9 +285,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced one pass, 4355572 silesia.tar, level 19, advanced one pass, 4257629 silesia.tar, no source size, advanced one pass, 4829268 -silesia.tar, long distance mode, advanced one pass, 4816169 +silesia.tar, long distance mode, advanced one pass, 4821065 silesia.tar, multithreaded, advanced one pass, 4836000 -silesia.tar, multithreaded long distance mode, advanced one pass, 4828167 +silesia.tar, multithreaded long distance mode, advanced one pass, 4833137 silesia.tar, small window log, advanced one pass, 7100064 silesia.tar, small hash log, advanced one pass, 6530222 silesia.tar, small chain log, advanced one pass, 4915689 @@ -535,9 +535,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced one pass, 32428 github.tar, no source size, advanced one pass, 38884 github.tar, no source size with dict, advanced one pass, 37995 -github.tar, long distance mode, advanced one pass, 40242 +github.tar, long distance mode, advanced one pass, 38797 github.tar, multithreaded, advanced one pass, 38884 -github.tar, multithreaded long distance mode, advanced one pass, 40223 +github.tar, multithreaded long distance mode, advanced one pass, 38797 github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 @@ -569,9 +569,9 @@ silesia, level 13, advanced silesia, level 16, advanced one pass small out, 4356799 silesia, level 19, advanced one pass small out, 4265851 silesia, no source size, advanced one pass small out, 4832054 -silesia, long distance mode, advanced one pass small out, 4823833 +silesia, long distance mode, advanced one pass small out, 4827748 silesia, multithreaded, advanced one pass small out, 4833065 -silesia, multithreaded long distance mode, advanced one pass small out, 4824827 +silesia, multithreaded long distance mode, advanced one pass small out, 4828882 silesia, small window log, advanced one pass small out, 7094480 silesia, small hash log, advanced one pass small out, 6525510 silesia, small chain log, advanced one pass small out, 4912248 @@ -603,9 +603,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced one pass small out, 4355572 silesia.tar, level 19, advanced one pass small out, 4257629 silesia.tar, no source size, advanced one pass small out, 4829268 -silesia.tar, long distance mode, advanced one pass small out, 4816169 +silesia.tar, long distance mode, advanced one pass small out, 4821065 silesia.tar, multithreaded, advanced one pass small out, 4836000 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4828167 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4833137 silesia.tar, small window log, advanced one pass small out, 7100064 silesia.tar, small hash log, advanced one pass small out, 6530222 silesia.tar, small chain log, advanced one pass small out, 4915689 @@ -853,9 +853,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced one pass small out, 32428 github.tar, no source size, advanced one pass small out, 38884 github.tar, no source size with dict, advanced one pass small out, 37995 -github.tar, long distance mode, advanced one pass small out, 40242 +github.tar, long distance mode, advanced one pass small out, 38797 github.tar, multithreaded, advanced one pass small out, 38884 -github.tar, multithreaded long distance mode, advanced one pass small out, 40223 +github.tar, multithreaded long distance mode, advanced one pass small out, 38797 github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 @@ -887,9 +887,9 @@ silesia, level 13, advanced silesia, level 16, advanced streaming, 4358094 silesia, level 19, advanced streaming, 4265908 silesia, no source size, advanced streaming, 4835768 -silesia, long distance mode, advanced streaming, 4827592 +silesia, long distance mode, advanced streaming, 4831544 silesia, multithreaded, advanced streaming, 4833065 -silesia, multithreaded long distance mode, advanced streaming, 4824827 +silesia, multithreaded long distance mode, advanced streaming, 4828882 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6525259 silesia, small chain log, advanced streaming, 4911577 @@ -921,9 +921,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced streaming, 4358029 silesia.tar, level 19, advanced streaming, 4258228 silesia.tar, no source size, advanced streaming, 4846779 -silesia.tar, long distance mode, advanced streaming, 4826177 +silesia.tar, long distance mode, advanced streaming, 4831119 silesia.tar, multithreaded, advanced streaming, 4836000 -silesia.tar, multithreaded long distance mode, advanced streaming, 4828167 +silesia.tar, multithreaded long distance mode, advanced streaming, 4833137 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529503 silesia.tar, small chain log, advanced streaming, 4915956 @@ -1171,9 +1171,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced streaming, 32428 github.tar, no source size, advanced streaming, 38881 github.tar, no source size with dict, advanced streaming, 38111 -github.tar, long distance mode, advanced streaming, 40242 +github.tar, long distance mode, advanced streaming, 38797 github.tar, multithreaded, advanced streaming, 38884 -github.tar, multithreaded long distance mode, advanced streaming, 40223 +github.tar, multithreaded long distance mode, advanced streaming, 38797 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 From 72406b71c30efbfe865611a79f50117254820c40 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 7 Feb 2025 18:57:44 -0800 Subject: [PATCH 389/405] update hrlog rule to favor compression ratio a bit more at low levels --- lib/compress/zstd_ldm.c | 2 +- programs/zstd.1.md | 2 +- tests/regression/results.csv | 48 ++++++++++++++++++------------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 39f23c565..e85e904da 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -141,7 +141,7 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, if (params->hashRateLog == 0) { assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); /* mapping: strat1 -> rate8 ... strat9 -> rate4*/ - params->hashRateLog = 9 - ((cParams->strategy+1)/2); + params->hashRateLog = 7 - (cParams->strategy/3); } if (params->hashLog == 0) { params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog); diff --git a/programs/zstd.1.md b/programs/zstd.1.md index be2179e5d..1459abb9f 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -464,7 +464,7 @@ The list of available _options_: Larger values will improve compression speed. Deviating far from the default value will likely result in a decrease in compression ratio. - The default value varies between 4 and 8, depending on `strategy`. + The default value varies between 4 and 7, depending on `strategy`. - `ldmHashLog`=_lhlog_, `lhlog`=_lhlog_: Specify the maximum size for a hash table used for long distance matching. diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 467073ebf..cc7500d96 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -111,9 +111,9 @@ silesia, level 9, zstdcli, silesia, level 13, zstdcli, 4488438 silesia, level 16, zstdcli, 4358150 silesia, level 19, zstdcli, 4265929 -silesia, long distance mode, zstdcli, 4828930 +silesia, long distance mode, zstdcli, 4827199 silesia, multithreaded, zstdcli, 4833113 -silesia, multithreaded long distance mode, zstdcli, 4828930 +silesia, multithreaded long distance mode, zstdcli, 4827199 silesia, small window log, zstdcli, 7094528 silesia, small hash log, zstdcli, 6527214 silesia, small chain log, zstdcli, 4911647 @@ -137,9 +137,9 @@ silesia.tar, level 13, zstdcli, silesia.tar, level 16, zstdcli, 4357018 silesia.tar, level 19, zstdcli, 4259593 silesia.tar, no source size, zstdcli, 4836000 -silesia.tar, long distance mode, zstdcli, 4833141 +silesia.tar, long distance mode, zstdcli, 4831415 silesia.tar, multithreaded, zstdcli, 4836004 -silesia.tar, multithreaded long distance mode, zstdcli, 4833141 +silesia.tar, multithreaded long distance mode, zstdcli, 4831415 silesia.tar, small window log, zstdcli, 7100110 silesia.tar, small hash log, zstdcli, 6530127 silesia.tar, small chain log, zstdcli, 4915865 @@ -217,9 +217,9 @@ github.tar, level 19, zstdcli, github.tar, level 19 with dict, zstdcli, 32705 github.tar, no source size, zstdcli, 38885 github.tar, no source size with dict, zstdcli, 38115 -github.tar, long distance mode, zstdcli, 38801 +github.tar, long distance mode, zstdcli, 38775 github.tar, multithreaded, zstdcli, 38888 -github.tar, multithreaded long distance mode, zstdcli, 38801 +github.tar, multithreaded long distance mode, zstdcli, 38775 github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 @@ -251,9 +251,9 @@ silesia, level 13, advanced silesia, level 16, advanced one pass, 4356799 silesia, level 19, advanced one pass, 4265851 silesia, no source size, advanced one pass, 4832054 -silesia, long distance mode, advanced one pass, 4827748 +silesia, long distance mode, advanced one pass, 4826152 silesia, multithreaded, advanced one pass, 4833065 -silesia, multithreaded long distance mode, advanced one pass, 4828882 +silesia, multithreaded long distance mode, advanced one pass, 4827151 silesia, small window log, advanced one pass, 7094480 silesia, small hash log, advanced one pass, 6525510 silesia, small chain log, advanced one pass, 4912248 @@ -285,9 +285,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced one pass, 4355572 silesia.tar, level 19, advanced one pass, 4257629 silesia.tar, no source size, advanced one pass, 4829268 -silesia.tar, long distance mode, advanced one pass, 4821065 +silesia.tar, long distance mode, advanced one pass, 4819329 silesia.tar, multithreaded, advanced one pass, 4836000 -silesia.tar, multithreaded long distance mode, advanced one pass, 4833137 +silesia.tar, multithreaded long distance mode, advanced one pass, 4831411 silesia.tar, small window log, advanced one pass, 7100064 silesia.tar, small hash log, advanced one pass, 6530222 silesia.tar, small chain log, advanced one pass, 4915689 @@ -535,9 +535,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced one pass, 32428 github.tar, no source size, advanced one pass, 38884 github.tar, no source size with dict, advanced one pass, 37995 -github.tar, long distance mode, advanced one pass, 38797 +github.tar, long distance mode, advanced one pass, 38771 github.tar, multithreaded, advanced one pass, 38884 -github.tar, multithreaded long distance mode, advanced one pass, 38797 +github.tar, multithreaded long distance mode, advanced one pass, 38771 github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 @@ -569,9 +569,9 @@ silesia, level 13, advanced silesia, level 16, advanced one pass small out, 4356799 silesia, level 19, advanced one pass small out, 4265851 silesia, no source size, advanced one pass small out, 4832054 -silesia, long distance mode, advanced one pass small out, 4827748 +silesia, long distance mode, advanced one pass small out, 4826152 silesia, multithreaded, advanced one pass small out, 4833065 -silesia, multithreaded long distance mode, advanced one pass small out, 4828882 +silesia, multithreaded long distance mode, advanced one pass small out, 4827151 silesia, small window log, advanced one pass small out, 7094480 silesia, small hash log, advanced one pass small out, 6525510 silesia, small chain log, advanced one pass small out, 4912248 @@ -603,9 +603,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced one pass small out, 4355572 silesia.tar, level 19, advanced one pass small out, 4257629 silesia.tar, no source size, advanced one pass small out, 4829268 -silesia.tar, long distance mode, advanced one pass small out, 4821065 +silesia.tar, long distance mode, advanced one pass small out, 4819329 silesia.tar, multithreaded, advanced one pass small out, 4836000 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4833137 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4831411 silesia.tar, small window log, advanced one pass small out, 7100064 silesia.tar, small hash log, advanced one pass small out, 6530222 silesia.tar, small chain log, advanced one pass small out, 4915689 @@ -853,9 +853,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced one pass small out, 32428 github.tar, no source size, advanced one pass small out, 38884 github.tar, no source size with dict, advanced one pass small out, 37995 -github.tar, long distance mode, advanced one pass small out, 38797 +github.tar, long distance mode, advanced one pass small out, 38771 github.tar, multithreaded, advanced one pass small out, 38884 -github.tar, multithreaded long distance mode, advanced one pass small out, 38797 +github.tar, multithreaded long distance mode, advanced one pass small out, 38771 github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 @@ -887,9 +887,9 @@ silesia, level 13, advanced silesia, level 16, advanced streaming, 4358094 silesia, level 19, advanced streaming, 4265908 silesia, no source size, advanced streaming, 4835768 -silesia, long distance mode, advanced streaming, 4831544 +silesia, long distance mode, advanced streaming, 4829919 silesia, multithreaded, advanced streaming, 4833065 -silesia, multithreaded long distance mode, advanced streaming, 4828882 +silesia, multithreaded long distance mode, advanced streaming, 4827151 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6525259 silesia, small chain log, advanced streaming, 4911577 @@ -921,9 +921,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced streaming, 4358029 silesia.tar, level 19, advanced streaming, 4258228 silesia.tar, no source size, advanced streaming, 4846779 -silesia.tar, long distance mode, advanced streaming, 4831119 +silesia.tar, long distance mode, advanced streaming, 4829404 silesia.tar, multithreaded, advanced streaming, 4836000 -silesia.tar, multithreaded long distance mode, advanced streaming, 4833137 +silesia.tar, multithreaded long distance mode, advanced streaming, 4831411 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529503 silesia.tar, small chain log, advanced streaming, 4915956 @@ -1171,9 +1171,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced streaming, 32428 github.tar, no source size, advanced streaming, 38881 github.tar, no source size with dict, advanced streaming, 38111 -github.tar, long distance mode, advanced streaming, 38797 +github.tar, long distance mode, advanced streaming, 38771 github.tar, multithreaded, advanced streaming, 38884 -github.tar, multithreaded long distance mode, advanced streaming, 38797 +github.tar, multithreaded long distance mode, advanced streaming, 38771 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 From d5e4698267b970545c349b3ed30a9168bcd165c3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 7 Feb 2025 22:47:57 -0800 Subject: [PATCH 390/405] fix boundary condition --- lib/compress/zstd_ldm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index e85e904da..aa5743c5c 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -144,8 +144,7 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, params->hashRateLog = 7 - (cParams->strategy/3); } if (params->hashLog == 0) { - params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog); - assert(params->hashLog <= ZSTD_HASHLOG_MAX); + params->hashLog = MIN(MAX(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog), ZSTD_HASHLOG_MAX); } if (params->minMatchLength == 0) { params->minMatchLength = (params->hashRateLog < 6) ? From 09d7e34ed8c138e913d8c11724f2d5fb5a1436bd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 8 Feb 2025 14:27:29 -0800 Subject: [PATCH 391/405] adjust mml --- lib/compress/zstd_ldm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index aa5743c5c..981287d85 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -147,10 +147,8 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, params->hashLog = MIN(MAX(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog), ZSTD_HASHLOG_MAX); } if (params->minMatchLength == 0) { - params->minMatchLength = (params->hashRateLog < 6) ? - LDM_MIN_MATCH_LENGTH : - LDM_MIN_MATCH_LENGTH * 2; - if (cParams->strategy >= ZSTD_btultra2) + params->minMatchLength = LDM_MIN_MATCH_LENGTH; + if (cParams->strategy >= ZSTD_btultra) params->minMatchLength /= 2; } if (params->bucketSizeLog==0) { From 339bca66066e4a099bc91d04265c9bfbf15001bb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 8 Feb 2025 16:16:35 -0800 Subject: [PATCH 392/405] update ldm compression results --- programs/zstd.1.md | 2 +- tests/regression/results.csv | 48 ++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 1459abb9f..e5c1b7fd2 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -483,7 +483,7 @@ The list of available _options_: Larger/very small values usually decrease compression ratio. - The minimum _lmml_ is 4 and the maximum is 4096 (default: 32 to 128, depending on `strategy`). + The minimum _lmml_ is 4 and the maximum is 4096 (default: 32 to 64, depending on `strategy`). - `ldmBucketSizeLog`=_lblog_, `lblog`=_lblog_: Specify the size of each bucket for the hash table used for long distance diff --git a/tests/regression/results.csv b/tests/regression/results.csv index cc7500d96..c0d4f4ae7 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -111,9 +111,9 @@ silesia, level 9, zstdcli, silesia, level 13, zstdcli, 4488438 silesia, level 16, zstdcli, 4358150 silesia, level 19, zstdcli, 4265929 -silesia, long distance mode, zstdcli, 4827199 +silesia, long distance mode, zstdcli, 4824341 silesia, multithreaded, zstdcli, 4833113 -silesia, multithreaded long distance mode, zstdcli, 4827199 +silesia, multithreaded long distance mode, zstdcli, 4824341 silesia, small window log, zstdcli, 7094528 silesia, small hash log, zstdcli, 6527214 silesia, small chain log, zstdcli, 4911647 @@ -137,9 +137,9 @@ silesia.tar, level 13, zstdcli, silesia.tar, level 16, zstdcli, 4357018 silesia.tar, level 19, zstdcli, 4259593 silesia.tar, no source size, zstdcli, 4836000 -silesia.tar, long distance mode, zstdcli, 4831415 +silesia.tar, long distance mode, zstdcli, 4827830 silesia.tar, multithreaded, zstdcli, 4836004 -silesia.tar, multithreaded long distance mode, zstdcli, 4831415 +silesia.tar, multithreaded long distance mode, zstdcli, 4827830 silesia.tar, small window log, zstdcli, 7100110 silesia.tar, small hash log, zstdcli, 6530127 silesia.tar, small chain log, zstdcli, 4915865 @@ -217,9 +217,9 @@ github.tar, level 19, zstdcli, github.tar, level 19 with dict, zstdcli, 32705 github.tar, no source size, zstdcli, 38885 github.tar, no source size with dict, zstdcli, 38115 -github.tar, long distance mode, zstdcli, 38775 +github.tar, long distance mode, zstdcli, 40143 github.tar, multithreaded, zstdcli, 38888 -github.tar, multithreaded long distance mode, zstdcli, 38775 +github.tar, multithreaded long distance mode, zstdcli, 40143 github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 @@ -251,9 +251,9 @@ silesia, level 13, advanced silesia, level 16, advanced one pass, 4356799 silesia, level 19, advanced one pass, 4265851 silesia, no source size, advanced one pass, 4832054 -silesia, long distance mode, advanced one pass, 4826152 +silesia, long distance mode, advanced one pass, 4823264 silesia, multithreaded, advanced one pass, 4833065 -silesia, multithreaded long distance mode, advanced one pass, 4827151 +silesia, multithreaded long distance mode, advanced one pass, 4824293 silesia, small window log, advanced one pass, 7094480 silesia, small hash log, advanced one pass, 6525510 silesia, small chain log, advanced one pass, 4912248 @@ -285,9 +285,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced one pass, 4355572 silesia.tar, level 19, advanced one pass, 4257629 silesia.tar, no source size, advanced one pass, 4829268 -silesia.tar, long distance mode, advanced one pass, 4819329 +silesia.tar, long distance mode, advanced one pass, 4815868 silesia.tar, multithreaded, advanced one pass, 4836000 -silesia.tar, multithreaded long distance mode, advanced one pass, 4831411 +silesia.tar, multithreaded long distance mode, advanced one pass, 4827826 silesia.tar, small window log, advanced one pass, 7100064 silesia.tar, small hash log, advanced one pass, 6530222 silesia.tar, small chain log, advanced one pass, 4915689 @@ -535,9 +535,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced one pass, 32428 github.tar, no source size, advanced one pass, 38884 github.tar, no source size with dict, advanced one pass, 37995 -github.tar, long distance mode, advanced one pass, 38771 +github.tar, long distance mode, advanced one pass, 40156 github.tar, multithreaded, advanced one pass, 38884 -github.tar, multithreaded long distance mode, advanced one pass, 38771 +github.tar, multithreaded long distance mode, advanced one pass, 40139 github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 @@ -569,9 +569,9 @@ silesia, level 13, advanced silesia, level 16, advanced one pass small out, 4356799 silesia, level 19, advanced one pass small out, 4265851 silesia, no source size, advanced one pass small out, 4832054 -silesia, long distance mode, advanced one pass small out, 4826152 +silesia, long distance mode, advanced one pass small out, 4823264 silesia, multithreaded, advanced one pass small out, 4833065 -silesia, multithreaded long distance mode, advanced one pass small out, 4827151 +silesia, multithreaded long distance mode, advanced one pass small out, 4824293 silesia, small window log, advanced one pass small out, 7094480 silesia, small hash log, advanced one pass small out, 6525510 silesia, small chain log, advanced one pass small out, 4912248 @@ -603,9 +603,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced one pass small out, 4355572 silesia.tar, level 19, advanced one pass small out, 4257629 silesia.tar, no source size, advanced one pass small out, 4829268 -silesia.tar, long distance mode, advanced one pass small out, 4819329 +silesia.tar, long distance mode, advanced one pass small out, 4815868 silesia.tar, multithreaded, advanced one pass small out, 4836000 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4831411 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4827826 silesia.tar, small window log, advanced one pass small out, 7100064 silesia.tar, small hash log, advanced one pass small out, 6530222 silesia.tar, small chain log, advanced one pass small out, 4915689 @@ -853,9 +853,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced one pass small out, 32428 github.tar, no source size, advanced one pass small out, 38884 github.tar, no source size with dict, advanced one pass small out, 37995 -github.tar, long distance mode, advanced one pass small out, 38771 +github.tar, long distance mode, advanced one pass small out, 40156 github.tar, multithreaded, advanced one pass small out, 38884 -github.tar, multithreaded long distance mode, advanced one pass small out, 38771 +github.tar, multithreaded long distance mode, advanced one pass small out, 40139 github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 @@ -887,9 +887,9 @@ silesia, level 13, advanced silesia, level 16, advanced streaming, 4358094 silesia, level 19, advanced streaming, 4265908 silesia, no source size, advanced streaming, 4835768 -silesia, long distance mode, advanced streaming, 4829919 +silesia, long distance mode, advanced streaming, 4827032 silesia, multithreaded, advanced streaming, 4833065 -silesia, multithreaded long distance mode, advanced streaming, 4827151 +silesia, multithreaded long distance mode, advanced streaming, 4824293 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6525259 silesia, small chain log, advanced streaming, 4911577 @@ -921,9 +921,9 @@ silesia.tar, level 13, advanced silesia.tar, level 16, advanced streaming, 4358029 silesia.tar, level 19, advanced streaming, 4258228 silesia.tar, no source size, advanced streaming, 4846779 -silesia.tar, long distance mode, advanced streaming, 4829404 +silesia.tar, long distance mode, advanced streaming, 4825842 silesia.tar, multithreaded, advanced streaming, 4836000 -silesia.tar, multithreaded long distance mode, advanced streaming, 4831411 +silesia.tar, multithreaded long distance mode, advanced streaming, 4827826 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529503 silesia.tar, small chain log, advanced streaming, 4915956 @@ -1171,9 +1171,9 @@ github.tar, level 19 with dict copy, advanced github.tar, level 19 with dict load, advanced streaming, 32428 github.tar, no source size, advanced streaming, 38881 github.tar, no source size with dict, advanced streaming, 38111 -github.tar, long distance mode, advanced streaming, 38771 +github.tar, long distance mode, advanced streaming, 40156 github.tar, multithreaded, advanced streaming, 38884 -github.tar, multithreaded long distance mode, advanced streaming, 38771 +github.tar, multithreaded long distance mode, advanced streaming, 40139 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 From 67fad95f7971b97085fb838e3aa47cd37e9d7908 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 9 Feb 2025 11:11:49 -0800 Subject: [PATCH 393/405] derive hashratelog from hashlog when only hashlog is set --- lib/compress/zstd_ldm.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 981287d85..6aa6197e9 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -133,18 +133,26 @@ done: } void ZSTD_ldm_adjustParameters(ldmParams_t* params, - ZSTD_compressionParameters const* cParams) + const ZSTD_compressionParameters* cParams) { params->windowLog = cParams->windowLog; ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX); DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (params->hashRateLog == 0) { - assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); - /* mapping: strat1 -> rate8 ... strat9 -> rate4*/ - params->hashRateLog = 7 - (cParams->strategy/3); + if (params->hashLog > 0) { + /* if params->hashLog is set, derive hashRateLog from it */ + assert(params->hashLog <= ZSTD_HASHLOG_MAX); + if (params->windowLog > params->hashLog) { + params->hashRateLog = params->windowLog - params->hashLog; + } + } else { + assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); + /* mapping: strat1 -> rate8 ... strat9 -> rate4*/ + params->hashRateLog = 7 - (cParams->strategy/3); + } } if (params->hashLog == 0) { - params->hashLog = MIN(MAX(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog), ZSTD_HASHLOG_MAX); + params->hashLog = BOUNDED(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog, ZSTD_HASHLOG_MAX); } if (params->minMatchLength == 0) { params->minMatchLength = LDM_MIN_MATCH_LENGTH; @@ -152,11 +160,8 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, params->minMatchLength /= 2; } if (params->bucketSizeLog==0) { - params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; - if (cParams->strategy > ZSTD_lazy) { - params->bucketSizeLog += (U32)cParams->strategy - (U32)ZSTD_lazy; - } - params->bucketSizeLog = MIN(params->bucketSizeLog, ZSTD_LDM_BUCKETSIZELOG_MAX); + assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); + params->bucketSizeLog = BOUNDED(LDM_BUCKET_SIZE_LOG, (U32)cParams->strategy, ZSTD_LDM_BUCKETSIZELOG_MAX); } params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog); } From d2c562b803a4c49dbd5afb1717db095aae1557b1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 10 Feb 2025 10:48:56 -0800 Subject: [PATCH 394/405] update hrlog comment --- lib/compress/zstd_ldm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 6aa6197e9..070551cad 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -147,7 +147,7 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, } } else { assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9); - /* mapping: strat1 -> rate8 ... strat9 -> rate4*/ + /* mapping from [fast, rate7] to [btultra2, rate4] */ params->hashRateLog = 7 - (cParams->strategy/3); } } From 815ca8c6784f59de825058b2b84bdb59b854feee Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 09:19:08 -0800 Subject: [PATCH 395/405] ubuntu 20 is being deprecated change ubuntu20 tests to use more modern ubuntu variants --- .github/workflows/dev-short-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 2b35354d2..392b005f6 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -38,7 +38,7 @@ jobs: CFLAGS="-m32 -O1 -fstack-protector" make check V=1 check-x32: - runs-on: ubuntu-20.04 # ubuntu-latest == ubuntu-22.04 have issues currently with x32 + runs-on: ubuntu-lastest # ubuntu-latest == ubuntu-22.04 have issues currently with x32 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: make check on x32 ABI # https://en.wikipedia.org/wiki/X32_ABI @@ -467,7 +467,7 @@ jobs: qemu-consistency: name: QEMU ${{ matrix.name }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix failed. matrix: From fc1baf34637e7f230996cdc8ca259bf71809978a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 09:57:18 -0800 Subject: [PATCH 396/405] move qemu tests to ubuntu24 --- .github/workflows/dev-short-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 392b005f6..d9610d3a4 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -467,7 +467,7 @@ jobs: qemu-consistency: name: QEMU ${{ matrix.name }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix failed. matrix: From 75bcae1272cbd6e417a9eb2c0e35e9f02828fba4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 11:37:18 -0800 Subject: [PATCH 397/405] removing x32 tests this ABI is no longer supported by Ubuntu, and there is a wider consensus that this ABI is on the way out, with more and more distributions dropping it, and lingering questions about support of x32 in the kernel. --- .github/workflows/dev-short-tests.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index d9610d3a4..7cc7bd85f 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -37,18 +37,6 @@ jobs: APT_PACKAGES="gcc-multilib" make apt-install CFLAGS="-m32 -O1 -fstack-protector" make check V=1 - check-x32: - runs-on: ubuntu-lastest # ubuntu-latest == ubuntu-22.04 have issues currently with x32 - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: make check on x32 ABI # https://en.wikipedia.org/wiki/X32_ABI - env: - CHECK_CONSTRAINED_MEM: true - run: | - sudo apt update - APT_PACKAGES="gcc-multilib" make apt-install - CFLAGS="-mx32 -O1 -fstack-protector" make check V=1 - build-c89: runs-on: ubuntu-latest steps: From 2b7c661ad2c022a56f6d0c58cbafa6f3d637ad4f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 11:43:23 -0800 Subject: [PATCH 398/405] update arm64 test for ubuntu-24 --- .github/workflows/dev-short-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 7cc7bd85f..61fd9fb69 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -461,7 +461,7 @@ jobs: matrix: include: [ { name: ARM, xcc_pkg: gcc-arm-linux-gnueabi, xcc: arm-linux-gnueabi-gcc, xemu_pkg: qemu-system-arm, xemu: qemu-arm-static }, - { name: ARM64, xcc_pkg: gcc-aarch64-linux-gnu, xcc: aarch64-linux-gnu-gcc, xemu_pkg: qemu-system-arm, xemu: qemu-aarch64-static }, + { name: ARM64, xcc_pkg: gcc-aarch64-linux-gnu, xcc: aarch64-linux-gnu-gcc, xemu_pkg: qemu-system-aarch64,xemu: qemu-aarch64-static }, { name: PPC, xcc_pkg: gcc-powerpc-linux-gnu, xcc: powerpc-linux-gnu-gcc, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc-static }, { name: PPC64LE, xcc_pkg: gcc-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static }, { name: S390X, xcc_pkg: gcc-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static }, @@ -494,7 +494,7 @@ jobs: - name: ARM64 if: ${{ matrix.name == 'ARM64' }} run: | - LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make clean check + CFLAGS="-march=armv8-a -Og" LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make clean check LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check - name: PPC if: ${{ matrix.name == 'PPC' }} From b73e06b83e0fc6f7f6999c2292b3250eb50b2084 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 12:52:59 -0800 Subject: [PATCH 399/405] updated FreeBSD VM to 14.2 14.1 seems no longer supported by gcloud --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 9461de412..745024bc2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,7 +2,7 @@ task: name: FreeBSD (make check) freebsd_instance: matrix: - image_family: freebsd-14-1 + image_family: freebsd-14-2 install_script: pkg install -y gmake coreutils script: | MOREFLAGS="-Werror" gmake -j all From 0b8119f0ad0b027faffb7955b835718e049399e6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 12:58:35 -0800 Subject: [PATCH 400/405] minor arm64 test script clarification --- .github/workflows/dev-short-tests.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 61fd9fb69..19446d18e 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -494,8 +494,10 @@ jobs: - name: ARM64 if: ${{ matrix.name == 'ARM64' }} run: | - CFLAGS="-march=armv8-a -Og" LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make clean check - LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make clean check + make clean + CFLAGS="-march=armv8-a -Og" LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make check + make clean + CFLAGS="-march=armv8-a -Og" LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make check - name: PPC if: ${{ matrix.name == 'PPC' }} run: | From 85c39b78cfabf64fe0d8859f3c4ac5f240d52fc8 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 13:11:29 -0800 Subject: [PATCH 401/405] faster aarch64 test execution --- .github/workflows/dev-short-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 19446d18e..a163e0219 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -495,9 +495,9 @@ jobs: if: ${{ matrix.name == 'ARM64' }} run: | make clean - CFLAGS="-march=armv8-a -Og" LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make check + LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check make clean - CFLAGS="-march=armv8-a -Og" LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make check + LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make check V=1 - name: PPC if: ${{ matrix.name == 'PPC' }} run: | From 2a58b047529ca385867fea53b4077526bb10486e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 11 Feb 2025 13:20:15 -0800 Subject: [PATCH 402/405] disabled BTI test this test seems impossible on Ubuntu-24 --- .github/workflows/dev-short-tests.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index a163e0219..408331abc 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -496,8 +496,10 @@ jobs: run: | make clean LDFLAGS="-static" CC=$XCC QEMU_SYS=$XEMU make -j check - make clean - LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make check V=1 +# This test is only compatible with standard libraries that support BTI (Branch Target Identification). +# Unfortunately, the standard library provided on Ubuntu 24.04 does not have this feature enabled. +# make clean +# LDFLAGS="-static -z force-bti" MOREFLAGS="-mbranch-protection=standard" CC=$XCC QEMU_SYS=$XEMU make check V=1 - name: PPC if: ${{ matrix.name == 'PPC' }} run: | From c26bde119ba984ae1f2efe76d610eb50d152b1ec Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 18 Feb 2025 13:42:54 -0800 Subject: [PATCH 403/405] update changelog for v1.5.7 --- CHANGELOG | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ac44affce..92df0f462 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,29 @@ +V1.5.7 (Feb 2025) +fix: compression bug in 32-bit mode associated with long-lasting sessions +api: new method `ZSTD_compressSequencesAndLiterals()` (#4217, #4232) +api: `ZSTD_getFrameHeader()` works on skippable frames (#4228) +perf: substantial compression speed improvements (up to +30%) on small data, by @TocarIP (#4144) and @cyan4973 (#4165) +perf: improved compression speed (~+5%) for dictionary compression at low levels (#4170) +perf: much faster speed for `--patch-from` at high compression levels (#4276) +perf: higher `--patch-from` compression ratios, notably at high levels (#4288) +perf: better speed for binaries on Windows (@pps83) and when compiled with Visual Studio (@MessyHack) +perf: slight compression ratio improvement thanks to better block boundaries (#4136, #4176, #4178) +perf: slight compression ratio improvement for `dfast`, aka levels 3 and 4 (#4171) +perf: runtime bmi2 detection enabled on x86 32-bit mode (#4251) +cli: multi-threading as default CLI setting, by @daniellerozenblit +cli: new `--max` command (#4290) +build: improve `msbuild` version autodetection, support VS2022, by @ManuelBlanc +build: fix `meson` build by @artem and @Victor-C-Zhang, and on Windows by @bgilbert +build: compatibility with Apple Framework, by @Treata11 +build: improve icc/icx compatibility, by @josepho0918 and @luau-project +build: improve compatibility with Android NDK, by Adenilson Cavalcanti +portability: linux kernel branch, with improved support for Sequence producers (@embg, @gcabiddu, @cyan4973) +portability: improved qnx compatibility, suggested by @rainbowball +portability: improved install script for FreeBSD, by @sunpoet +portability: fixed test suite compatibility with gnu hurd, by @diegonc +doc: clarify specification, by @elasota +misc: improved tests/decodecorpus validation tool (#4102), by antmicro + V1.5.6 (Mar 2024) api: Promote `ZSTD_c_targetCBlockSize` to Stable API by @felixhandte api: new `ZSTD_d_maxBlockSize` experimental parameter, to reduce streaming decompression memory, by @terrelln From 5c465fcabeea65e642aaf70d1059958acd6acd69 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 18 Feb 2025 14:50:03 -0800 Subject: [PATCH 404/405] harden github actions script Android NDK Build --- .github/workflows/android-ndk-build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-ndk-build.yml b/.github/workflows/android-ndk-build.yml index c77d5f0d1..175add4ff 100644 --- a/.github/workflows/android-ndk-build.yml +++ b/.github/workflows/android-ndk-build.yml @@ -6,6 +6,8 @@ on: push: branches: [ actionsTest, '*ndk*' ] +permissions: read-all + jobs: build: runs-on: ubuntu-latest @@ -14,13 +16,13 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 with: java-version: '17' distribution: 'temurin' - name: Setup Android SDK - uses: android-actions/setup-android@v3 + uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3.2.2 - name: Install Android NDK run: | From b14d76d88810f2984e0cd9ebd307269843a5d7d9 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 18 Feb 2025 14:53:31 -0800 Subject: [PATCH 405/405] pinned dependency hash --- .github/workflows/dev-short-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 53ae03d79..7df105532 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -97,7 +97,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 with: path: "${{ env.SRC_DIR }}" - - uses: ilammy/msvc-dev-cmd@v1 + - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 if: ${{ matrix.generator == 'NMake Makefiles' }} - name: cmake build on a source directory with spaces run: | @@ -722,4 +722,4 @@ jobs: - name: make check run: | source /opt/intel/oneapi/setvars.sh - make CC=icx check \ No newline at end of file + make CC=icx check