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.)
我正在尝试优化我编写的程序,该程序旨在通过将数据包发送到指定的 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.)