What is the cost of calling many functions?

9
Recently, in the face of a discussion on Clean Code and best programming practices, a co-worker commented that in his previous job there was a lot of resistance from other programmers to begin dividing code and make it more readable.

The main reason for the resistance has always been that many function calls would stack a lot of data in stack and consequently lose a lot of performance.

In particular, I do not see how a function call can have such a negative impact, but I say this based on an experience primarily of high-level languages like Java, C # and PHP. Considering the use of a low-level language (where I can actually manage memory) as C or C ++:

What's the cost of calling 10 more functions?

How do I calculate the amount of memory I spent on this operation?

Detail : In my understanding, the difference in performance is extremely negligible, so I am merely interested in how to calculate the cost of calls.

    
asked by anonymous 15.02.2017 / 20:29

3 answers

11

Performance

The cost of calling function is small or large depending on how you look. In generates the cost is to save some registers in memory (most likely it will be in the L1 cache which is very fast, and then recover the original state of the registers.

In addition there may be data copies because of the parameter pass. If this would not happen if it were not a function it depends.

Under certain circumstances the compiler can linearize the function , that is, instead of calling it (< in> call ) it copies the function code to the place it was calling. You will achieve readability and performance.

If the compiler does not do this, it is because it can not (okay, there are situations that the human knows that it can and the compiler does not) or does not compensate for the inline function.

In the linked question above I say this. If the function is not lowercase and run for a very short time does not compensate. It also does not pay to optimize what will be called a few times, but this is not always the case for the compiler.

The programmer may know until something is called many times but actually in a lot of place that there is natural waiting, so performance does not matter at all.

It is true that on devices with reduced resources it may be useful to do a little more optimization. Optimization can be much worse in these cases because gaining performance loses memory and low memory greatly affects performance. And one of the scarce resources is battery power. Faster code is usually more economical code.

In the past, when computers were less powerful, this was far more important.

The performance is negligible in most cases and where it is not the compiler helps you. Of course there may be if the performance is bad. But most likely the algorithm is bad and not the call of the function that is in the way.

There are cases where the linearization of the function can cause extra costs and what seemed a certain performance gain, gives the opposite. And as the difference is very small, the programmer "smart" who did what he thought would give a better performance ends up not even realizing that he did the worst, although this worse also will not disturb anything.

Readability

I will never say forever prefer to reproduce the code than to call it, but rarely does this need to be done, and only do so after verifying that the performance is not as expected (you have to measure it). The cost of optimizing may not outweigh the gain. Because maintenance becomes more difficult. You break the DRY .

Of course between the readability with less performance and the legible with more performance I prefer the one with more performance. But copying the code to avoid the call will hardly be more readable than calling it.

Languages

If a person uses PHP primarily, or Java or C #, they do not want maximum performance. These languages can be fast, they can benefit from this optimization, but it is not so common to need this. When you need a lot of performance in general C or C ++ is preferred. In this language it makes more sense to eliminate function calls, but depends on the application, it depends on the point of the application.

Memory

The question talks about memory consumption as well. The function will use more memory to save the registers and may also spend a little more because of the parameter copy, but not always. If the code was right this does not matter, because the memory used is stack which is already allocated using it or not.

Profilling

You need a profiler to check how the code is running and to indicate the costs. Valgrind is best known for Linux and Windows should probably be using Visual Studio which has a profiler .

There are other ways, but this is the most accurate and correct.

    
15.02.2017 / 21:10
6

Significant performance differences because of stack size execution would only make sense in a few cases. The ones I can list that are realistic are these:

  • Intensive use of recursion at very deep levels.

  • Code that runs on devices with very little available memory and very low computing power.

  • Calling functions within loops that perform heavy computations.

  • There are scenarios that combine more than one of these cases above, but most likely you are not falling into any of these cases, and therefore doing code micro-optimizations without having a solid foundation of knowledge based on concrete evidence ends up being stupid . Often these micro-optimizations end up having the opposite effect, meaning they slow down the code.

    In addition, C ++ compilers are very smart, sooooo smart. Modern C ++ compilers were developed by the hard work and collaboration of thousands of extremely competent and intelligent people in what they did and they are able to see optimization opportunities and possibilities far beyond what most experienced C ++ programmers and assemblers would be capable of. There are a lot of optimizations that apply to such cases and related cases, such as inlining, allocating registers for most commonly used variables, loop unwinding, tail recursion, caches, and a whole bunch of other things.

    Even in the 3 scenarios above, if you fall into cases 1 and 3, the problem is probably not the use of functions but the way they are organized.

    If you fall back on case 2, you probably will not be thinking of optimizations related to the size of the execution stack, but instead squeeze as many bits as possible into the smallest possible space by looking at the project at the hardware level, considering things like positioning transistors in a microchip, power consumption, heat generation, etc.

    Again, probably your case is none of these.

    And to be sure, if the conversation actually gets into performance / performance as a crutch or ragged excuse to tamper with or tamper with the code, it is important to take measurements. Estimating performance and performing optimizations is something that requires evidence, evidence, and experiments carried out with methodological rigor, that is, it is science . Going simply in the limelight of disobeying good practices because that supposedly would produce a performance is fallacious and reckless.

    In addition, most performance problems that exist in the real world (and not the imaginary problems invented by those who do not want to follow good programming practices) have no relation to whether or not you are making functions or procedures. These are problems that usually involve algorithm designs, memory or disk data organization, threads, information caching, distributed systems, synchronous versus asynchronous processes, and other things that are related to the project architecture, not to small details about to the size of the execution stack when making 10 calls to a function.

        
    15.02.2017 / 21:03
    4

    I suggest doing looping tests by measuring the total time of at least 1 million iterations.

    Even in high-level languages, as mentioned, such as Java, in which I have reasonable experience, the total call time, without I / O operations should not come close to 1 second.

    On stacking a lot of data on the stack, with the current computational power this is irrelevant. I have already developed in languages where the concern with the size of the recorded data records was very large, since in the past the storage offers were much lower. But to this day, I had never seen anyone pay attention to the cost of calling functions at the expense of code quality, and especially ease of maintenance and evolution.

        
    15.02.2017 / 21:01