From Fedora Project Wiki

Simple Analysis of btrfs zstd compression level

Workstation root fs disk space savings

tl;dr;

For an installed root directory of Fedora 32, zstd:1 yields a 40% storage savings as compared to uncompressed ext4. zstd:9 yields a 43% storage savings.

Test Steps

1. Obtain an “installed.dir” by

   1. Prep the image
       1. truncate -s 64G installed.raw
   2. Booting the live cd (in the case F32) in a qemu-kvm 
       1. qemu-kvm -drive file=installed.raw -cdrom $ISO -m 1G
   3. Installing it in the graphical installer
       1. I used regular partitions, and did not create a new one for /home
   4. Shutting down the qemu instance3105440
   5. Mount it to the directory
       1. losetup -Pf installed.raw
       2. mkdir -p installed.dir
       3. mount /dev/loop1p2 installed.dir

2. Run the script below

#!/bin/sh

set -e

SIZE=16G

if [ $EUID -ne 0 ] ; then
    echo "Needs to be root" >&2
    exit 2
fi

for compress_level in 1 3 9 ; do
    raw=zstd${compress_level}.raw
    truncate -s $SIZE $raw
    mkfs.btrfs -f $raw
    dir=zstd${compress_level}.dir
    mkdir -p $dir
    mount -o compress=zstd:${compress_level} $raw $dir
    perf record -g -o perf${compress_level}.data bash -c "cp -r installed.dir/* $dir ; sync $dir"
done
</code>

=== Results ===

zstd:1 - 40% savings
zstd:3 - 41% savings
zstd:9 - 43% savings

This is the result from df. Ignore Use% because the installed directory is a different size.

<code>
Filesystem                              1K-blocks     Used Available Use% Mounted on
/dev/loop1p3                             61665068  5458980  53043976  10% /scratch/installed.dir
/dev/loop0                               16777216  3257192  13356936  20% /scratch/zstd1.dir
/dev/loop2                               16777216  3197668  13415468  20% /scratch/zstd3.dir
/dev/loop3                               16777216  3105440  13502704  19% /scratch/zstd9.dir

/dev/urandom copy cpu cost

    • note: this test is a lot less scientific than the other one, because it’ll be CPU dependent and I had other stuff going on (chrome was open, etc). It’s likely still a reasonable proxy for CPU impact though.**

tl;dr;

zstd:1 added 9% and zstd:9 added 15% of system time to the baseline.

Test Steps

1. Get a 2GB blah file that will compress very poorly

   1. dd if=/dev/urandom of=blah bs=256K count=8192

2. Run the script

#!/bin/sh

set -e

SIZE=16G

if [ $EUID -ne 0 ] ; then
    echo "Needs to be root" >&2
    exit 2
fi

for compress_level in 0 1 3 9 ; do
    raw=zstd${compress_level}.raw
    truncate -s $SIZE $raw    #perf record -g -o perf${compress_level}.data bash -c    #perf record -g -o perf${compress_level}.data bash -c
    mkfs.btrfs -f $raw 2>/dev/null >/dev/null
    dir=zstd${compress_level}.dir
    mkdir -p $dir
    if [ $compress_level -eq 0 ] ; then
        mount $raw $dir
    else
        mount -o compress=zstd:${compress_level} $raw $dir
    fi
    echo Compression Level ${compress_level}
    time bash -c \
         "dd if=blah of=$dir/blah ; sync $dir"
done

Results

Compression Level 0
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 13.3657 s, 161 MB/s

real    0m13.386s
user    0m2.891s
sys     0m9.486s
Compression Level 1
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 14.8094 s, 145 MB/s

real    0m14.913s
user    0m3.313s
sys     0m10.380s
Compression Level 3
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 15.1291 s, 142 MB/s

real    0m15.259s
user    0m3.261s
sys     0m10.720s
Compression Level 9
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 15.4792 s, 139 MB/s

real    0m15.499s
user    0m3.442s
sys     0m10.913s

/dev/zero cpu copy test

tl;dr;

Easily compressed data is a lot more expensive at higher levels. zstd:1 added 16%, zstd:9 added 82%

Test Steps

Same as above, but swap /dev/urandom for /dev/zero

Results

Compression Level 0
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 14.1791 s, 151 MB/s

real    0m14.196s
user    0m2.971s
sys     0m9.909s
Compression Level 1
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 16.4391 s, 131 MB/s

real    0m16.536s
user    0m3.403s
sys     0m11.511s
Compression Level 3
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 14.9807 s, 143 MB/s

real    0m15.094s
user    0m3.398s
sys     0m10.833s
Compression Level 9
4194304+0 records in
4194304+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 18.0451 s, 119 MB/s

real    0m18.066s
user    0m3.758s
sys     0m12.173s