[lld] [lld][ELF][test] Accept zlib-ng compressed size (PR #206880)

Mark Zhuang via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 1 20:49:00 PDT 2026


zqb-all wrote:

 <details>                                                                                                                                                                                                                                                                     <summary>Reproduction script (needs cmake, cc, curl)</summary>

```bash
#!/usr/bin/env bash
# Reproduce the zlib vs zlib-ng level-1 deflate size difference behind
# lld/test/ELF/compressed-debug-level.test, and show it is an intentional
# speed/ratio tradeoff (deflate_quick), not a RISC-V or zlib-ng bug.
# Requirements: cmake, cc, curl. Runs entirely under /tmp/zngrepro.
set -e
cd /tmp && rm -rf zngrepro && mkdir zngrepro && cd zngrepro

# 1) Fetch zlib-ng 2.3.2 source (the version Bianbu ships).
curl -fsSL --retry 5 --retry-all-errors -o zlib-ng-2.3.2.tar.gz \
     https://codeload.github.com/zlib-ng/zlib-ng/tar.gz/refs/tags/2.3.2
tar xzf zlib-ng-2.3.2.tar.gz
SRC=$PWD/zlib-ng-2.3.2

# 2) Build A: stock defaults. At level 1, zlib-ng dispatches to deflate_quick
#    (configuration_table[1] in deflate.c).
cmake -S "$SRC" -B build-quick   -DZLIB_COMPAT=ON -DCMAKE_BUILD_TYPE=Release >/dev/null 2>&1
cmake --build build-quick   -j"$(nproc)" >/dev/null 2>&1

# 3) Build B: -DNO_QUICK_STRATEGY. This disables deflate_quick, so level 1
#    falls back to deflate_fast -- the same strategy stock zlib uses.
cmake -S "$SRC" -B build-noquick -DZLIB_COMPAT=ON -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_C_FLAGS="-DNO_QUICK_STRATEGY" >/dev/null 2>&1
cmake --build build-noquick -j"$(nproc)" >/dev/null 2>&1

# 4) Minimal reproducer: deflate the exact 36-byte .debug_info payload from the
#    lld test at level 1. Section size reported by llvm-readelf = deflate stream
#    + 12-byte Elf32_Chdr, so we add 12 to match the values seen in the test.
cat > defl.c <<'EOF'
#include <stdio.h>
#include <string.h>
#include <zlib.h>
static const unsigned char in[] = {
 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x02,0x01,
 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x02,0x01,
 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x02,0x01};
int main(void){
  unsigned char out[256]; z_stream s; memset(&s,0,sizeof s);
  deflateInit(&s,1);                       /* level 1, same as ld.lld default */
  s.next_in=(unsigned char*)in; s.avail_in=sizeof in;
  s.next_out=out; s.avail_out=sizeof out;
  deflate(&s,Z_FINISH);
  printf("%-16s deflate(level1)=%2lu bytes  -> ELF section size 0x%lx\n",
         zlibVersion(), (unsigned long)s.total_out,
         (unsigned long)s.total_out+12);   /* + Elf32_Chdr */
  deflateEnd(&s); return 0;
}
EOF
cc defl.c -o defl_quick   -I"$SRC" -Ibuild-quick   -Lbuild-quick   -lz -Wl,-rpath,"$PWD/build-quick"
cc defl.c -o defl_noquick -I"$SRC" -Ibuild-noquick -Lbuild-noquick -lz -Wl,-rpath,"$PWD/build-noquick"
cc defl.c -o defl_sys -lz                  # link against the system's stock zlib

echo "================ Root cause: level-1 deflate of the 36-byte payload ================"
echo -n "stock zlib (system)           : "; ./defl_sys
echo -n "zlib-ng 2.3.2 deflate_quick   : "; ./defl_quick
echo -n "zlib-ng 2.3.2 NO_QUICK_STRATEGY: "; ./defl_noquick
echo "host arch: $(uname -m)"

# 5) Tradeoff: deflate_quick trades ratio for speed. Compare stock zlib vs
#    zlib-ng at level 1 (deflate_quick) and level 2 (leaves deflate_quick)
#    on realistic inputs, measuring both output size and throughput.
cat > bench.c <<'EOF'
#define _POSIX_C_SOURCE 199309L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <zlib.h>
static double now(void){struct timespec t;clock_gettime(CLOCK_MONOTONIC,&t);return t.tv_sec+t.tv_nsec*1e-9;}
int main(int argc,char**argv){
  int level=atoi(argv[2]);
  FILE*f=fopen(argv[1],"rb"); fseek(f,0,SEEK_END); long n=ftell(f); fseek(f,0,SEEK_SET);
  unsigned char*in=malloc(n); if(fread(in,1,n,f)!=(size_t)n)return 2; fclose(f);
  unsigned long bound=compressBound(n); unsigned char*out=malloc(bound);
  unsigned long outlen=bound; compress2(out,&outlen,in,n,level);
  long budget=200L*1024*1024; int iters=(int)(budget/(n?n:1)); if(iters<3)iters=3; if(iters>200000)iters=200000;
  double t0=now(); for(int i=0;i<iters;i++){unsigned long ol=bound; compress2(out,&ol,in,n,level);} double dt=now()-t0;
  printf("  %-14s lvl=%d  out=%8lu  ratio=%7.3f  %8.1f MB/s\n",
         zlibVersion(),level,outlen,(double)n/outlen,(double)n*iters/dt/1e6);
  return 0;
}
EOF
cc bench.c -o bench_sys -O2 -lz
cc bench.c -o bench_ng  -O2 -I"$SRC" -Ibuild-quick -Lbuild-quick -lz -Wl,-rpath,"$PWD/build-quick"

# Inputs: highly-repetitive text, natural source text, and a real binary.
yes "$(printf '%.0s/' $(seq 1 70))" 2>/dev/null | head -c 4500000 > in_repetitive.txt
cat "$SRC"/*.c "$SRC"/*.h > in_source.txt
cp "$(command -v cc)" in_binary.bin

echo
echo "================ Tradeoff: size vs throughput (stock zlib vs zlib-ng) ================"
for f in in_repetitive.txt in_source.txt in_binary.bin; do
  for lvl in 1 2; do
    echo "input=$f  level=$lvl"
    ./bench_sys "$f" "$lvl"
    ./bench_ng  "$f" "$lvl"
  done
done 
```
</details>

result:
```
$ bash ./zlibng_repro.sh
================ Root cause: level-1 deflate of the 36-byte payload ================
stock zlib (system)           : 1.2.11           deflate(level1)=18 bytes  -> ELF section size 0x1e
zlib-ng 2.3.2 deflate_quick   : 1.3.1.zlib-ng    deflate(level1)=20 bytes  -> ELF section size 0x20
zlib-ng 2.3.2 NO_QUICK_STRATEGY: 1.3.1.zlib-ng    deflate(level1)=17 bytes  -> ELF section size 0x1d
host arch: x86_64

================ Tradeoff: size vs throughput (stock zlib vs zlib-ng) ================
input=in_repetitive.txt  level=1
  1.2.11         lvl=1  out=   41167  ratio=109.311     671.2 MB/s
  1.3.1.zlib-ng  lvl=1  out=   78029  ratio= 57.671    2882.4 MB/s
input=in_repetitive.txt  level=2
  1.2.11         lvl=2  out=   41167  ratio=109.311     483.8 MB/s
  1.3.1.zlib-ng  lvl=2  out=   28803  ratio=156.234    3344.0 MB/s
input=in_source.txt  level=1
  1.2.11         lvl=1  out=  380828  ratio=  2.656      62.8 MB/s
  1.3.1.zlib-ng  lvl=1  out=  486395  ratio=  2.080     152.7 MB/s
input=in_source.txt  level=2
  1.2.11         lvl=2  out=  366271  ratio=  2.762      79.1 MB/s
  1.3.1.zlib-ng  lvl=2  out=  355518  ratio=  2.845     130.9 MB/s
input=in_binary.bin  level=1
  1.2.11         lvl=1  out=  369680  ratio=  2.512      47.0 MB/s
  1.3.1.zlib-ng  lvl=1  out=  446865  ratio=  2.078     147.8 MB/s
input=in_binary.bin  level=2
  1.2.11         lvl=2  out=  362590  ratio=  2.561      56.4 MB/s
  1.3.1.zlib-ng  lvl=2  out=  370760  ratio=  2.505      85.2 MB/s
```
                          

https://github.com/llvm/llvm-project/pull/206880


More information about the llvm-commits mailing list