如何识别 linux 系统调用 unshare(CLONE_NEWNET) 中的性能瓶颈

How to identify performance bottleneck in linux system call unshare(CLONE_NEWNET)

我有一个 linux 应用程序(用 C 语言编写),它不断地创建和删除网络名称空间。通常一个 create/delete 周期大约需要 300 毫秒。

在性能调查期间,我 运行 对程序执行 strace 以查明哪个系统调用花费的时间最多。从 strace 输出来看,似乎第一次调用 unshare 在我的系统上只需要 4 毫秒,但后续调用需要接近 200 毫秒。

strace -p <pid> -T
unshare(CLONE_NEWNET)                   = 0 <0.004150>
unshare(CLONE_NEWNET)                   = 0 <0.192055>
unshare(CLONE_NEWNET)                   = 0 <0.192872>
unshare(CLONE_NEWNET)                   = 0 <0.190303>
unshare(CLONE_NEWNET)                   = 0 <0.193062>

程序的结构使得在循环(内部控制循环)开始时,它创建一个网络名称空间并在循环结束时删除该名称空间。

为了实验,我修改了我的应用程序以在控制周期结束时不删除网络名称空间 -- 只创建新的网络名称空间但从不删除它们。这显着提高了性能,并且我在后续调用取消共享系统调用时没有任何延迟。每次unshare系统调用需要2-3ms。

strace -p <pid> -T    
unshare(CLONE_NEWNET)                   = 0 <0.003102>
unshare(CLONE_NEWNET)                   = 0 <0.002980>
unshare(CLONE_NEWNET)                   = 0 <0.003070>
unshare(CLONE_NEWNET)                   = 0 <0.003124>
unshare(CLONE_NEWNET)                   = 0 <0.002952>

显然,删除网络命名空间是某种方式 impacting/delaying 随后的网络命名空间创建。

这里可能发生了什么?我该如何进一步调试?

我正在使用 linux 内核 3.12.9-301.fc20.x86_64.

Linux ftrace 对于 debugging/profiling 系统调用非常有用。

参考以下文章

  1. http://lwn.net/Articles/365835/
  2. http://lwn.net/Articles/366796/

ftrace-cmd (http://lwn.net/Articles/410200/) 为快速调试提供了一个方便的前端。然而,对于细粒度调试,原生 ftrace 接口更好,也相当简单。

对我有用的 --

  1. 将代码检测到 enable/disable 仅在感兴趣区域跟踪点。这基本上涉及将“1”(启用)或“0”(禁用)写入 debug-fs 下的文件 "tracing-on"。
  2. 将应用程序 pid 插入 debug-fs 下的文件 "set_ftrace_pid"。
  3. 在set_trace_filter中添加一个或多个系统调用。可用符号存在于 debug-fs 下的文件 available_filter_function 中。
  4. 使用您最喜欢的示踪剂​​来归档 current_tracer。我用了 function_graph.

请注意,第 1 步和第 2 步不是强制性的,但它有助于从外部过滤大量噪音并获取与您正在调查的内容相关的数据。

综上所述,ftrace规则!!!