Hi there. I'm one of the many folks who is having problems with GC.Collect running from inside one of my GUI functions every quarter second and basically totally destroying my frame rate. This is on a windows build, mind you, not iPhone. it's not like I should be running out of memory here.
the problem is that as I do this, if anything, the problem is getting worse.
so what the hell is going on? what garbage is GC.collect collecting exactly, and why on earth does it think it needs to run a collection every quarter second or so, when my entire GUI section (according to the profiler) is using only 300 kb of memory?
I'd like to know specifically how this functions, so that I can optimize around it...
Adendum question -- I'm using a custom GUIskin with many (130) custom gui styles in a single skin. most of those are for painted bitmaps that we use for buttons. what kind of an effect does this have on the garbage collector? is having such a large GUIskin a bad idea? do the sheer number of bitmaps themselves get collected as well? I'm also calling the styles by name, using a string. I'm assuming that these strings in the gui function are allocations as well and I should move them off, yes?
I'd like to help, but I don't have the exact answer to your questions so I posted this as a simple comment. From what I understand, OnGUI is called a number of times more often each frame than Update. If your GC.Collect is within OnGUI, that just means that garbage collection is fast and frequent... and maybe TOO fast and TOO frequent. Can you try calling garbage collection every Nth frame instead (or disable it temporarily) just to see how much of the 'performance degradation' it is causing by calling it within OnGUI? I'm also interested in the answer to your question.
Sorry, I meant '..more often each second than Update.'.
Interesting. I wasn't aware that I had control of how frequently garbage collection was called (or not) at all... in fact, manually writing GC.Collect() into my scripts causes a compile error... uh oh. This isnt' a C# only thing, is it?
Answer by VS48
Nov 03, 2010 at 02:58 AM
Disclaimer: without a response from a Unity developer or the source code, the GC and allocations made by the core code will always be a bit of a mystery. So I cannot answer your question about what exactly is being allocated, and why the collections occur more frequently with native GUI.
At present, any time OnGUI is called, it will generate garbage. So, having
// Nothing here
in your code will cause positive allocation.
Side note: From what I've read, the GC is called much more frequently with recent version of Unity. This is designed to reduce the devastating impact the GC would have on performance if it was reclaiming like 8MB of memory at runtime.
The obvious solution to this problem is to not call OnGUI -- if you are drawing screen-space textures or text, simply place objects with a texture/text component into your scene and manipulate their properties from Update() or another point in the execution loop. Leave the OnGUI stuff (buttons, sliders, checkboxes, etc) for debugging or intro UI where memory and CPU performance is not an important factor.
I know this doesn't answer all your questions, but hope it helps a bit.
Answer by Lucas Meijer 1
Nov 04, 2010 at 09:00 PM
having garbage collections take so much time to destroy your framerate on a desktopmachine is totally not supposed to be happening, and means that either you are diong something wrong, or we are doing something wrong. Can you post a project that reproduces this behaviour so we can try to help?
Hello, I have the same problem - I have checked all of my OnGUI methods and I am not allocating any heap memory anywhere. However every 2-3 seconds I see a huge 40ms spike in the profiler inside GUI.Repaint()->GUIUtility.BeginGUI()->GC.Collect(). This kills the framerate. Could it be a bug? It is very hard for me to send you the whole project as it is several gigabytes.
Answer by hypnoslave
Nov 05, 2010 at 09:47 PM
Hi Lucas, VS48 -- good to hear from you guys, thanks.
ugh, I can't post the project that I'm working on here unfortunately.. it's all supposed to be kept hush hush at the moment. I could submit the whole thing as a bug report, i suppose..?? I'm assuming that's all confidential? it's a rather big project. Should i submit the whole thing as a bug?
after reading VS48's post (Thanks man!!) I tried more-or-less moving all OnGUI functions into a single script (so I have one OnGUI function that basically calls a list of externalScript.RenderMyGUI() functions) and that seems to have had a significant positive effect on this problem. i'm still getting performance spikes but things are staying under 30 fps (barely)... most of the time. it still goes to hell once and a while.
also, the problem isn't noticeable in the webplayer, which is good news... So far it's just in the windows editor. I have had reports of terrible framerates in the webplayer, but they've been few and far between and I haven't been able to reproduce them...
Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.
The best place to ask and answer questions about development with Unity.
To help users navigate the site we have posted a site navigation guide.
If you are a new user to Unity Answers, check out our FAQ for more information.
Make sure to check out our Knowledge Base for commonly asked Unity questions.
If you are a moderator, see our Moderator Guidelines page.
We are making improvements to UA, see the list of changes.
Answers and Comments
1 Person is following this question.
Best practice: projectile destroy or allocate a list?
How do I efficiently maintain a constantly-changing list without triggering GC?
does application.loadlevel run Garbage Collector automatically?