2

I have a function and several nested loops in it. Each loop uses different variable that is not used by the others.

My question is motivated by optimization considerations.

Here it is: Which approach is better?

To define local variables inside the body of the loop

void aspProtocolDetectEvents()
{
    uint8_t arrayIndex;
    for( arrayIndex = 0; arrayIndex < sizeof(__aspProtocol_events); arrayIndex++ )
    {
        uint8_t contextBitPosition;
        for(contextBitPosition = 0; __aspProtocol_events[arrayIndex] != 0; contextBitPosition++)
        {
            __aspProtocol_Event contextEvent = utils_getAbsoluteBitPosition(__aspProtocol_events, arrayIndex, contextBitPosition);
            if( __aspProtocol_isRisenEvent(contextEvent) )
            {
                __aspProtocol_dispatchEvent(contextEvent);
                __aspProtocol_clearEvent(contextEvent);
            }
        }
    }
}

Or is it better to define all of them at the beginning of the function body like this?:

void aspProtocolDetectEvents()
{
    uint8_t arrayIndex;
    uint8_t contextBitPosition;
    __aspProtocol_Event contextEvent;
    for( arrayIndex = 0; arrayIndex < sizeof(__aspProtocol_events); arrayIndex++ )
    {
        for(contextBitPosition = 0; __aspProtocol_events[arrayIndex] != 0; contextBitPosition++)
        {
            contextEvent = utils_getAbsoluteBitPosition(__aspProtocol_events, arrayIndex, contextBitPosition);
            if( __aspProtocol_isRisenEvent(contextEvent) )
            {
                __aspProtocol_dispatchEvent(contextEvent);
                __aspProtocol_clearEvent(contextEvent);
            }
        }
    }
}

I mean, I don't know if the compiler optimizes it. In aspect of code structure I would prefer the first example, but if it takes more time (for allocation each time the loop iterates) I will have to compromise, and use the second one.

Hairi
  • 3,318
  • 2
  • 29
  • 68
  • What did your profiler say? – Sourav Ghosh Mar 22 '17 at 11:18
  • @SouravGhosh Sorry, what is a profiler? – Hairi Mar 22 '17 at 11:21
  • You should take a look at generated assembler. Optimizer can do magics.. – LPs Mar 22 '17 at 11:21
  • it doesn't take too much time if you use first method, it's purely depend on compiler optimization, you can have look at assembler code after you compile both the methods. – ntshetty Mar 22 '17 at 11:23
  • 2
    Possible duplicate of [Which is the better way to declare dummy variables for nested loops?](http://stackoverflow.com/questions/42311188/which-is-the-better-way-to-declare-dummy-variables-for-nested-loops) – ad absurdum Mar 22 '17 at 11:42

6 Answers6

5

As they're locals they'll be allocated on the stack. The compiler will do this by adjusting the stack pointer when the function is called to make sure it has enough space for all the locals.

I wouldn't worry about how the space is allocated for variables in nested scopes. If you think you are seeing speed issues when using scoped locals then use a profiler to measure, but I suspect worrying about this is a classic case of premature optimization. Instead write readable and maintainable code.

Sean
  • 60,939
  • 11
  • 97
  • 136
2

Depending on the compiler, the compiler may re-use stack space. Consider the following example:

for (int i=0; i<somevalue; i++) {
    for (int j=0; j<i; j++) {
        int k[1024];
        ...
    }
    for (int j=0; j<i; j++) {
        int k[1024];
        ...
    }
}

in the i loop the variables j of the two for loops may re-use the same stack space and also the array variables k may re-use the same stack space.

So there is no performance improvement but possibly a space improvement

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
1
uint8_t contextBitPosition;

In most implementations, this shouldn't matter, performance-wise. Given that, it's best if you declare it in the tightest scope possible.


__aspProtocol_Event contextEvent = utils_getAbsoluteBitPosition(__aspProtocol_events, arrayIndex, contextBitPosition);

This matters. If the result of this operation is always the same, there is no reason to put it inside the loop. You would be better off putting it outside the loop and computing the result once.

While static analysis can theoretically figure this out and move it outside the loop for you, it would take a clever compiler.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
0

The compiler will probably optimise the code so that all variables are in function code. If it doesn't, function scope is faster because other wise you get a stack push and pop on each iteration of the loop. But the consideration should be clarity, not micro-optimisation.

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
  • 2
    It really depends on the optimizer configuration. – LPs Mar 22 '17 at 11:22
  • *"you get a stack push and pop on each iteration"* - No it doesn't necessarily mean that. Implementations can calculate and allocate the required stack frame in advance once. The only difference is which offsets from the stack pointer are used in which loop. – StoryTeller - Unslander Monica Mar 22 '17 at 11:30
  • "Function scope" doesn't mean what you think it does. In C, "function scope" refer to labels and goto. Best not to use that term at all. – Lundin Mar 22 '17 at 12:30
0

when a function call happens, memory is allocated for all its local variables, no matter where they are defined. so it won't change the execution time. defining local variables inside or outside a loop only changes their scope.(i mean, the scope that we have access to them)

read more at: journy to stack

Fatemeh Karimi
  • 914
  • 2
  • 16
  • 23
0

Where a variable is allocated in your local scope source code has no impact on performance what-so-ever.

The compiler will allocate space for the variable if it is used, at some point before the first time that variable is used. The variable might end up in CPU register or on the stack, or optimized away entirely.

Lundin
  • 195,001
  • 40
  • 254
  • 396