4.4 etc - Fixed cost GC? Better instantiate?

Be lovely if we could have fixed-cost GC - ie have a user-definable time in millisecs that the GC will execute in. Any remaining GC requiring to be collected after this time is deferred to the following frame(s).

Sometimes garbage really is unavoidable in some situations like networking instantiates, or dynamic situations where ram is tight or string concat. In situations like this, it becomes ridiculous in a modern language trying to avoid it, it isn’t laziness, it’s having less bugs and using Unity to solve problems.

There’s no danger of this feature crashing if there is a maximum buffer size we can allocate, say 1mb, and any GC over that amount means that there wasn’t enough time for spreading collection over several frames, and it should just collect.

This isn’t a replacement for good pooling practise, but good pooling practise is only part of the story.

Thoughts?

1 Like

Sounds like a good idea to keep things running smoothly without sudden spikes etc. Another idea would be some kind of built in memory pool that pre-allocates room (via hints you give it) instead of having to keep allocating a lot. But I supposed that’s more of an algorithmic change.

An A-sync GC call would be wonderful, or at least the ability to set a max GC time per frame as you say. Either of those should allow you to slot GC into the game deliberately in inventory/menus/screen fades/loading screens. If it’s done right you could call it just about anywhere though. Certainly a better option than just waiting for a spike to appear.

Our systems are generally designed to avoid garbage now, but really, it should be something we shouldn’t have to think about. I’d point out that merely updating the mono version would improve GC no end, if it weren’t for the fact that it’ll likely fall on deaf ears Unity’s end.

Does the GC run in another thread?

Also, what if we can just switch off the automatic GC and live with memory being used, and then do manual calls to trigger GC when we want to, perhaps with a maximum number of collection operations as a parameter??

Apologies for what’s gonna be a newb question… but what exactly is garbage collecting?
I’ve been seeing it talked about a lot recently, and while I gather it is something I probably don’t need to worry about at my experience level I can’t help but be curious haha.
I did a search and glanced at the entry in documentation, but I’m still not totally clear on what it is and when or what types of games it becomes an issue.

Thanks

The real problem is that it’s more complex than that. Old school garbage collection could be managed this way. XNA was a prime example of this because it didn’t support generational garbage collection on non-desktop devices so with techniques such as pooling, users tried to keep the allocations under that 1MB cap that would trigger collections.

Now we have generational garbage collection so not everything will be considered for collection on every frame. However, even with generational collection, it’s not the size of the heap that’s much of an issue. You could have 500MB of garbage on the heap and it will take some time to collect but it’s not going to be a killer. The complexity of the heap will cause you far more headaches… Take for instance an array of reference types, and each of these reference types having references to other reference types. The GC first examines the array… then examines every element in the array… then examines every object those objects link to in order to determine whether the objects are truly out of scope.

To add to that… you’re going to already see different results on different platforms. When targeting Windows Phone 8 and WinRT and Windows PC you’re actually going to use the .NET Native garbage collector while with other platforms you’re going to be using the Mono implementation. There’s also the issue of the large object heap which will affect what generation objects fall into.

Here’s an interesting MDSN Magazine article that should give you some insight:
http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

Edit: Also this one: http://msdn.microsoft.com/en-us/library/ee787088.aspx

XNA had a fixed 1MB GC collection size on the XBox, after every 1MB it would run…and it was terrible. Pooling wasn’t just a nice optimization, it was a necessity. Windows Phone, on the other hand, had a generational GC. It ran much nicer and was probably the single most desired feature for the XBox implementation of the .Net runtime.

Now, unless Unity updated past Mono 2.8, I don’t believe we have access to Mono’s new generational GC (SGen).

Windows Phone didn’t even have it until the Mango (7.5) update.

I support enhanced GC whether through fixed cost or updated .NET.
Gigi

Garbage Collection is a means by which, in a managed language like any .NET language, unused but managed memory resources are freed up for new handles. It’s a feature of the language that runs silently in the background, where it should have no effect in theory.

Usually, when a block of code goes out of scope (that is, you finish something like a pass of a for loop, or finish executing a method), any values inside that block go out of scope. The GC free those up, so your memory dosen’t get all cluttered with stale stuff.

The problem is, that the end programmer has no actual control over when the GC fires. The most we can say in .NET is, ‘GC, we need you to fire sometime soon.’ This is causing problems because (and this is my understanding of the problem, please correct me where I’m wrong) when we create game objects with GameObject.Instantiate, and then destroy them with GameObject.Destroy, the GC is firing when .NET feels like it, but there’s so much stuff that has to be cleaned up that it’s taking a lot of resources to do it, and thus introducing a short period of time where there’s super duper high latency in the game - a lagspike.

Please correct me if I’m wrong on any count, my understanding of the GC is somewhat limited also.

In the old days if you wanted to use a block of memory for something like storing variables, data, images, etc… you have to allocate it, through some kind of instruction in your program. The operating system would then mark that piece of memory as having been allocated. However the operating system wouldn’t really know when you were done with the memory so typically you had to keep track of which memory you allocated and how much so that you could then tell it to free it later. Usually when your program exited you’d free all the memory you used and be on your way, besides allocating and deallocating blocks while the program is still operating. This manual management of memory was somewhat annoying and could lead to memory leaks where you forgot to deallocate some memory and it just got left out there kind of orphaned and unavailable for other programs to use.

Then along came this fancy new method of automatically deallocating memory that isn’t being used anymore. ie if memory is not used it is garbage and the process of automatically figuring out what’s garbage and throwing it out is garbage collection. It’s a metaphor ;). … Typically a garbage collector is just a part of a program/engine (like Unity’s is built into their engine) which runs in the background and tries to find things like objects and pieces of memory that nothing is pointing to any more. Like if you were to create a texture object in a script and store the reference to it in a variable, but then the variable was freed or set to something else or only existed within the context of an inner loop or a function (the scope), then it would be spotted as being freeable, identified as gabage, and then collected ie freed automatically. There are various ways to go about it and apparently it’s gotten more sophisticated over the years but that’s basically it.

The problem is that often this collection process exchanges programming pain for automation as the cost of some overhead. Since it has to kind of search for garbage data to free it and can take some CPU work to perform, and if there’s lots of objects getting allocated and then becoming candidates for garbage collection, the collector could suddenly find a big pile of them and work to free them all at once. Memory allocation and deallocation is typically a fairly slow operation so this can create a big spike in how much cpu time it uses, as a sudden mass-throwing-out of allocated objects/memory/variables etc. This is undesirable in a game because it could be enough to make the framerate suddenly drop, since there isn’t enough cpu time left for the normal program to run smoothly, especially if you’re pushing the limits of the hardware. If there is no garbage collection for say a large number of frames and suddenly there’s a 1000’s of objects to free up, and it suddenly happens all within one frame, then you’re going to see the frames stuttering/stalling as the framerate drops temporarily. So ideally (and the reason for this thread) you want to do it as consistently and smoothly and hopefully as possible and only when necessary. It would be good to be able to tell the GC some kind of hint as to when is a good time or how much time to spend, otherwise it’s kind of working blindly.

The other solution of course is to change your algorithm. If you have enough memory available and you have up-front knowledge of the maximum amount of objects that your game might allocate at any one time, then you could simply allocate all of them at once in a memory pool, like store them all in an array or something, and then when you’re done with an object - instead of deleting it or turning it into garbage, put it into some kind of sleeping/dormant/hidden state, and then re-use it again when you need to add another object back into the scene. One disadvantage is that you have to use more memory, which is more of a fixed amount all the time, and it might also lead to having to process objects that are not even being used at the moment as part of your AI or game logic. But an advantage is that then the garbage collector almost never has to do any work on those objects (or at least hardly ever has to free any memory from them), memory doesn’t have to be allocated when you want to add an object to the scene (which is also slow usually), and then it can be as easy as just flipping a flag to unhide something rather than going through the process of instantiating and setting things up from scratch. If you really want good performance then you need to avoid as many memory allocations/deallocations as possible especially if it’s something you’re doing every frame. So similar to a particle system, you don’t want to be allocating thousands of new objects in a frame, it’s better to reawaken sleeping/hidden objects and then when their lifetime is used up, hide them but don’t delete them so that you can recycling. Don’t you know recycling is better for you than raw garbage? :wink:

here is some more…

The .NET Framework 4.5 includes new garbage collector enhancements for client and server apps
http://blogs.msdn.com/b/dotnet/archive/2012/07/20/the-net-framework-4-5-includes-new-garbage-collector-enhancements-for-client-and-server-apps.aspx

Back to basic: Series on dynamic memory management
http://blogs.msdn.com/b/abhinaba/archive/2009/01/25/back-to-basic-series-on-dynamic-memory-management.aspx

What’s the difference between generational and incremental garbage collection?
http://stackoverflow.com/questions/5092134/whats-the-difference-between-generational-and-incremental-garbage-collection

Difference between background and concurrent garbage collection?
http://stackoverflow.com/questions/2583644/difference-between-background-and-concurrent-garbage-collection

Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework

Garbage Collection: €"Part 2: Automatic Memory Management in the Microsoft .NET Framework

Large Object Heap Uncovered

Managing Object Lifetime

There really shouldn’t be much concern about GC firing on a modern desktop or even console, providing the garbage is small. The concern is for anything less than that level where hiccups can cause a hitch, so I’m not too worried about it in .net.

I thought this was what UT were working on ( from Joachim himself ):
http://forum.unity3d.com/threads/158652-No-More-quot-Cool-quot-Features-Please-Until-Crippling-Stuff-Is-Addressed/page9?p=1270001&viewfull=1#post1270001

I’m used to during things similar to the imaginaryhuman’s outline…you had to be fastidious.

but now C++ is rusty, Java is slow, and C# is getting ugly as perl with some of the syntax constructs…

I think modern GC is a symptom of modern event driven OO languages like C#? Seems like it would be horrid using Unity UI. Once it’s out of scope and not static or global doesn’t it just do a destroy? Trying to learn about public, private, static, and GC / new / destroy without dropping $30 on a book…

Unity have already been working on the GC, they have allocated a 4 man team with the aim to get the GC trimmed down to under 2ms a frame, see link below.[

http://forum.unity3d.com/threads/158652-No-More-quot-Cool-quot-Features-Please-Until-Crippling-Stuff-Is-Addressed/page9?p=1270001&viewfull=1#post1270001](http://forum.unity3d.com/threads/158652-No-More-quot-Cool-quot-Features-Please-Until-Crippling-Stuff-Is-Addressed/page9?p=1270001&viewfull=1#post1270001)

They’re working on it but they were alqo working on 64bit editor over a year ago as a top priority. I wouldn’t hold my breath

C# Memory Management for Unity Developers (part 1 of 3)
by Wendelin Reich on 11/09/13 11:57:00 am Featured Blogs

From my limited understanding of GC (mostly from reading Shawn Hargreaves’ blog posts about .NET’s GC) the problem is that even if the amount of garbage is small, if the amount of memory allocated by the game is large the garbage collector still has to check through the game’s entire pool of memory to figure out what is garbage and make sure that garbage isn’t referenced by another piece of memory.

You can have a very well optimized game with only the smallest amount of garbage created, but if the game uses a large amount of memory with complex references chains between objects it will cause a major hitch the moment the garbage collector kicks in. On the other hand you can have a game which creates garbage regularly but uses very little memory in the first place with few references between objects, which means the garbage collector may run a lot more often but it probably won’t be cause that noticeable a hitch compared to the other case.

yeah i think that is pretty much the problem…

unity should move to newer different garbage collector, either by updating mono to newer version or by they themselves updating the garbage collector

not that hard to do. they could build one or find one that they could use and license it…