Profiler告诉函数调用开销是正常语句的10倍

时间:2017-08-14 14:08:27

标签: c++ visual-studio function c++14 overhead

我得到一个配置文件结果表明调用函数的开销非常大 它目前是我计划的瓶颈。

该函数位于模板类中: -

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%
}                                   

enter image description here
(^图像被编辑了一点,以保护我免受老板的伤害。)

问题

有可能吗?分析器错了吗?
如果是这样,如何优化呢? 我尝试了inline关键字(没有不同)。这个功能已经是内联的,不是吗?

我正在使用Visual Studio 2015的分析器(优化-O2) 结果与How much overhead is there in calling a function in C++?非常不一致。

修改:我确认Profiling Collection = Sampling(不是Instrumention)。

1 个答案:

答案 0 :(得分:2)

假设您在Visual Studio中使用默认的 sampling 分析方法。

此类分析器通常在程序集级别工作,例如,通过定期对当前指令指针进行采样。然后,他们使用调试数据尝试将数据映射回源代码行。对于经过大量优化和内联的代码,此映射并不总是可靠的(实际上,某些指令源可能不是来自任何行,或者可能有效地在多个行之间共享)。

除了使分析变得棘手之外,这也意味着诸如“函数调用具有正常语句的10倍开销”之类的语句并不真正有意义:没有“典型”函数调用,并且当然没有典型的“正常语句” ”。功能可以从完全免费(内联甚至消除)到有些昂贵(错误预测的虚拟调用 1 )和语句跨越更大范围从免费到几乎无限制的成本(但是常见的) case将是一个缓存未命中数百个周期。)

最重要的是,采样方法通常具有固有的误差或偏差。例如,昂贵的指令可能倾向于将其样本扩展到后续指令中,而不是自己分配所有样本。这会在指令级别导致额外的错误。

所有这些加起来意味着虽然采样结果对于宽中笔分析(即识别数百个周期的特征)可能非常准确,但您不能总是读取太多细粒度的结果比如你上面的单行函数。

如果你想要阅读这些结果,第一步是see if the sampling mode has an assembly level view并使用该视图,因为至少那时你完全删除了程序集到源的映射问题。

1 在C ++中有没有可以合理地被视为“函数调用”的东西?