2

I got a profile result states that overhead of calling a function is very large.
It is currently a bottle neck of my program.

The function is in a template class :-

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
(^ The image was edited a little to protect me from my boss.)

Question

Is it possible? Is profiler wrong?
If so, how to optimize it?
I have tried inline keyword (no different). This function is already inline, isn't it?

I am using Visual Studio 2015's profiler (optimization -O2).
The result is very inconsistent with How much overhead is there in calling a function in C++?.

Edit: I confirm that Profiling Collection = Sampling (not Instrumention).

cppBeginner
  • 1,114
  • 9
  • 27
  • Are you using the sampling or instrumenting profilers? – BeeOnRope Aug 14 '17 at 14:18
  • @BeeOnRope I believe it is sampling. I will find a way to check it. Thank. – cppBeginner Aug 14 '17 at 14:20
  • It looks like you might not be using plain old 'assert' from . I have a custom assert which I created, and I recently discovered that my custom assert's 'success-do nothing' is surprisingly slower than the success side assert of . If you have a suitable test environment, you might try plain for comparison. FYI - I did not profile, I just measured duration of a lot of them. – 2785528 Aug 14 '17 at 14:40
  • @DOUGLAS O. MOEN Thank a lot, I never heard about it. Yes, I use custom assertion. – cppBeginner Aug 14 '17 at 14:44

1 Answers1

2

Let's assume you are using the default sampling method of profiling in Visual Studio.

Such profilers usually work at the assembly level, for example, by sampling the current instruction pointer periodically. They then use debug data to try to map that data back to source lines. For heavily optimized and inlined code, this mapping isn't always reliable (indeed, some instruction origin may not originate from any line, or it may effectively be shared among several).

In addition to making profiling tricky, this also means statements like "function call has a 10x overhead of a normal statement" isn't really meaningful: there is no "typical" function call and there certainly is no typical "normal statement". Functions can vary from totally free (when inlined or even eliminated), to somewhat expensive (mis-predicted virtual calls1) and statements span an even greater range from free to almost unlimited in cost (but a common case would be a cache miss taking hundreds of cycles).

On top of that, sampling methods often have inherent error or skew. For example, an expensive instruction may tend to spread its samples out among subsequent instructions rather than being assigned all the samples itself. This leads to additional error at the instruction level.

All this adds up to mean that while sampling results may be quite accurate for broad-stroke profiling (i.e., identifying features on the order of hundreds of cycles), you can't always read too much into very fine-grained results such as your one-line function above.

If you do want to read into those results, the first step is to see if the sampling mode has an assembly level view and to use that view, since at least then you remove entirely the assembly-to-source mapping issue.


1 Is there anything worse that could reasonably be considered a "function call" in C++?

BeeOnRope
  • 60,350
  • 16
  • 207
  • 386
  • Thank. Do you happen to know how to look at the mentioned profiled assembly from the profile c++ result, in Visual Studio? I have tried right-click randomly in the profiled window. – cppBeginner Aug 14 '17 at 14:29
  • 1
    @cppBeginner - no, but I asked a [question](https://stackoverflow.com/questions/45676799/does-the-visual-studio-sampling-profiler-have-an-assembly-level-view) about it. – BeeOnRope Aug 14 '17 at 14:31