- 背景:NixOS 广泛使用基于 QEMU 的虚拟机运行测试套件,为避免为每个测试生成磁盘映像,测试驱动通常通过 9p 共享启动。作者在一个 VM 测试中,将大量数据从 9p 挂载的 Nix 存储中复制出来,花费了超过 2 小时,于是决定深入研究并将测试时间缩短至 7 分钟。
- 分析 QEMU:作者使用“穷人的分析器”来找出耗时的地方,遇到 gdb 在不同 PID 命名空间的问题,通过创建新的挂载命名空间解决。但分析结果未找到关键问题,于是转向 quickstack 等工具,最终通过 perf 记录性能数据生成火焰图找到问题根源。
- 问题根源:QEMU 的 9p 服务器在实现
stat
、open
、read
等操作时,通过遍历fid_list
来查找文件的fid
,时间复杂度为O(n),且fid_list
是链表结构,缓存局部性差。这导致在复制大量文件和启动虚拟机时,查找操作非常频繁,成为性能瓶颈。 - 解决方法:用 glib 实现的哈希表替代链表来存储
fid
,提供O(1)的查找复杂度,重写相关代码后,测试时间从超过 2 小时缩短至 7 分钟,NixOS 的 ZFS AWS 镜像构建时间从 19 分钟缩短至 1 分钟。 - 贡献修复:QEMU 使用邮件提交补丁的工作流程,作者在提交修复补丁过程中犯了一些错误,但最终补丁被接受。如果使用 Nix,可以通过特定的 overlay 应用该补丁。
- 成果总结:此次经历带来了诸多积极成果,如编写 Nix 包、学会使用
perf
、了解不同的分析方法、提交两个 QEMU 补丁、学会邮件提交补丁、了解 9p 协议、使测试运行更快以及获得满足感等。作者认为深入研究问题即使面对不熟悉的代码和技术也很有价值,能为开源软件做出贡献并惠及其他用户。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。