在 callgrind 输出中解释 _dl_runtime_resolve_xsave'2

interpreting _dl_runtime_resolve_xsave'2 in callgrind output

查看我的程序 运行 的 callgrind 输出,我看到了 125% !!!的周期花费在 _dl_runtime_resolve_xsave'2(显然是动态链接器的一部分),而 100% 花费在 main 中。但它也说,几乎所有在 _dl_runtime_resolve_xsave'2 内部花费的时间实际上都花在了内部方法(self=0%)上,但 callgrind 没有显示此方法的任何被调用者。 此外,看起来 _dl_runtime_resolve_xsave'2 是从我正在分析的程序中的几个地方调用的。

我可以理解,有些时间可能会花在 main 之外,因为我正在分析的程序正在使用原型模式,并且在加载动态库时正在构建许多对象原型,但这不能接近 25%那个特定 运行 的时间(因为如果我在没有输入数据的情况下这样做 运行,它所花费的时间比我现在正在分析的 运行 少几个数量级)。

此外,程序启动后未使用 dlopen 打开共享对象。一切都应该在开始时加载。

这是 kcachegrind 的屏幕截图 window:

如何解释对 _dl_runtime_resolve_xsave'2 的调用?我需要担心这种方法花费的时间吗?

感谢您的帮助。

_dl_runtime_resolve_xsave 用于延迟绑定期间的 glibc 动态加载程序。它在函数的第一次调用期间查找函数符号,然后对实现执行尾调用。除非您在启动程序时在环境中使用 LD_BIND_NOT=1 之类的东西,否则这是一次性操作,仅在第一次调用该函数时发生。惰性绑定有一些成本,但除非您有许多只调用一次的函数,否则它不会对执行成本产生太大影响。它更可能是一个报告工件,可能与尾部调用或 _dl_runtime_resolve_xsave.

中使用的相当奇特的 XSAVE 指令有关

您可以通过使用 LD_BIND_NOW=1 环境变量设置启动程序来禁用延迟绑定,将不会使用动态加载器蹦床,因为所有功能都将在启动时解析。或者,您可以 link 和 -Wl,-z,now 使此更改永久化(至少对于您 link 的代码,系统库可能仍然对它们自己的函数符号使用惰性绑定)。