Skip to main content
GameDev.net gamedev.net
🔒 Locked

Declaring variables in loops.

Started by Thevenin Jan 27, 2006 at 10:24 PM 15 replies 1.3k views
Original Post
Thevenin
Thevenin
So today I finally ask a question I've had for quite a while... Is there a different between....
int x;
for(some big loop)
   for(some even bigger loop)
      for(wowz0rs loop)
      {
         x = return_something(anything);
         use_variable(x);
      }
... and
for(some big loop)
   for(some even bigger loop)
      for(wowz0rs loop)
      {
         int x = return_something(anything);
         use_variable(x);
      }
I've already concluded that the later code would be a very bad idea for non-primitive types, but I can't decide for primitives.
Ra
Ra
In either case (primitive or non-primitive type) the compiler should will optimize it. The real question is which scope the variable should have. If it's only supposed to exist in the innermost loop then it belongs there, otherwise it should be outside.
Ra
ender7771
ender7771
When you declare x and then pass it as an argument, you are only passing the value, not the location. It doesn't matter where it was declared.
Thevenin
Thevenin
Quote:
Original post by Ra
In either case (primitive or non-primitive type) the compiler should optimize it. The real question is which scope the variable should have. If it's only supposed to exist in the innermost loop then it belongs there, otherwise it should be outside.


I'm not sure the compiler could optimize this to the point where it becomes merly preference...
(This is what I ment by non-primitives; eg.. not just the reference but the instancing of the object itself.)

for(some big loop)   for(some even bigger loop)      for(wowz0rs loop)      {         ColorOperator x = new ColorOperator();         x.Color = return_something(anything);         use_variable(x);      }


.. but in the case of primitives (Or non-instanced non-primitives), it would be in my best interests to put it inside the loop since its scope doesn't exceed it.
Nypyren
Nypyren
I think what he meant is that the compiler optimizes the space allocated for local variables. Initialization is optimized (or not) separately. Static initialization would be done at compile time, however.

It ends up being up to preference about how you like your scope...
etothex
etothex
Quote:
Original post by Thevenin
I'm not sure the compiler could optimize this to the point where it becomes merly preference...
(This is what I ment by non-primitives; eg.. not just the reference but the instancing of the object itself.)

for(some big loop)   for(some even bigger loop)      for(wowz0rs loop)      {         ColorOperator x = new ColorOperator();         x.Color = return_something(anything);         use_variable(x);      }


.. but in the case of primitives (Or non-instanced non-primitives), it would be in my best interests to put it inside the loop since its scope doesn't exceed it.


If you are using heap allocation (i.e., new+delete), then reusing the object might provide some benefit. But otherwise, allocate it in the scope it is used. In fact, it might even open more optimization opportunities for the compiler if the smallest scope.

It looks though like you are using Java/C#. In that case, all objects are allocated on the heap. So there might be some benefit to reusing objects. However, it is nowhere near as big a benefit as it once was because of the much better garbage collectors and heap allocators in modern virtual machines.
Wavarian
Wavarian
I don't remember where I heard it from, but I was once told that you should declare a variable outside of the loop if there's a good probability that it'll be assigned the same value more than once.

For example:

int value;while(true){	value = ...;	// ...}


Here, in the first iteration of the loop, the number 5 might be assigned to value.. And in the second iteration, the number 5 might again be assigned to value (perhaps a very very VERY slight performance gain, but nothing to wow over).

while(true){	int value = ...;	// ...}


I usually use the above when I know that the number assigned to value could be anything, and thus such micro-optimising would prove to be pointless.

In any case I would definitely favour whichever method makes my code cleaner and easier to manage.

EDIT: For anything other the standard types (int, float, etc) it is a completely different story. You wouldn't really want to create and destroy a complex object in the loop over and over.
Thevenin
Thevenin
Quote:
Original post by etothex
Quote:
Original post by Thevenin
I'm not sure the compiler could optimize this to the point where it becomes merly preference...
(This is what I ment by non-primitives; eg.. not just the reference but the instancing of the object itself.)

for(some big loop)   for(some even bigger loop)      for(wowz0rs loop)      {         ColorOperator x = new ColorOperator();         x.Color = return_something(anything);         use_variable(x);      }


.. but in the case of primitives (Or non-instanced non-primitives), it would be in my best interests to put it inside the loop since its scope doesn't exceed it.


If you are using heap allocation (i.e., new+delete), then reusing the object might provide some benefit. But otherwise, allocate it in the scope it is used. In fact, it might even open more optimization opportunities for the compiler if the smallest scope.


Well, by not putting the x variable before the loops (In this case), the memory manager is now having to new/delete...

big*bigger*wowz0rs

...many ColorOperators. And if my math is correct, this is alot of unnecessary processing. Enough to the point where I could foresee SiCrane saying something along the lines of...

Quote:
Original post by SiCrane
I mean this in the nicest way possible, but what the hell is wrong with you? [...]




Skeleton_V@T
Skeleton_V@T
If the object value is not going to be changed, apparently I'll put it outside of the loop and have it to be const (I'm not considering about compiler optimizations here though).

If not, my choice depends on the complexity of the constructing object:
  • For fundamental types, I'd prefer putting it inside the loop.
  • For other types that are more complex than Vector3, I'd prefer putting it outside.

    [Edit]: Beaten by Wavarian.
  • --> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
    Thevenin
    Thevenin
    Quote:
    Original post by ender7771
    When you declare x and then pass it as an argument, you are only passing the value, not the location. It doesn't matter where it was declared.


    Yuppers, but is there a performance hit for putting it in the for loop.

    I know that the C# compiler will optimize just about everything you write, but that doesn't always produce an acceptable solution; this part of the code is in the heart of my graphics procedures so I'm not even worried about "premature optimization".
    etothex
    etothex
    Quote:
    Original post by Thevenin
    Quote:
    Original post by ender7771
    When you declare x and then pass it as an argument, you are only passing the value, not the location. It doesn't matter where it was declared.


    Yuppers, but is there a performance hit for putting it in the for loop.

    I know that the C# compiler will optimize just about everything you write, but that doesn't always produce an acceptable solution; this part of the code is in the heart of my graphics procedures so I'm not even worried about "premature optimization".


    Java (and I would assume C#/.NET) uses a generational garbage collector that is heavily optimized for very short-lived objects, those being the most common.

    So while I would say that if it's simple to reuse the object, I would, but I wouldn't be too concerned about it unless you really were trying to squeeze the last bit of performance out of the loop - in which case you can find out by trying both and see which is faster, which will give you a conclusive answer.
    stylin
    stylin
    Quote:
    Original post by Skeleton_V@T
    If [the object is mutable], my choice depends on the complexity of the constructing object:
  • For fundamental types, I'd prefer putting it inside the loop.
  • For other types that are more complex than Vector3, I'd prefer putting it outside.

  • For objects that are more 'complex' than simple Vectors, you've got to choose based on more than construction. If your assignment semantics are more expensive than construction/destruction, and efficiency of the loop is a concern, declaring/initializing the object inside the loop would be preferrable. Often this isn't the case, but it probably should be pointed out anyway.
    :stylin: "Make games, not war." "...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
    maximAL
    maximAL
    holy hell, how often do you guys need "premature optimization" yelled at you?

    variables are declared as local as possible
    everything else is ugly performance tweaking, thats the last thing to worry about. and the compiler will most likely optimize it anyway.
    ------------------------------------------------------------Jawohl, Herr Oberst!
    stylin
    stylin
    Quote:
    Original post by maximAL
    holy hell, how often do you guys need "premature optimization" yelled at you?

    Believe it or not, there are those that read this forum for which understanding how your objects are created/assigned/destroyed is not premature at all. Rather, I'd suggest that blanket adherence to one particular method, without regard for, IMO, important issues such as those I mentioned above is much worse than premature optimization (for built-in types, this is of course a non-issue, and has nothing to do with optimization - although there are certain circumstances where the state of an uninitialized variable is a concern).
    :stylin: "Make games, not war." "...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
    maximAL
    maximAL
    i didn't just mean the op. there are other posts, too, promoting thoughtless use of that.
    ------------------------------------------------------------Jawohl, Herr Oberst!

    Topic Locked

    This topic has been locked by a moderator. New replies are not allowed.

    Sign in to reply to this topic.