本文记录了作者Linus Heckemann在NixOS虚拟机测试中发现QEMU文件复制速度缓慢,并通过优化代码将其速度提升10倍的经历。
**背景**
NixOS使用QEMU虚拟机进行测试,通过9p文件系统共享Nix store来避免重复创建磁盘镜像。作者遇到一个复制大量文件(278k个文件,5.3GiB)的测试用例,发现耗时过长(超过2小时),主要原因是9p文件系统的文件复制速度缓慢。
**性能分析**
作者尝试使用GDB进行性能分析,但由于Nix使用Linux命名空间隔离构建环境,导致GDB无法获取到目标进程信息。通过创建新的挂载命名空间并挂载proc文件系统,作者成功解决了这个问题。但是,使用这种“穷人版”的性能分析方法,并没有获得太多有用的信息。
**火焰图分析**
作者最终使用perf工具生成火焰图,发现QEMU中9p文件系统的fid相关函数占据了大量时间。fid类似于POSIX文件API中的文件描述符,用于表示打开的文件。
**问题定位**
QEMU中的get_fid函数使用链表来查找fid对应的文件数据,时间复杂度为O(n),当打开文件数量较多时,性能会很差。这正是导致文件复制缓慢的原因。
**解决方案**
作者使用glib库的哈希表来替换链表,将查找fid的时间复杂度降低至O(1)。
**代码贡献**
作者将修改后的代码贡献给QEMU项目,并经历了多次提交和审查。
**成果**
通过本次优化,QEMU的9p文件系统性能得到了显著提升,测试用例的运行时间从超过2小时缩短至7分钟。作者也从中积累了丰富的经验,包括使用perf分析性能、贡献代码给开源项目、以及9p协议的相关知识等。
**总结**
作者鼓励大家勇于解决遇到的问题,即使对代码和技术不熟悉,也可能获得意想不到的成果。开源软件的魅力在于,每个人都可以参与其中,解决问题,并为其他人带来便利。