在分析 drivers/dma-buf/heaps/system_heap.c 的代码时,我们发现其 system_heap_mmap 函数存在明显的性能瓶颈。该函数在处理 dma-buf 的 scatter-gather (sg) 列表时,采用了逐页(page-by-page)进行内存映射的方式。

如代码所示,它遍历 sg 列表中的每一个条目(entry),并在每个条目内部再逐个页面调用 vm_insert_page。这种方式效率较低,因为一个 sg entry 本身可能就代表一大片连续的内存区域(例如一个 8-order 的复合页)。逐页操作不仅增加了函数调用开销,也未能充分利用内存的连续性。
优化的核心思路是将“逐页映射”改为“批量映射”。即一次性映射整个连续的 sg entry 区域,而非其中的每个独立页面。这涉及到对 Linux系统 内存管理机制的深入理解。主要的挑战在于处理各种边界不对齐的情况,例如 mmap 的起始地址可能位于一个大 order 内存块的中间某个页面,而非其起始位置。
经过对边界条件的完整处理,优化后的核心代码如下,它能够识别连续的内存块并进行批量映射:

为了量化性能提升,我们编写了一个微基准测试(micro-benchmark)来对比优化前后的 mmap 操作耗时:

测试结果对比如下:

测试数据显示,应用优化补丁后,mmap 操作的耗时降低了约 35倍(最初在提交日志中误记为3.5倍)。性能提升的幅度取决于内存的碎片化程度;在最理想的情况下(内存连续性好),提升可达40倍以上;而在极端碎片化(全是0-order页面)的场景下,则可能没有提升。
考虑到现代计算场景,尤其是在AI大模型应用中,dma-buf 的尺寸可能非常庞大,此项优化对于减少内存映射延迟、提升整体系统性能优化响应能力具有积极意义。
该补丁已由子系统维护者修正了性能倍数的描述,并成功合入 DMA-BUF 子系统仓库 [2],预计将随 Linux 内核主线版本 6.19 发布。
参考链接
|