[newbie] is there any overhead declaring local variables inside Update?

For optimization purposes, I was wondering if I should declare local variables outside functions like Update or OnGUI, to avoid the overhead of declaring the variable again and again every frame.

So instead of this:

Update() {
   var i: int;
   ...
}

should I use this?

private var i: int;
Update(){
   ...
}

Thanks.

1 Like

Good coding practice is to keep the variables as local(?) as possible.

Which means keep it in the Update function (also applies to things like loops).

While the performance difference should be negligible(you do it for code clarity), there are more optimizations that can be made with the latter.

1 Like

You ask if there is overhead, there is always some overhead in declaring variables.

As a matter of maintainability, I generally agree with NPSF. You’re probably better off having that one variable there so it is easier to read and maintain. If there were many thousands of these, you might have to improve the performance of the script.

Good software engineering has to balance clean and maintainable code against performance. Some (bad) programmers will just go entirely for the former suggesting the user throw more hardware at it, some programmers will optimize to the point that nobody can tell what is happening when it is time to find a bug or update the code (which is a real pain). If your organization has well documented coding standards, you won’t have too much trouble knowing when which method is appropriate for a situation.

1 Like

Let me interject one thing. If you build complex objects, it is best NOT to rebuild them every frame. Things that take a while to build are bad for update functions. If I were concerned about limits I would not build GameObjects every frame, nor meshes. This includes Instantiating. They take a touch of time to build but if you build 500 per frame then your performance will drop significantly.

Does this mean you can never build these in an Update? You can, and often will, just don’t do it with reckless abandon. Your game is already instantiating particles and other things it takes to make it look nice. :wink:

Things like Int’s and Float’s would be no problem. Even Vector3’s and Quat’s are not much of a burden. I recently found an HSBColor class. I looked into the code and saw that to build one it took a lot of math to convert a color. I remember thinking, that can’t be good. I built it and ran tests on it’s efficiency, it’s not that bad.

1 Like

This question comes up every once in a while and it is an excellent example of how not to approach performance optimization :stuck_out_tongue:

Performance optimization begins with measuring.

While the first two replies to your question give excellent advice to stick to what’s most readable, they both pick option ‘b’ as the faster of the two. Measuring (as done by Eric in this thread http://forum.unity3d.com/threads/40981-it-is-good-to-declare-variable..if…) will show that option ‘a’ is not only more readable, but also slightly faster (at least in eric’s test case). This may seem counter intuitive, but it is caused by the fact that declaring a variable on the stack (which resides in cache and is done for the entire function at once) can be faster than accessing data from a variable which might reside in main memory.

In my opinion, it is best to write your code as readable as possible without any focus on optimization. Only when you find your game is starting to run too slow, measure which parts of your game take the most time and do performance optimization right there, where it counts the most. 9 out of 10 times, the most time consuming process in your game it is not where you thought it would be.

I would estimate the odds of global vs local variable declaration having a noticeable effect on performance to be approximately zero (but please measure to prove me wrong :wink: ).

16 Likes

As a general rule if you don’t need it outside of the scope then don’t declare it outside of that scope. Even if just for the benefits of easier code-writing when using autocomplete/intellisense

1 Like

i can not thank you enough for your comment. i’ve always struggled with this kind of decision before, but from now on i will write the code to be clean and easy to understand and not stress out about minuscule optimizations.

thanks a lot!

Personally, I draw the line at using the new keyword. For instance new Vector3(), because you are creating an object and destroying it over and over and the garbage collector will work harder. This article is a good read:

As far as being more readable, that’s pretty much up to the coder. I think those are good practices to get into right away. Some are very easy like using two labels instead of concatenating strings. Why wait till it’s a problem? Your program might be just slightly slower, but stutter because of the garbage collector and annoy the user, or you’ll have to go over it with a profiler when you wouldn’t have had to.

2 Likes

Not quite.
Vector3 is a struct, not an object.
new Vector3 does not generate garbage.

1 Like

I didn’t know that, but I’ll stick with my “new” keyword approach anyway.

1 Like

If you use them only in update so keep them in update or coroutines.
You should keep them locally whatever you can but if you use many new keywords (create reference types) you require to change your design

Actually it is, as Vector3 is a struct but i think any instance would be an object (everything in C# inherits from object class right?) and also when you make an instance of vector3 you can use that 4 functions of object class

Bad necroing. And no, not everything.

I disagree. There are certain best practices for optimization that we should just start off with. Asking if these is one of them, is a good question. Especially for beginners. For example we see new programmers using GetComponent methods inside of update all the time. One does not need to measure if this is a bad idea. Why waste our time when its a known issue and there is a simple solution.

Guess not much has changed since 2011, lol.

3 Likes

Structs in C# are Value Types, which mean they work like fancy ints or string. Try these 2 tests:

Vector3 v1; v1.x=6; v1.y=8; v1.z=8;
Vector3 v2=v1; v2.x=111; print(v1.x); // 6

In the 1st line, we don’t need to use new. v1 exists as soon as we declare it. In the 2nd line, v2 is a copy of v1, not a reference to it. changing v2.x doesn’t affect v1.x.

To be fair, System.String is a class, and strings are all ref types. They’re immutable, so they technically behave like a value type when interacted with, but are treated like a ref type when it comes to how they persist in memory… well actually that’s also slightly untrue because several strings (mostly const strings both expllicit and implicit) get their only special block of memory allocated for them as well.

I also take slight issue with @ 's link.

It’s only examples are really just pointers, interfaces, and generics.

But pointers only work in unsafe mode which is full of all sorts of odd exceptions (and is why the author probably sort of excludes them from their own list).

Interfaces aren’t objects… because they’re just type declarations. To say interfaces aren’t objects is to say any type declaration isn’t an object (unless reflected of course). Nothing is an interface directly, they only are indirectly in that they implement an interface. And if they’re capable of implementing an interface they themselves are an object as only objects can implement interfaces. You can’t instantiate an IFoo, only a Foo which can be treated as an IFoo.

… Basically it’s like saying methods aren’t objects, or operators aren’t objects, or fields aren’t objects. Cause they aren’t. But that’s because these things are outside of the idea of a data structure. They’re parts of the data structures. Otherwise, that link needs to add quite a few more things to its odd list of things that aren’t objects, pretty much consisting of quite a deal of C# syntax. Which I would argue MS was expecting computer science students and professional programmers to understand they didn’t mean EVERYTHING when they said everything on such a pedantic level.

And of course generics aren’t… because that’s basically runtime templating. Your is not a type… it’s the idea that a type will be defined when used. You can’t have a “T”… you can only have a “string” once “T” is replaced with “string” when it’s JIT compiled (or AOT compiled, or any other compiled). And once that is compiled, whatever the “T” variable/field/etc is associated with… is an object. It’s basically the interface/method/operator/field argument all over.

At the end of the day the idea that “everything is an object” in C# is that if you have a defined chunk of managed data (which pointers are unmanaged data), that chunk of managed data (the boundary of ‘chunk’ being defined by any of the known type definitions class/struct/enum/etc) can be treated as an object. In that it can be cast and stored in a field/variable/mechanism typed ‘object’.

1 Like

I have never heard MS saying that “in C# everything inherits from the object class”. Maybe I have missed something.

And I’m sorry, we’re software developers, to be at least broadly precise is sort of coming with the territory.
This phrase is very far from true and I only argue with this phrase. My link is only a randomly selected example so I don’t only tell that he’s wrong, but he gets the idea why he’s wrong.

Unfortunately the English language isn’t as strict as programming languages. So try as we might as developers, the English language will forever wiggle away from what we expect it to mean since anyone can interpret it the way they see fit based on their knowledge of the language.

Hence law using such strict usages of language as to needing explicit definitions before entering any description of law. Otherwise the natural state of English wiggles away from the courts.

So as a result trying to wrangle the “everything is an object” down into a pedantic liturgy just becomes tiresome.

At the end of the day… the point is, you can cast pretty much everything to the the object type with exceptions in the outer limits of the language such as unsafe mode.

…

Also:

1 Like

The point is that new Vector3 doesn’t make garbage, since it’s a struct, which is a Value-type. That’s what firecracker pointed out 8 years ago. Saying that structs are technically Objects is only confusing the issue.

1 Like

I’m a little confusing, so value types are not Object unless you use boxing and unboxing? and as lordofduct pointed Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. when it comes to memory management value types will not treat as an object?