为什么 __nss_database_lookup 在我的 C++ 数值程序中占用了大部分时间

Why does __nss_database_lookup take most of the time in my numerical C++ program

google-pprof 的行分析输出声称我的数值 C++ 程序的大部分 运行 时间都花在了一个名为 __nss_database_lookup 的函数上(见下文)。显然,该函数用于处理诸如 UNIX 系统上的 passwd 文件之类的事情。我的 C++ 程序应该只进行数值计算、分配内存和传递一些自定义 C++ 数据类型。

这是怎么回事?该函数的出现是海市蜃楼,仅仅是 google-pprof 工作原理的产物吗?或者它实际上被调用并浪费了我程序 运行 三分之二的时间?如果它正在被调用,那么调用它的是什么?在我的 C++ 类 中有什么东西错误地调用了它吗?我该如何追踪?

我正在使用 Ubuntu 20.04、g++-7g++-9

Total: 1046 samples
     665  63.6%  63.6%      665  63.6% __nss_database_lookup ??:0
     107  10.2%  73.8%      193  18.5% <function1> file.h:1035
      92   8.8%  82.6%       92   8.8% <function2> file.h:...
      87   8.3%  90.9%       87   8.3% <function3> file.h:995
      17   1.6%  92.5%      734  70.2% <function4> file.h:1128
...

(出于保密原因隐藏了函数和文件名)

我的一个朋友今天遇到了类似的问题。虽然你提出这个问题已经有一段时间了,但我还是想回答一下,以便任何到达这里的人都能得到一些提示。

这是因为调用了一些局部符号(对应C/C++中的静态局部函数),而这些符号在符号table中没有它们的入口,它们的文本(代码)放在 __nss_database_lookup 之后。所以你的 perf 工具将它们视为 __nss_database_lookup.

的一部分

例如,您的程序可能会调用 memcpy,而 memcpy 会调用 __memmove_unaligned_avx_erms,它是 glibc 中的本地符号,不会在动态符号中导出 table,它的代码恰好和其他局部符号一起放在了__nss_database_lookup之后。而你的 perf 工具找不到关于 __memmove_unaligned_avx_erms 的任何信息,所以它只是认为 __nss_database_lookup 被调用了。

一个可能的解决方案是安装 libc-dbg 包(包名可能因不同的发行版而异),如果您的 perf 工具足够智能以自动加载调试信息,它可能会正确地注释符号。 (我的朋友检查了它对 perf 工具有一些影响)