#tera #client #game-client #online #fragment #command-line-tool

bin+lib tera-client-packer

一个用于打包、压缩和碎片化TERA Online客户端文件的命令行工具

1个不稳定版本

0.1.2 2023年10月20日
0.1.1 2023年10月20日

#258压缩

MPL-2.0 许可证

19KB
300

tera-client-packer

一个命令行工具,用于压缩和碎片化TERA Online游戏客户端文件。允许用户更快地下载和解包游戏,节省带宽和时间。该工具还提供了一个Rust库,以便以编程方式执行相同的操作。

它是如何工作的?

tera-client-packer pack [OPTIONS] <INPUT_DIR>

Arguments:
  <INPUT_DIR> - Parent directory where the client files are located

Options:
  -w, --workers <usize>             Worker count                              [default: 8]
  -n, --package-name <string>       Output package name                       [default: client]
  -e, --package-extension <string>  Output package extension                  [default: cabx]
  -s, --package-size <u64>          Output fragment size in MB                [default: 500]
  -o, --output-dir <Path>           Path where package files will be dumped   [default: ./packed]
  -c, --compress                    Flag for compression (unused)
tera-client-packer unpack [OPTIONS] <OUTPUT_DIR>

Arguments:
  <OUTPUT_DIR> - Top Level directory where the client files will be unpacked

Options:
  -i, --input-dir <Path>  Input directory where package files are contained [default: ./packed]
  -m, --manifest <Path>   Define a custom manifest file for unpacking       [default: ./_manifest.json]
  -w, --workers <usize>   Thread count for multithreaded use                [default: 8]

程序为每个线程读取大约 package-size * 2 的数据,因此如果包大小设置为 500mb,则 8个工作线程 的总内存使用量约为 8-10 GB

它做了什么?

这是一个用于通过启动器或安装程序分发游戏客户端文件的打包工具。专为TERA在线游戏设计,但可以用于任何其他目的。

为什么它存在?

我在学习Rust语言的同时,对Menma's TERA客户端如何管理安装和补丁进行了实验。注意到了他们当前实现中的几个令人困惑的问题

  • 文件没有被压缩,尽管他们计划实现压缩(通过其清单中的压缩标志字段明显),导致文件大小增加了20.57%,大约增加9~10GB的数据下载。 虽然目前我的解决方案中尚未实现,但我计划在不久的将来支持Gzip和/或LZMA压缩 现在默认启用并实现了Gzip压缩。
  • 源文件以某种方式碎片化,以便它们可以分布在多个包文件之间,试图使部分字节数相等。这在大多数情况下是可以接受的,但会严重影响多线程解包性能,因为当您处理(解包)这些文件时,工作负载必须等待写入锁在分割的目标文件上。

多线程实现细节

我目前有一个多线程IO和压缩的工作原型,但可以进一步优化。程序按顺序读取文件,并在达到package-size字节的倍数时存储缓冲区以进行处理。为了内存优化,程序管理一个大小为worker_count + 1的线程池和长度为worker_count的缓冲队列。因此,所有时间使用的内存量将保持在大约worker_count * package_size * 2的稳定水平,当然这包括存储的任务缓冲区和并发处理的字节流。

可能可以用其他一些内存使用方法做得更高效,但这比顺序执行写操作要好得多。

基准测试

所有测试都在补丁100.02的客户文件上运行,是干净的Gameforge发布版本,ReleaseRevision.txt的md5哈希值为0396410868EDE6E05F8DEDC5142E93EB,并将package-size选项设置为500mb

打包器

运行时间 压缩 持续时间 结果
单线程 无压缩 1分37秒 66.9 GB (100.00%)
单线程 Deflate 2小时32分44秒 59.5 GB (88.94%)
多线程(16线程) Gzip(默认值) 37分18秒 58.6 GB (87.29%)
* 多线程(16线程) Gzip(默认值) 3分33秒 58.6 GB (87.29%)

*优化发布目标构建

解包器

运行时间 压缩 持续时间
多线程(16线程) Gzip(级数6) 5分50秒

已知问题

  • 进度条非常不直观,经常看起来像程序挂起,尽管它并没有。
  • 没有内存限制的强制执行,程序通常消耗大约package-size * workers * 2.10 MB的内存,使用这些选项时请谨慎。
  • 目前没有当前包哈希功能,如果打算分发输出,这是必须的。
  • 输出目录或清单文件的名称目前不可定制,分别默认为cwd_manifest.json

依赖项

~5–13MB
~143K SLoC