Sign in to follow this  
Tispe

Create variables inside or outside loops?

Recommended Posts

I often come by code where people recreate variables for each iteration ex:
[code]
int main()
{

//main loop
while(true)
{
bool Foo = false;
/*

code

*/
}

return 0;
}
[/code]

How does this effect performance? Why would you recreate a variable 1000 times over in a second when you can create it once outside it? ex:
[code]
int main()
{
bool Foo = false;
//main loop
while(true)
{
Foo = false;
/*

code

*/
}

return 0;
}
[/code]

Share this post


Link to post
Share on other sites
Creating it outside the loop will give you extra performance if its executed a lot, if, lets say, it was executed in the initialization of some application then it doesn't really matter. But yeah, declaring them outside the loop will increase performance.

Share this post


Link to post
Share on other sites
With the optimiser turned on, there's every chance that both examples above will be equivalent. You can try it by enabling ASM output from your compiler, and writing two functions that do the same thing to see what the compiler emits.

The operation becomes a bit more nontrivial if your type isn't a simple integer though - because if it's a class, then you're asking for a constructor call for every initialisation, and the compiler might be unable to inline the constructor - and hence determine whether it can optimise it away.

So as a rule of thumb, code how you want it to be executed - you can still pull your hair out when the optimiser does something obscenely different later ;)

Share this post


Link to post
Share on other sites
It is good to be thinking about this kind of distinction, but in reality the compiler can often optimise both down to the same thing if they are equivalent.

So I might put it inside the loop when:
a. It makes the code more readable and
b. I know from seeing generated assembly/bytecode that the difference will be optimised away

Share this post


Link to post
Share on other sites
There is actually an entire class of optimizations with a specific name (that eludes me at this time) dealing with detecting the actual scope of a variable and removing unnecessary creation/assignment.

Share this post


Link to post
Share on other sites
First rule of thumb: scope all variables as locally as possible.

The only reason a loop variable should be declared outside of the loop scope is because it's used outside of the loop scope. If it is not used outside of the loop scope, declare it inside the loop scope.

If the variable is invariant within the loop scope, the optimizer will hoist it. This is one of the most basic optimizations that can be performed. If there is a complex constructor, it's probably not invariant and the optimizer will probably not be able to hoist it. Then again, if you're doing a complex operation inside a loop you probably mean to, otherwise don't do your complex operations inside the loop. Say what you mean and mean what you say.

Second rule of thumb: do not optimize prematurely.

Read what empirical results your profiler tells you and act on that, not on some [i]a priori[/i] knowledge. Follow the first rule of thumb unless you have good reason not to.

Share this post


Link to post
Share on other sites
[quote name='arbitus' timestamp='1317991942' post='4870106']
There is actually an entire class of optimizations with a specific name (that eludes me at this time) dealing with detecting the actual scope of a variable and removing unnecessary creation/assignment.
[/quote]
The fancy term is loop-invariant code motion. Usually it's just referred to as variable hoisting. It's also referred to as scalar promotion, but the other two names seem more frequent in the literature I'm familiar with.

Share this post


Link to post
Share on other sites
The CPU doesn't know anything about variables. The closest thing is a register, and the CPU actually has very few of these to work with. This means the compiler needs to determine which registers are being used, and when. In other words it expends a considerable amount of effort working out when you've stopped using a variable so it can recycle the associated register. Declaring the variable inside the loop actually makes it easier for the compiler to work out when the register can be freed (i.e. when the loop ends and the variable is out of scope). Ideally the compiler would produce identical code either way, but the existence of pointers can make it very difficult for the compiler to work out when a variable is being used. You really can't guess what's happening unless you step through the object code after compiling with optimisations on.

Now setting a variable to false every iteration of the loop will incur overhead, unless the compiler knows that the variable won't be changed during execution of the loop. Personally I wouldn't initialise and assign to a (non-const) variable inside a loop unless the variable's contents will change and needs to be reset after every iteration. It makes more sense to people reading the code if they don't get confused by a superfluous variable assignment at the start of each iteration.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this