每个玩家在安装你的游戏时都会解压你的资产包。每次冷启动、每次加载关卡、每次流式加载纹理时,都是在别人的CPU上、别人的电池上,面对一个loading条时发生的解码过程。你在一个你控制的构建机器上压缩这些资产一次。它们在别人的硬件上百万次被解压。
大多数编解码器都不会利用这种不对称性。LZ4是为对称速度而设计的(log流式,RAM分页)。Zstd在整个比率/速度曲线上进行了调优。两者都很棒——但对于已发布的游戏资产,压缩时间是被平均化的,而解码时间才是玩家感觉到的唯一数字。
ZXC是一款小型BSD-3 C库,围绕着这个单一的权衡建构。它在构建时花费了额外的努力——更重的匹配选择、最佳的解析、一个现代CPU管道中布局的比特流——以换取更快的解码时间。
具体来说,在Silesia语料库(lzbench 2.2.1,单线程):
- 苹果M2,快速关卡:ZXC解码速度约为12,890MB/s,LZ4在相同比率下解码速度约为5,620MB/s,约为2.3倍,文件大小微小。
- 最近的x86(Zen 5):约2.0倍。ARM云(Graviton/Axion类):约1.9倍。
- 比率等级上升时,差距会缩小;每个CPU表(以及具体命令)都在repo中,所以你可以检查方法论,而不是仅仅是标题。
ARM是最明显的优势,正好与玩家实际位置一致:手机、Switch类硬件、苹果Silicon笔记本。
这个实际上对游戏有帮助的地方
可寻址归档。将千个资产打包到一个文件中,然后在O(1)时间内从归档中取出任何一个资产,而无需扫描整个归档:
# 构建时:使用可寻址表打包
zxc -z -S -5 assets.tar assets.tar.zxc
在运行时只需膨胀所需的块——玩家刚刚走进房间时的纹理——而不是整个包。这个就是“解压关卡”和“解压屏幕上显示的东西”的区别。
字典用于小资产。如果你压缩大量小、相似的载荷(JSON配置、对话树、小精灵、保存块),每个块通常都会以冷启动的形式开始,没有历史可以与之匹配。训练一个字典一次,从代表性样本中学习:
zxc --train -o assets.zxd samples/*.json # 训练一次
zxc -z -D assets.zxd config.json # 使用它压缩
zxc -d -D assets.zxd config.json.zxc # 解压(字典是必需的)
块越小(它目标4K–128K范围),收益越大——小块正是编解码器通常没有什么可用的情况。
在你的引擎中
在热循环中,你不希望每个资产都有一个malloc/free。创建一个解码上下文一次,重复使用它:
#include "zxc.h"
zxc_dctx* dctx = zxc_create_dctx(); // 一次,载入时
// 每个资产:
int64_t n = zxc_decompress_dctx(dctx, comp, comp_sz, out, out_cap, NULL);
zxc_free_dctx(dctx); // 解体时
缓冲区是由调用者分配的,并带有一个明确的容量——没有惊喜分配,没隐含的状态——而一个损坏的资产会返回一个n < 0值,而不是一个损坏的堆栈。对于工作系统来说,有一个警告:上下文不能跨线程共享。给每个工作者一个自己的dctx(它们很便宜),或者使用无状态的单次zxc_decompress()——无论哪种方式,解码路径中都没有锁。
不是C/C++?有官方的Rust、Python、Node和Go绑定,有一个WASM构建,有社区的Nim和Free Pascal端口。引擎方面:它直接插入到Unreal和自定义C++引擎中,通过P/Invoke将其插入到Unity中,将其插入到Godot中通过GDExtension。
真实的一面
ZXC的压缩速度在顶级中非常缓慢——级别6大约为11MB/s。这是交易:你在构建机器上支付一次,以便玩家永远不会。你的资产管道在CI中运行,并缓存输出,你不会感到它。如果你需要在运行时重新压缩,ZXC不是正确工具——使用LZ4或Zstd的快速级别。
并且它不是一个干净的胜利:在最大密度等级上,lz4hc -9仍然在老的Zen 3 x86上比ZXC的解码速度快约6%(ZXC在比率上赢得了,ZXC在每个ARM核心上都赢得了)。了解你的目标硬件。
对于已发布的游戏资产,目标是玩家手机、游戏机或笔记本——正是ZXC的不对称性所带来的优势。
在你的资产包上尝试
唯一重要的基准是你的资产,而不是Silesia:
brew install zxc # 也在vcpkg / conan / cargo / pip / npm上
zxc -b your_asset_pack # 基准模式:速度 + 比率在你的数据上
如果你不想相信我的数字,ZXC在lzbench和TurboBench中,因此你可以将其与70+个编解码器进行比较。代码、格式规范和完整基准表都在repo中——欢迎在评论中提问有关格式或解码路径。
评论 (0)