惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Hugging Face - Blog
Hugging Face - Blog
IT之家
IT之家
Jina AI
Jina AI
Google DeepMind News
Google DeepMind News
大猫的无限游戏
大猫的无限游戏
The GitHub Blog
The GitHub Blog
腾讯CDC
L
LangChain Blog
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
量子位
Apple Machine Learning Research
Apple Machine Learning Research
Cloudbric
Cloudbric
B
Blog RSS Feed
B
Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Vercel News
Vercel News
S
Schneier on Security
Project Zero
Project Zero
宝玉的分享
宝玉的分享
美团技术团队
MyScale Blog
MyScale Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Spread Privacy
Spread Privacy
T
Threatpost
A
Arctic Wolf
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News - Newest:
Hacker News - Newest: "LLM"
爱范儿
爱范儿
Recorded Future
Recorded Future
C
CERT Recently Published Vulnerability Notes
T
Threat Research - Cisco Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
SecWiki News
SecWiki News
H
Hacker News: Front Page
AWS News Blog
AWS News Blog
博客园_首页
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tor Project blog
C
Check Point Blog
L
Lohrmann on Cybersecurity
F
Full Disclosure
TaoSecurity Blog
TaoSecurity Blog
Google Online Security Blog
Google Online Security Blog
云风的 BLOG
云风的 BLOG
The Last Watchdog
The Last Watchdog
Martin Fowler
Martin Fowler

Peng's Blog

Vibe paper不负责指北 SPFC参考文献阅读《CONGA》 读《Uno:数据中心间和数据中心内拥塞控制与可靠连接的一站式解决方案》 Lenovo Legion Y9000P 在 Linux 下只有 30W:从现象、WMI 到驱动补丁 理解《From ATOP to ZCube》中的ZCube网络拓扑 集合通信原语学习 Zotero在Wayland下侧边栏无法拖动的解决办法 再读CAVER 我读的第一篇论文--NSDI_26_CAVER 在archlinux下使用万象拼音实现更智慧的中文输入法 Traefik实现单Docker容器托管多个静态网站 Pengs.top浴火重生!备案、服务器迁移与全站Docker化 严谨与温度并存:北航宋友老师程设课的学习感悟 Android Studio全流程换源指南 解决linux系统下pipewire作为音频服务器持续播放声音中断问题 在ThinkBook 16+ 2025上安装archlinux驯服记录【基本信息与触摸板修复】 「行云流水」在挂载移动硬盘时自动启动Syncthing开始同步的丝滑体验 自建图床和PicGo闹不愉快?干脆自己写个脚本,深度整合到KDE右键菜单! 别当冤大头,Adobe全家桶破解源头方案:修图剪辑不求人,盗版网站也得从你这儿进货! 轻松配置aria2下载器,通过systemd设置开机自启并与浏览器集成 Git Commit 规范指南
btrfs各压缩等级速率测试脚本,选择最适合你的压缩级别
Pengbo · 2025-08-08 · via Peng's Blog

btrfs透明压缩值得尝试

之前我们写过btrfs快照的使用,不得不说,btrfs是一个非常先进的文件系统(至少在设计理念上是的)。

除了快照,btrfs的另外一个高级特性是透明压缩,强调透明是由于压缩的过程由文件系统完成,而用户以及应用无感。这就是接口抽象的意义。

透明压缩有诸多好处,引用Arch wiki:

Btrfs 支持透明自动压缩,这不仅能缩减文件体积,还能通过减弱写入放大效应显著延长闪存介质的使用寿命。
在某些情况下(例如单线程繁重文件 I/O 时),压缩可以提升性能,但在其他场景中(如多线程或高 CPU 占用并涉及大量文件读写的任务),性能则会明显下降。
通常采用压缩算法越快(zstd 和 lzo)性能越好,一些基准测试提供了详细的性能对比数据。

简而言之,优点是省地方,对SSD友好,缺点是会降低一定的吞吐量,以及会占用CPU资源,可是在SSD速度已经很充足,CPU性能总是过剩的现在,这点缺点算不了什么。

所以很值得尝试。

确实很值得“尝试”

btrfs给用户提供了zlib(类似zip),lzozstd三个可选算法。

对于压缩级别,zlib:1~9;zstd:-15~-1、1~15,需为整数。

所以理论上有25种尝试组合(忽略zstd的负值,lzo无法设置等级)

手动尝试耗时耗力还不准确,所以我万能的Gemini又下场了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/bin/zsh
set -e

trap 'umount -q /mnt; rmmod brd' INT TERM

# 依赖检查
check_dependency() {
if ! command -v $1 &> /dev/null; then
echo "错误: 未找到必需的工具 $1,请先安装"
exit 1
fi
}

check_dependency zsh
check_dependency hyperfine
check_dependency compsize
check_dependency jq
check_dependency bc
check_dependency mkfs.btrfs
check_dependency mkfs.ext4

# 基准测试数据目录
BENCHMARK_DIR="/tmp/silesia/"

# 检查基准目录是否存在且非空
if [ ! -d "$BENCHMARK_DIR" ] || [ -z "$(ls -A "$BENCHMARK_DIR" 2>/dev/null)" ]; then
echo "错误: 基准目录 $BENCHMARK_DIR 不存在或为空"
echo "请下载Silesia测试集: wget http://mattmahoney.net/dc/silesia.zip && unzip silesia.zip -d /tmp/silesia/"
exit 1
fi

DIR_SIZE=$(du -bs "$BENCHMARK_DIR" | cut -f1)
if [ "$DIR_SIZE" -eq 0 ]; then
echo "错误: 基准目录大小为零"
exit 1
fi

OUTPUT_ROW="%-15s %-10s %-10s %20s %25s\n"

# 通用基准测试函数,增加文件系统参数
bench(){
local fs_type=$1
local mount_opts=$2
local label=$3

# 根据文件系统类型选择格式化命令
if [ "$fs_type" = "btrfs" ]; then
mkfs_cmd="mkfs.btrfs -O block-group-tree /dev/ram0 -f"
elif [ "$fs_type" = "ext4" ]; then
mkfs_cmd="mkfs.ext4 -F /dev/ram0"
else
echo "错误: 不支持的文件系统类型 $fs_type"
return 1
fi

# 测量压缩时间 (对于ext4和无压缩Btrfs,这实际是纯复制时间)
comp_time=$(
hyperfine \
--prepare "umount -q /mnt; $mkfs_cmd; mount -o $mount_opts /dev/ram0 /mnt; sync; echo 3 > /proc/sys/vm/drop_caches" \
--style=none --export-json - --runs 20 \
"cp -r $BENCHMARK_DIR/* /mnt; sync" | jq -r '.results[].mean'
)

# 测量解压缩/读取时间
decomp_time=$(
hyperfine \
--prepare "umount -q /mnt; mount -o $mount_opts /dev/ram0 /mnt; sync; echo 3 > /proc/sys/vm/drop_caches" \
--style=none --export-json - --runs 20 \
"tar -c /mnt 2>/dev/null| cat > /dev/null" | jq -r '.results[].mean'
)

# 检查是否成功获取时间数据
if ! [[ "$comp_time" =~ ^[0-9.]+$ ]] || ! [[ "$decomp_time" =~ ^[0-9.]+$ ]]; then
echo "错误: 无法获取有效的时间数据 for $label"
return 1
fi

# 获取大小信息 (ext4不支持compsize,使用du替代)
if [ "$fs_type" = "btrfs" ]; then
usage=$(compsize /mnt | awk '/TOTAL/ {print $2, $3}')
else
# 对于ext4,Ratio设为1.0,压缩后大小等于原始大小
compressed_size=$(du -bs /mnt | cut -f1)
ratio=$(echo "scale=2; $compressed_size / $DIR_SIZE" | bc)
usage="$ratio $compressed_size"
fi

# 计算速度 (MiB/s)
comp_speed=$(echo "scale=6; ($DIR_SIZE / 1024 / 1024) / $comp_time" | bc)
decomp_speed=$(echo "scale=6; ($DIR_SIZE / 1024 / 1024) / $decomp_time" | bc)

# 格式化输出
speed=$(printf "%.3f MiB/s | %.3f MiB/s" $comp_speed $decomp_speed)
printf $OUTPUT_ROW "$label" ${=usage} "$speed"

umount -q /mnt
}

# 输出表头
printf $OUTPUT_ROW "文件系统/算法" "压缩比" "压缩后大小" "压缩速度" "解压缩速度"

# 加载ramdisk模块 (2GB大小以确保能容纳测试数据)
modprobe brd rd_size=$((1*1024**2)) max_part=1 rd_nr=1

# 测试ext4
bench ext4 "defaults" "ext4"
echo

# 测试无压缩Btrfs
bench btrfs "compress=none" "btrfs (无压缩)"
echo

# 测试LZO压缩Btrfs
bench btrfs "compress=lzo" "btrfs (lzo)"
echo

# 测试不同级别zstd压缩Btrfs
for i in {1..6}; do
bench btrfs "compress=zstd:$i" "btrfs (zstd:$i)"
done
echo

# 测试不同级别强制zstd压缩Btrfs
for i in {1..6}; do
bench btrfs "compress-force=zstd:$i" "btrfs (zstd-force:$i)"
done
echo

# 清理
rmmod brd

echo "测试完成"

前决条件

运行此脚本前,你需要安装以下包:

  • zsh
  • btrfs-progs
  • hyperfine
  • compsize
  • jq
  • bc

你还需要下载silesia测试集,并将其解压至/tmp/silesia/下。

silesia数据集是一个专门用来测试压缩算法的数据集,包含了各种格式与编码的内容,可以模拟日常使用中用户可能使用的各类文件,确保压缩算法的鲁棒性、通用性。

你最好不要在/mnt上挂载设备,因为这个脚本即将在/mnt上创建临时文件系统。

为了确保结果准确,测试过程中不要使用电脑。

结果展示

屏幕截图_20250808_075325

实际上图片中我没有测试完就结束运行了,因为上次测试发现,zstd压缩级别大于5时压缩后大小几乎不下降而读写速率持续下降。

从结果来看,无压缩的btrfs已经在读写速率上存在小幅下降,lzo压缩算法取得了还算不错的压缩率,而读写速率也有所下降。

可是我最看好的是压缩级别为1的zstd压缩。此时压缩率较lzo压缩有较大增长,而读写速率也有小幅下降,大于一的时候,读写速率持续下降,但是压缩率似乎已经达到极限了。

基于此,我最终选择了zstd压缩,压缩级别为1.

持久化设置

我们通过一个使用脚本完成了对压缩算法与级别的选择。可是如果想要应用压缩,需要在每次mount挂载时手动输入参数,否则就不会应用压缩。这对我来说是不可接受的,因为我已经习惯了在dolphin(文件管理器)里点击设备,自动挂载访问了。

那么有没有办法自动化应用挂载参数呢?

有!

答案在于/etc/fstab,linux已经提供了这样一种设置方式。

这个文件记录了某一个特定设备在挂载时应该挂载于什么目录,是什么文件系统,需要使用怎么样的参数。

这个文件非常重要,如果损毁将无法开机。在修改前建议先备份。

你应该会发现该文件每一行格式都如下:

1
<file system>	<dir>	<type>	<options>	<dump>	<pass>

<file system>可以用/dev/sda1这样的设备名确定,但我更喜欢使用UUID,这样不容易出错。可以用sudo lsblk -f查看:
屏幕截图_20250808_160558
UUID那一栏的内容,复制下来。

<dir>指定了该文件系统应该挂载于什么目录,它必须存在,否则会挂载失败。需要提前创建好。

<type> 写明文件系统。

<options>是这里的主角。如果你的fstab里已经有条目了,只需要增加compress=zstd:1就好了。

顺便推荐另外几个用于SSD上的btrfs参数:ssd,discard=async,space_cache=v2

<dump> 指定dump工具是否要备份此文件系统,一般我们都不用,置零即可。

<pass>指定需要检查的文件系统的检查顺序。允许的数字是0, 1, 和2。 根目录应当获得最高的优先权 1, 其它所有需要被检查的设备设置为 2. 0 表示设备不会被 fsck 所检查。

btrfs文件系统建议全部设置为0,因为btrfs的fsck是不起作用的。

btrfs支持在线检查,请在启动后使用btrfs scrub检查文件系统。

保存之后,重启生效。

压缩效果

你可以用之前安装的compsize检查压缩效果:

屏幕截图_20250808_161914

命令为:

1
compsize -x <路径>

-x表示不跨越文件系统,不加上可能会报错:

/boot/EFI/Microsoft/Boot/bg-BG/bootmgfw.efi.mui: Not btrfs (or SEARCH_V2 unsupported).

因为EFI分区使用了fat32文件系统。

从数据可以看出,在我的系统上,btrfs节省了6GB空间,可是要知道目前我整个系统,带上我一些文件一共只使用了19GB左右。(点名Windows)

总体来说,还是很满意的,吞吐量的减少对我的影响也不大。

你学会了吗?快利用酷酷的btrfs特性吧!

评论

留下神评妙论