Jump to content
  • Advertisement
Sign in to follow this  
noodleBowl

Local scope benefits

This topic is 732 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been wondering this for a while now and this is in very general terms. Including a general non-specific programming language context.
 
But which of the below is "better." Not just in speed but in practice. Is there even any real difference?
//Local scope variable outside the for loop
CoolObject obj;
for(int i = 0; i < 5; ++i)
{
	obj = coolObjectList[i];
	obj.doWork();
}

//Local scope variable inside the for loop
for(int i = 0; i < 5; ++i)
{
	CoolObject obj = coolObjectList[i];
	obj.doWork();
}

In what instance does the placement of local scope variables effect the quality of ones code?

Share this post


Link to post
Share on other sites
Advertisement

By keeping a variable's scope limited, you make the code easier to read (because you don't have to scroll so far to find a variable's declaration). It also removes a small class of errors such as accidentally using a variable where you shouldn't be able to (e.g. because you made a typo and intended to refer to some other variable). It will also declutter debugging since a debugger will only show you the variables in scope.

 

However, the variable is constructed when it is encountered and destructed when that scope is left. In your first example, CoolObject is created once, assigned to 5 times, then destroyed later. In your second example, CoolObject is created and destroyed 5 times - although whether that is significantly different from being assigned to 5 times depends on the object. (And in languages other than C/C++, assignment often has quite different semantics.)

Share this post


Link to post
Share on other sites

In the example you give, in most languages and most scenarios the work will be identical.  This is not always the case.

 

In your specific example there are some extremely basic optimizations that will be made by almost every compiler. The first is to eliminate the temporary, the second is to unroll the loop.  In both cases it will be trivially optimized to this:

 

coolObjectList[0].doWork();

coolObjectList[1].doWork();

coolObjectList[2].doWork();

coolObjectList[3].doWork();

coolObjectList[4].doWork();

 

 

In other cases where the compiler couldn't be certain about the optimizations, so it couldn't take them.

 

Removing temporary objects is a common task for compilers. Various things can prevent that. Perhaps the assignment needed to go through a custom assignment operator, then the change could make a difference.  

 

Hoisting constant values out of loops, hoisting object creation out of loops, hoisting allocation and other expensive allocations out of loops, these are very common changes to make in a code base: do something once rather than doing it many times.  In this simple case the compiler can do it for you, in more complex cases it may not.

 

Another item is that you looped a fixed number of times.  Loops have a very tiny performance impact, It is on the order of a fraction of a nanosecond each time, but doing it thousands of times every frame for millions of frames and the time accumulates. If you looped a variable number of times the compiler may not be able to unroll the loop.

 

 

 

Mainstream compilers are generally quite aggressive with optimizations, and they contain databases of an enormous number of software patterns they can quietly improve. If you see in your code that it is something you should improve, doing the work once rather than doing it in a loop, then do so.  Otherwise you can generally trust the optimizer to do its job behind your back.

Share this post


Link to post
Share on other sites

Note that in C++ the code will not do what you expect. In both operations you make a deep copy of your object and then update it. If the doWork() function will change the state of the object it will not be reflected in the object list. I think in C# it might work . You cannot look at the problem from a general language agnostic perspective. 

 

Personally I think declaring variables at a different location from where it is used should have very a good reasons. Write code for readability first, optimize second if you have proof it is important for performance. You write code for human beings first and not the compiler. The correct version in C++ for your loop would be using a reference:

 

for(int i = 0; i < 5; ++i)
{
    CoolObject& obj = coolObjectList[i];
    obj.doWork();
}

 

If in your language this resolves to a reference/pointer anyway, it doesn't matter which form you use for performance. 

Edited by Dirk Gregorius

Share this post


Link to post
Share on other sites

In addition to what others said, note that in C++ declaring a variable will invoke its constructor, which can have side effects.

 

The big advantage in keeping declarations close to their use is that you can forget about the declaration shortly afterwards. After its last use, the variable becomes "dead", to use a term from compiler jargon. The fewer live variables you have at once, the less space you need in your head to read the code.

 

Clear head. Clear code.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!