我的 gprof 输出中的这些 c++ std 函数是啥,它们需要花费大量时间?

Posted

技术标签:

【中文标题】我的 gprof 输出中的这些 c++ std 函数是啥,它们需要花费大量时间?【英文标题】:What are these c++ std functions in my gprof output which are taking quite a lot of time?我的 gprof 输出中的这些 c++ std 函数是什么,它们需要花费大量时间? 【发布时间】:2020-04-25 14:55:53 【问题描述】:

gprof 输出。我在我的代码中使用了双端队列,std::vectorstd::move

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
 10.70      0.78     0.78 411724776     0.00     0.00  __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator*() const
  5.97      1.22     0.44 114087996     0.00     0.00  __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator--()
  5.90      1.65     0.43 256602502     0.00     0.00  __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::base() const
  5.90      2.08     0.43 197352626     0.00     0.00  std::remove_reference<int&>::type&& std::move<int&>(int&)
  5.76      2.50     0.42    20556     0.00     0.00  void std::__move_merge_adaptive<int*, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__ops::_Iter_less_iter>(int*, int*, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__ops::_Iter_less_iter)
  5.49      2.90     0.40 139505351     0.00     0.00  __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator++()

【问题讨论】:

你在编译优化吗? 好吧,我做到了,所有这些功能都从 gprof 输出中消失了。怎么样? 【参考方案1】:

这些函数是标准库的实现细节。既然你在分析,你想在编译器中启用优化,否则编译器基本上不会注意试图让你的程序运行得很快,它只是想让它易于调试。启用优化后,您应该会看到这些函数消失,因为编译器意识到它们可以被内联,从而消除了函数调用开销。

【讨论】:

实际上我确实启用了优化并且那些函数调用消失了。【参考方案2】:

我希望 Vaughn 是对的,但根据我的经验,它并不总是有效。事实上,据我所见,它几乎永远不会奏效。由于在调试构建中您无法看到该代码,因此程序员倾向于假设这些东西是内联的,而实际上它们可能不是内联的。一种检查方法是在其他 DEBUG 构建中打开优化,并检查生成的反汇编代码。

编译器通常无法判断程序员的意图,因此它会坚持安全的内容。例如,程序员可能知道数组索引在数组边界内甚至是常量,但这并不意味着编译器可以弄清楚。

这是您使用标准库模板时的问题。 我知道鼓励人们使用它们是因为他们发现了初级编程错误,但您为它们付出的代价并没有消失。

【讨论】:

以上是关于我的 gprof 输出中的这些 c++ std 函数是啥,它们需要花费大量时间?的主要内容,如果未能解决你的问题,请参考以下文章

为啥循环摘要在 gprof 的调用图输出中没有任何调用者?

C++ 成员函数指针和 STL 算法

关于gprof和gprof2dot生成的图的一些疑惑

gprof 输出问题

使用 SWIG 在 Python 中公开 std::list 成员

C++ main 只使用约 20% 的时间说 gprof