Sign in to follow this  

Declaring variables in loops.

This topic is 4337 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

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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? [...]




Share this post


Link to post
Share on other sites
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.

    Share this post


    Link to post
    Share on other sites
    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".

    Share this post


    Link to post
    Share on other sites
    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.

    Share this post


    Link to post
    Share on other sites
    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.

    Share this post


    Link to post
    Share on other sites
    holy hell, how often do you guys need "premature optimization" yelled at you?

    variables are declared as local as possible <PERIOD>
    everything else is ugly performance tweaking, thats the last thing to worry about. and the compiler will most likely optimize it anyway.

    Share this post


    Link to post
    Share on other sites
    Guest Anonymous Poster
    Quote:
    Original post by Ra
    In either case (primitive or non-primitive type) the compiler should will optimize it.
    Non-primitive type's constructor may have such side-effects that this optimization would lead to different behaviour.

    Share this post


    Link to post
    Share on other sites
    Guest Anonymous Poster
    Quote:
    Original post by maximAL
    holy hell, how often do you guys need "premature optimization" yelled at you?

    variables are declared as local as possible <PERIOD>
    everything else is ugly performance tweaking, thats the last thing to worry about. and the compiler will most likely optimize it anyway.
    Who are you to say whether the original poster is optimizing prematurely or not? OP even said: "this part of the code is in the heart of my graphics procedures so I'm not even worried about "premature optimization"." Sometimes ugly performance tweaking is necessary.

    Share this post


    Link to post
    Share on other sites
    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).

    Share this post


    Link to post
    Share on other sites

    This topic is 4337 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.

    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