Perf Profiler 报告过度使用 "do_syscall_64"

Perf Profiler Reporting Excess Use of "do_syscall_64"

我正在尝试优化我编写的程序,该程序旨在通过将数据包发送到指定的 MAC 地址来复制网络流。

我的程序负责发送和删除流的主循环如下:

while (size != 0 || response) {
    for (i = 0; size != 0 && i < size; ++i) {
       curFlow = *pCurFlow;
       while (curFlow.cur_time < now) {
           // Sending Packet
           sendto(sockfd, curFlow.buff, curFlow.length, 0, \
                 memAddr, sAddrSize);

           // Adjusting Packet Attributes
           curFlow.packets_left -= 1;
           curFlow.cur_time += curFlow.d_time;

           // If the packet has no packets left, delete it
           if (!curFlow.packets_left) {
                pCurFlow -> last -> next = pCurFlow -> next;
                pCurFlow -> next -> last = pCurFlow -> last;
                size -= 1;
                break;
            }
        }
        *pCurFlow = curFlow;
        pCurFlow = pCurFlow -> next;
    }
}

我已经开始使用 perf 分析器来记录我进行的函数调用类型以及每次开销的开销。然而,每次我要求 perf 给我一份报告,结果如下:

Overhead  Command    Shared Object  Symbol
15.34%   packetize   /proc/kcore    0x7fff9c805b73   k [k] do_syscall_64
6.19%    packetize   /proc/kcore    0x7fff9d20214f   k [k] syscall_return_via_sysret
5.98%    packetize   /proc/kcore    0x7fff9d1a3de6   k [k] _raw_spin_lock      
5.29%    packetize   /proc/kcore    0x7fffc0512e9f   k [k] mlx4_en_xmit
5.26%    packetize   /proc/kcore    0x7fff9d16784d   k [k] packet_sendmsg

(注:"packetize"是我的程序名)

我的问题是,"do_syscall_64"到底是什么东西??经过一些研究,这个特定的函数似乎是一个用作中断请求的内核工具。

此外,我发现目录 /proc/kcore 负责内存管理的某些组件,尽管在有目的地用内存引用搜查我的程序时,我在程序中使用的动态库是唯一的开销从性能报告中增加。

如果您对我有任何建议,请告诉我。谢谢!

不是中断请求;它是从 syscall 入口点调用的 C 函数,它分派到适当的 C 函数,该函数实现由用户传递的寄存器选择的系统调用-space.

在这种情况下大概是sys_sendto

在 Linux 的旧版本中,x86-64 syscall 入口点直接使用函数指针的系统调用 table(例如 中所示其中只有像 int 0x80 这样的 32 位入口点使用了 C 包装函数)。

但是随着 Spectre 和 Meltdown 缓解的变化,本机 64 位系统调用入口点(从 64 位用户进入 64 位内核-space)也使用 C 包装器围绕系统调用调度。这允许使用 C 宏和 gcc 提示来控制间接分支之前的推测障碍。 do_syscall_64 on github 的当前 Linux 版本是一个非常简单的函数;除非 nr = array_index_nospec(nr, NR_syscalls); 比我在 CPU.

上预期的贵很多,否则它本身会获得如此多的循环有点令人惊讶

手写的 asm 系统调用入口点肯定会发生昂贵的事情,例如编写刷新分支预测缓存的 MSR。哦,也许缺乏良好的分支预测会在之后调用的第一个 C 函数中花费额外的周期。

系统调用密集型工作负载受到 Spectre / Meltdown 缓解措施的影响很大。尝试在其中一些禁用的情况下启动可能会很有趣,and/or 使用根本没有该代码的旧内核。

Meltdown / L1TF / 等在最新的 Intel CPUs 中完全修复,没有性能成本,因此禁用解决方法可能会给您一些线索,您可以从全新的产品中获得多少好处CPU.

(Spectre 仍然是一个非常棘手的问题,无法通过对加载端口进行本地更改来轻松解决。IDK 各种缓解微代码辅助或非缓解策略的效率的详细信息是什么各种 CPUs.)