为什么 __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++-7
和 g++-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
工具有一些影响)
google-pprof
的行分析输出声称我的数值 C++ 程序的大部分 运行 时间都花在了一个名为 __nss_database_lookup
的函数上(见下文)。显然,该函数用于处理诸如 UNIX 系统上的 passwd
文件之类的事情。我的 C++ 程序应该只进行数值计算、分配内存和传递一些自定义 C++ 数据类型。
这是怎么回事?该函数的出现是海市蜃楼,仅仅是 google-pprof
工作原理的产物吗?或者它实际上被调用并浪费了我程序 运行 三分之二的时间?如果它正在被调用,那么调用它的是什么?在我的 C++ 类 中有什么东西错误地调用了它吗?我该如何追踪?
我正在使用 Ubuntu 20.04、g++-7
和 g++-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
工具有一些影响)