我得到一个配置文件结果表明调用函数的开销非常大 它目前是我计划的瓶颈。
该函数位于模板类中: -
template<class U> class CustomArray{
....
public: U& operator[](int n){ //<-- 2.8%
... some cheap assertion ... //<-- 0.2%
return database()[n]; //<-- 0.3% (just add address to allocated mem)
} //<-- 2.7%
}
有可能吗?分析器错了吗?
如果是这样,如何优化呢?
我尝试了inline
关键字(没有不同)。这个功能已经是内联的,不是吗?
我正在使用Visual Studio 2015的分析器(优化-O2
)
结果与How much overhead is there in calling a function in C++?非常不一致。
修改:我确认Profiling Collection
= Sampling
(不是Instrumention
)。
答案 0 :(得分:2)
假设您在Visual Studio中使用默认的 sampling 分析方法。
此类分析器通常在程序集级别工作,例如,通过定期对当前指令指针进行采样。然后,他们使用调试数据尝试将数据映射回源代码行。对于经过大量优化和内联的代码,此映射并不总是可靠的(实际上,某些指令源可能不是来自任何行,或者可能有效地在多个行之间共享)。
除了使分析变得棘手之外,这也意味着诸如“函数调用具有正常语句的10倍开销”之类的语句并不真正有意义:没有“典型”函数调用,并且当然没有典型的“正常语句” ”。功能可以从完全免费(内联甚至消除)到有些昂贵(错误预测的虚拟调用 1 )和语句跨越更大范围从免费到几乎无限制的成本(但是常见的) case将是一个缓存未命中数百个周期。)
最重要的是,采样方法通常具有固有的误差或偏差。例如,昂贵的指令可能倾向于将其样本扩展到后续指令中,而不是自己分配所有样本。这会在指令级别导致额外的错误。
所有这些加起来意味着虽然采样结果对于宽中笔分析(即识别数百个周期的特征)可能非常准确,但您不能总是读取太多细粒度的结果比如你上面的单行函数。
如果你做想要阅读这些结果,第一步是see if the sampling mode has an assembly level view并使用该视图,因为至少那时你完全删除了程序集到源的映射问题。
1 在C ++中有没有可以合理地被视为“函数调用”的东西?