Is it a bad idea to create objects every update/draw?

I see a lot of MonoGame/XNA tutorials that do things like:

  • Create a new Vector2(...) in Draw
  • Create a new Rect(...) in Draw
  • etc.

Is it actually a bad idea to do this? Considering that draw/update run at 30-60fps, you’re creating (let’s say, per sprite/entity) 30-60 instances per second, and these will eventually get garbage-collected, won’t they?

Or am I missing something? I’m going through some length to “cache” these things inside persistent properties that only update when the underlying data changes, but is this a micro-optimization?

Ditto for Color instances.

It’s fine, in C# structs are value-types. Though how fine really depends on how fat a thing is.

It’s not fine with heap types (classes).

2 Likes

That’s easy enough to remember.

What about null checks? I take some pains (eg. denormalize things into a Dictionary) to try to avoid null checks in Update/Draw.

A good rule of thumb is to optimize only if your game is experiencing stutters or frame drops. Null checks operate in O(1) time and aren’t a bottleneck in the majority of applications.

What you should look out for though is memory leaks by creating objects that involve unmanaged data. For instance, manually creating Texture2Ds every frame will cause a memory leak unless those textures are manually disposed. In this case, it’s preferable to cache them. Note that loading objects through the ContentManager is fine, as it automatically caches and disposes these objects.

3 Likes

Are you putting things into a Dictionary in order to avoid null checks? You know inserting into a Dictionary and then doing Dictionary look-ups have a cost, right? Much more expensive than a null check.

2 Likes

I am planning to optimize once I find performance bottlenecks, but I’m more concerned about memory leaks from things I didn’t notice I’m doing wrong. Thanks for the tip about Texture2Ds; I’m loading them with Texture2D.FromStream (not every frame, just on initialization) and I will remember to call dispose on them when I’m done with them.

I have rarely written games in C# and almost never use structs, and I’m not sure what kind of things are bad practices as far as GC/memory-leaks.

You should always be aware that the garbage collector is SLOOOOOOWWWWWWW.

So generating garbage in the general case is very bad.

However as has already been stated, premature optomisation is the root of all evil.

To give you an idea of how bad it can be. I had to work on a third party 2D game engine once. The game ran perfectly for 4 minutes, then it dropped to less than 1 frame a second.

The guy I was working for bought the source code for the engine and I found they were creating a brand new GraphicsDevice every render pass. This gradually filled all available memory with garbage until the garbage collector was running every frame.

Once I had fixed that, all was good.

The garbage collector is so aggressive, I have seen it cause machines to totally lock up for about 100mS . I mean every core and every thread was suspended until it completed the garbage collection.

So to answer the original question, is it a bad idea to create objects every update/draw? Yes.

But it’s a soft yes.

It’s like one of those experience things.

When you first go camping you don’t take any toilet paper.
When you have been a few times you take toilet paper.
When you have been quite a lot you take toilet paper and put it in a plastic bag.
When you have been going camping for years, you don’t take toilet paper as you know you can always blag some from someone you know or use natural substitutes you can find in the woods

:slight_smile:

1 Like

Just to clarify what others said - allocating new actual objects each frame would add up in the heap and lead to a drop in frame rate and cause extra memory allocations if those are reference types - and the GC wouldn’t like it eventually.
So if you did like (each frame):
myClass = new MyClass(bla);
If you only really need 1 class to reuse, then as you said - you’d just do that in the initialize once.

However (just to reinforce what was mentioned) if you see a value-type struct like:
Vector2 vec = new Vector2(12f, 24f); (or Rectangle)
That’s not on the heap and you don’t need to worry about garbage collection with that. It’s pretty much like saying:
float x = 12f, y= 24f;
And you’ll see no memory or performance hit. I believe value types are placed on an pre-allocated stack space.
One thing to note too is that reference types can be passed around like a pointer in c++ - it’s just the memory address and the class is not copied so there’s no real hit from that either. If you pass a structure however (if it’s a big one), it would be like passing the entire list of parameters… which if it’s huge, that wouldn’t be a good idea - in such a case a class would be better than a struct.
I’d say it doesn’t hurt to have reasonably optimal habits. I think the premature optimization philosophy comes in when ppl go way overboard and make the code really confusing to make it faster before they’ve finished the overall design. I’ve crammed a huge amount of fx and layers into my game without seeing any slowdown yet. If at some point it does slow down - there’s probably something critically wrong with how something’s working.

2 Likes

Actually to clarify a little more.

The garbage collector will pause the application thread when it frees up allocated memory.
Garbage is memory memory is not a problem freeing it is as that is the meaning of collecting it.

Real world meaning … your game stutters slightly if you make reference type objects and let them go out of scope each frame or if you box structs or by a number of other odd cavets. The more you do that the faster the gc collects the now collectable un-usable memory and the more your game stutters.

Primitive types and structs are in general allocated on the stack BUT not guaranteed to be as this is a … quote ‘implementation detail’ unquote.

Real world meaning 1. A ton of regular vector2s in a method makes no garbage.
Real world meaning 2. If i put a struct in a class its gonna be on the heap. or If i make a really really big struct it can end up on the heap or by a number of other odd cavets…

So monitor the gc collections with a on screen display just like you would the frame rate for performance.

It’s what i do so that it doesn’t turn into a problem in the first place.

1 Like

The GC isn’t that slow. I do a lot of per-frame GC allocation and still the C# version of my draw flush runs at ~60% of the C++ version with the differences having more to do with C# being incompetent at raw crunching than its’ GC.

I don’t think I’ve ever had the GC be an actual problem (I’ve never done anything truly idiotic though) outside of Mono and strings in a lexer for performance in C#, it’s always been that .NET is just complete trash at crunching through work. Even the recent numerics.vectors is bottom of the barrel scum in perf.

I should of mentioned before that if you pool objects and operate on them properly even if they are on the heap they won’t create collectable garbage either.

The gc is fast but when it actually needs to perform a collection your game is on pause until it is done.

Typically what i see on windows is when about 1.5 to 2 mb of collectable or unreachable memory add up. The gc will do a collect.

The more it has to call collect the more it will pause. The more it pauses the more chance that you will notice it as a slight stutter skipping or apparent slow down.

For example the following seems like a simple question but the answer isn’t straight forward.
How do you draw a variable that changes every frame without triggering garbage collections?

Here i just ToString() a bunch of numbers to see a quick positional graph to debug buttons i was working on and bam 50 collects per second and a huge frame drop… So you might say well of course a list is a heap object as is stringbuilder. But the normal frame rate counter here is too and it causes no collections. In this picture i didn’t care the lines were going to get deleted which is why i generated them locally in the method and they made a ton of trash that generated a ton of collections.

Point im trying to make is how much garbage getting collected is relative. One line can be too much or worse you can just do a little here and there till it all adds up to be to much. If you aren’t watching it then it’s gonna start adding up.

Anyways the question itself should be directly answered

I see a lot of MonoGame/XNA tutorials that do things like:

Create a new Vector2(…) in Draw
Create a new Rect(…) in Draw
etc.

These are value types because structs are value types.

It’s value is copied when its value reference variable is, passed by value into a method parameter.

This does not mean it is on the stack or on the heap.

Is it actually a bad idea to do this?
Considering that draw/update
run at 30-60fps, you’re creating (let’s say, per sprite/entity) 30-60
instances per second, and these will eventually get garbage-collected,
won’t they?

As you have stated the question …

It depends on the context or scope of the type instance.
(by scope i mean the lifetime of the variable in the code { block } you are considering).

If the vector2 is declared in the game1 class or a pretty much any method as a temporary variable, since the compiler can known that game1 will exist for the lifetime of the application and its pass by value. As well the compiler can know exactly how long the temp variable will last. (provided there is no yield or something weird)
Then it can put it on the stack.

If the vector2 is a variable of game1 is said to be local to a instance of game1, it is one of game1’s method variables. There is no garbage reassigning it in game1’s update or draw. (unless you do something really weird to it).

If the vector2 is in a different class object and you create a instance of that object in a local Game1 method for example Update or Draw, That struct is then on the heap with the reference type object instance. When the method exits that instance including the vector2 inside it will be out of walkable scope to the application and will be marked for collection at some time by the gc.

Or am I missing something? I'm going through some length to "cache" 
these things inside persistent properties that only update when the 
underlying data changes, but is this a micro-optimization?

Cache if you need to.
If you can use structs go ahead if you don’t want to fine you can use class instances.
If either are on the heap and they go out of scope to game1 however then they’ll be garbage collected at some point.

All calls to new create garbage that has nothing to do with a actual Collection being triggered.
(Garbage isn’t evil garbage is memory)

Your reference type instances or structs on the heap going out of application scope creates a collection random number 90% of the time.
(Which for a game at a fast paced critical action packed moment… is evil).

Ditto for Color instances.

Same as above.
There are a couple other ways structs can end up on the heap as well. TLDR already.’

Here is a good article.

Thank you for this explanation, it really clarified what I wanted to know.