Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Mono garbage collection, can I get a summary?

Discussion in 'General Discussion' started by jackmott, Feb 13, 2014.

Thread Status:
Not open for further replies.
  1. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,516
    Make a clean, empty scene with just a camera. Put your test script on the camera. Start the Profiler. Hit play, wait a moment, hit pause. In the Profiler browse frame by frame from the start. You'll find tiny allocations from the test script. If you keep running, you'll find that they double in size and halve in frequency from allocation to allocation.
     
  2. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    For networking, you need to convert things to bytes and then back.
    Networking send rate can be very high, possibly even every frame if the framerate is something like 60fps.

    I am not able to use the c# BitConverter class since all of its methods (.GetBytes, .ToXXXXX) allocate garbage. Is this a good enough example of where I would need to do things like in my no garbage example?

    Now, with the networking example. What would you do? Would you do as I did in my no garbage example?

    Lower in the comments of the blog, Josh Peterson stated this to someones comment
    "
    On the GC issue, the Boehm-Demers-Weiser garbage collector is used for IL2CPP on both 4.6 and 5.0. It does replace the Mono GC, but this is effectively the same GC used for Mono in Unity before. We’re using a newer version of the source code for the GC, but it still has the same features and behaviors. So I don’t think there is much you can do from the C# level to improve GC performance.

    We are investigating the use of the Microsoft GC that is a part of the CoreCLR, but we don’t have anything ready on that front yet. We’ll also have a blog post in this series about the GC coming up soon.

    "
    Doesnt seem like we have improved things yet, or maybe I am just misunderstanding things (which is very possible ^^)
     
    Last edited: Oct 12, 2015
  3. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Last edited: Oct 12, 2015
  4. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    1,033
    Often you have to fix somebody else code and it would be a pain to rewrite everything to use a new data type.
    This happen a lot for me when I use something from the asset store, so much that I am always more hesitant to buy anything and usually the best assets are the free and open source ones.
     
    angrypenguin likes this.
  5. Sebioff

    Sebioff

    Joined:
    Dec 22, 2013
    Posts:
    218
    Well. You've been shown the code for List that shows the allocations, and multiple people here (including 2 Unity engineers) and on stackoverflow agreed that they exist, so trolling is a rather unlikely explanation, no?
    ...and I don't think updating the GC changes anything about how much garbage you're allocating (plus yes, I'm using 5.1.2f1).
     
    angrypenguin likes this.
  6. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
     
  7. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    How about you show me some proof? I ran over 100000 frames, overhead stays at 0 bytes..
     
  8. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,516
    Haha! And you suspect us of trolling...
     
    N1warhead, Sebioff and HiddenMonk like this.
  9. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    That depends where is the proof ? Did every thing listed here:
    Deep profile = no change
    Clicking every frame = no change
    Changing frame count = no change

    Show me a video where this codes generates overhead and GC allocation over many frames. If not what is your excuse?
     
  10. N1warhead

    N1warhead

    Joined:
    Mar 12, 2014
    Posts:
    3,884
    I've been watching this thread over past few hours (very distracting btw) haha.

    But I'm coming to the conclusion it must have something to do with how strong your CPU is.
    One has 0 bytes, others have bytes, etc.

    So perhaps nobody is trolling and one just has a stronger CPU than you?
    Perhaps it's a bug, idk.

    EDIT - When I say "You" I am speaking in general to whoever is getting bytes. lol.
     
  11. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Where is the overhead? that i was promised..
     
  12. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Well I'm guessing it's somewhere in another dimension. The multiverse has those right? I'd look there.
     
  13. Sebioff

    Sebioff

    Joined:
    Dec 22, 2013
    Posts:
    218
    Code should be "proof" enough, but fine, I'll bite:
     
  14. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Why do you have 2 gameobjects with that script on? But any ways, i believe you, looks like it could be a issue with GC and Mac OS.? Maybe something to look in to, its for sure running zero on PC..
     
  15. Noxzo

    Noxzo

    Joined:
    Feb 16, 2014
    Posts:
    14
    Test on PC (4core) GC allocation 0 bytes like Iron says, but i did get a one time 6kb that's about it.
     
  16. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    It's common sense that it HAS to allocate memory. Imagine that you let your code run for twenty years, and it puts 70 bajillion million trillion vectors into that list. We can agree that that would take up a large amount of memory right? More than 12 bytes, yes? Where do you think that memory comes from?
     
  17. N1warhead

    N1warhead

    Joined:
    Mar 12, 2014
    Posts:
    3,884
    @makeshiftwings - I'm not sure, how do we as humans keep apparently having unlimited memory and storage in our brains? lol.

    EDIT - I mean surely we've encompassed 3252352345345 terabytes of memory and storage (from video memory and audio memory and photos we take in our brains) by the time we are 30 lol.
     
  18. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Push and Pop... your welcome to google it
     
  19. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Yeah but once you hit 40 or 50, you'll start having memory leaks, and eventually around 80 or 90 you'll probably blue screen with a pretty bad seg fault.
     
    angrypenguin likes this.
  20. N1warhead

    N1warhead

    Joined:
    Mar 12, 2014
    Posts:
    3,884
    lmao hahaahahahaha. That is very true, but I suppose some people have an extra few cloud drives floating around, that's why they have healthy brains for life lol.
     
  21. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    okey i am out have fun guys, i got stack overflow so.
     
    Last edited: Oct 12, 2015
  22. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    So you agree the list has to keep getting bigger, but you think it's on a stack. Let's say it is... you make a new List in object A, add some stuff to it, and then reference it in object B. Then you delete object A. What happens to the List? If it was on some kind of stack linked to object A that gets deleted when object A is deleted, then object B is now pointing at corrupt data when it accesses the list. Does the stack for object A just stick around forever even after you delete object A?
     
    angrypenguin likes this.
  23. Sebioff

    Sebioff

    Joined:
    Dec 22, 2013
    Posts:
    218
    It's only one GameObject, not sure why the Profiler shows it twice on the first frame.
    And no, it's the same on PC, as it should be.
    Since @Noxzo isn't seeing it either though my suspicion is that it might actually be a problem with the Profiler? Or all of us are missing something here.

    As someone previously explained, C# allocates arrays on the heap.
     
    angrypenguin likes this.
  24. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    I ran the profiler and it shows it allocating for me; basically doubling in size every few frames as the list grows, like I'd expect it to.
     
    angrypenguin likes this.
  25. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Just to make sure we're all looking at the same thing, you need to look at the Memory row and find where the purple line spikes; that is the GC allocation happening. You can then click in the CPU section at that point and you'll see that the allocation is coming from your Update function.

    upload_2015-10-12_3-27-1.png
     
    angrypenguin likes this.
  26. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @Ironmax - The problem is that you don't understand how a List<T> works. I'll try to explain it in detail. Let's say you do this:

    MyList = new List<int>();

    MyList will be a List... it's only allocated once, that is true. You can reuse it every frame by adding elements to it like so:
    MyList.Add(1);

    Now, here is where it gets interesting. List<T> is not a primitive type by any means. It is a wrapper to add generic support to arrays and some extra syntactic sugar. The List<T> class itself actually uses an array internally to store its values.

    When you say: var x = MyList[1], internally List<T> does something like:

    return _backingArray[1];

    Now, when you create a new list, it creates an array of an initial fixed size, which I believe is 4 though I'd have to go back to the documentation to see exactly, but the constructor of List<T> looks something like this:

    Code (csharp):
    1.  
    2. public List<T>()
    3. {
    4.     _backingArray = new T[4];
    5. }
    6.  
    So, if we then add 5 items to the array:
    Code (csharp):
    1.  
    2. MyList.Add(1);
    3. MyList.Add(2);
    4. MyList.Add(3);
    5. MyList.Add(4);
    6. MyList.Add(5);
    7.  
    We have a problem because the array has only 4 elements in its capacity. But, List<T> magically handles that for us by automatically resizing the array. And by resizing, I mean it creates a brand new backing array with a higher capacity and copies the old array to it.

    Now, here's the kicker. Every time List<T> needs to increase the size of its internal array, it doubles it. So, in pseudo-ish code, it looks something like this:

    Code (csharp):
    1.  
    2. public void Add(T item)
    3. {
    4.    if(_currentListSize == _backingArray.Length)
    5.    {
    6.         var newArray = new T[_backingArray.Length * 2];
    7.         for(var idx = 0; idx < _backingArray.Length; idx++)
    8.         {
    9.             newArray[idx] = _backingArray[idx];
    10.         }
    11.  
    12.         _backingArray = newArray;
    13.    }
    14.  
    15.    _backingArray[_currentListSize++] = item;
    16. }
    17.  
    So, every time you reach the capacity of the List<T> it allocates a new array internally, so it will allocate. List<T> is also not the only collection that does this. If you cannot see this, I highly recommend you start doing some deep diving into the MSDN documentation on how collections work. If you're not seeing new allocation, then either the profiler is reporting it incorrectly, or you're doing something wrong.

    If you want want a better idea try doing this immediately after adding an object:

    Code (csharp):
    1.  
    2. var allocated = GC.GetTotalMemory();
    3.  
    You'll need to do this immediately after adding to make sure you catch it before it runs a collection and reclaims the memory that was held by the old array.

    Also, if you want I can dig up a class I wrote that monitors garbage collection in multiple generations and can fire a delegate for you every time a collection happens. It's pretty simple.
     
  27. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You're always keeping at least one reference to your Test class in that variable. You can actually create a class instance without assigning it to a variable, just use new Test() as below:
    Code (csharp):
    1.  
    2. for (int i = 0; i < iterations; i++) {
    3.         new Test();
    4.     }
    5.  
    Calling Destroy() just marks an object for deletion, so you can have an object that has been destroyed, but is not technically null. Unity won't actually null out and destroy those references until the end of the frame.
     
  28. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    1,033
    I would love to see that class! I tried to write something like that but I noticed I often got negative delta values from successive GetTotalMemory(), like if the collection had already happened, which it hadn't according to the profiler.
    I gave up in the end :(
     
  29. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    The link in the comment shows where I got this code from initially and I modified it slightly. This will notify you when a collection takes place, after it has occurred so it won't help you when making a call to GetTotalMemory but at least you can track collections. The code here uses an event which should probably be swapped out with a multicast delegate instead, but that's simple enough to do.

    I'm actually working on a future asset that will include this as a set of tools for monitoring / analyzing GC and analyzing classes and objects for stripping for troubleshooting purposes. Apologies for the formatting, I can't stop the Unity forum from stripping out my indents for some reason.

    Code (csharp):
    1.  
    2. using System;
    3. using System.Threading;
    4.  
    5.  
    6. namespace ParentElement.Messaging
    7. {
    8.   //The following class is from:
    9.   //Jeff Richter - http://www.wintellect.com/CS/blogs/jeffreyr/archive/2009/12/22/receiving-notifications-garbage-collections-occur.aspx
    10.   internal static class GcNotification
    11.   {
    12.   private static Action<Int32> _gcDone; // The event’s field
    13.   internal static event Action<Int32> GcDone
    14.   {
    15.   add
    16.   {
    17.   // If there were no registered delegates before, start reporting notifications now
    18.   if (_gcDone == null) { new GenObject(0); new GenObject(2); }
    19.   _gcDone += value;
    20.   }
    21.   remove
    22.   {
    23.   if (_gcDone != null) _gcDone -= value;
    24.   }
    25.   }
    26.   private sealed class GenObject
    27.   {
    28.   private readonly Int32 _generation;
    29.   internal GenObject(Int32 generation) { _generation = generation; }
    30.   ~GenObject()
    31.   { // This is the Finalize method
    32.   // If this object is in the generation we want (or higher),
    33.   // notify the delegates that a GC just completed
    34.   if (GC.GetGeneration(this) >= _generation)
    35.   {
    36.   //Thread safe get of the _gcDone delegate - will not be interrupted
    37.   var temp = Interlocked.CompareExchange(ref _gcDone, null, null);
    38.   //Fire the event
    39.   if (temp != null) temp(_generation);
    40.   }
    41.   // Keep reporting notifications if there is at least one delegate
    42.   // registered, the AppDomain isn't unloading, and the process
    43.   // isn’t shutting down
    44.   if ((_gcDone != null) &&
    45.   !AppDomain.CurrentDomain.IsFinalizingForUnload() &&
    46.   !Environment.HasShutdownStarted)
    47.   {
    48.   // For Gen 0, create a new object; for Gen 2, resurrect the
    49.   // object & let the GC call Finalize again the next time Gen 2 is GC'd
    50.   if (_generation == 0) new GenObject(0);
    51.   else GC.ReRegisterForFinalize(this);
    52.   }
    53.   else { /* Let the objects go away */ }
    54.   }
    55.   }
    56.   }
    57. }
    58.  
     
    00christian00 likes this.
  30. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Actually I see that my original statement was abit wrong, there are 2 things that happens, First we allocate a reference on the stack, then when the "new" operator make a instance of it, it will allocate on the Heap(Reference type), Right? So its the Heap size that will increase in size not the Stack (my bad, <insert epeen excuse> ) . But! Just because HEAP size gets larger doesn't mean we get GZ or overhead(its the overhead you should worry about) that only happens if the HEAP block get changed or allocated, normally on deletion and new instance allocation. This is the reason my code show clean HEAP but increase in size, there is nothing bad with a large HEAP as long as the reference/pointer styes with the STACK without change. Its like a kid holding a balloon, the kid is the STACK and the balloon is the HEAP. Lets say we stop the list at 200, no overhead will occur.

    Dustin; I am fully aware the LIST does array internally, i just find LIST more intelligent to use when we want to work with Vector3 in this example.
     
  31. BornGodsGame

    BornGodsGame

    Joined:
    Jun 28, 2014
    Posts:
    580
    This is a great list. The one I can add is to call GC yourself whenever there is a point in your game where it won´t be noticed. I have a large UI that gets pulled up when a player is inside a small room and clicks on an item. The UI has a lot of data, so I know for at least the first second the players eyes will be frozen on the data and they will not notice GC. On scene changes is another example.

    But like everything else with optimization, it is mostly just a matter of learning what are the bad things, and then avoiding them whenever possible.
     
    Ironmax likes this.
  32. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Only kind of right.

    1. Heap size does affect the GC, though minimally. Heap complexity has more of an impact, but regardless, every time the GC runs it has to examine every object on the heap to check for those references, so it does matter. Those objects will at least get examined by the GC regardless of whether there are still references.

    2. Heap allocation (size increase) DOES matter, because the GC is triggered automatically every time x number of bytes (generally around 1 MB) get allocated on the heap, so as you increase the size of that heap you are triggering the GC and telling it to look for things eligible for collection.
     
    angrypenguin likes this.
  33. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    I totally agree
     
  34. Sebioff

    Sebioff

    Joined:
    Dec 22, 2013
    Posts:
    218
    Well yes, obviously if you stop putting items into the list at 200 there won't be any allocations after that. In that case you might want to consider instantiating the List with a capacity of 200 in the first place (new List<Vector3>(200)), then you're entirely avoiding the internal array resizes that cause the garbage (until you add item 201 of course).

    And yeah, I think this thread nicely demonstrates that avoiding garbage allocations is not that trivial sometimes ;)
     
    Ironmax likes this.
  35. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Right, so now we get closer to my point.

    1. GC allocation can happen when new instance allocation happens on the heap
    2. GC allocation can happen if the size gets to big
    3. GC allocation can happen if you unbox the stack.

    What will not happen
    1. GC allocation will not happen if the stack is unchanged even the size of the HEAP is increasing.
    2. GC allocation will not happen if the typevalue stayes on the stack (no instance or class)
    3. GC allocation will not be invoked if using struct since it happens on the STACK

    Doing heap allocation on Update or forecearh is just asking for trouble..

    And finally remember that strings are also a array of letters..
     
    Last edited: Oct 12, 2015
  36. BornGodsGame

    BornGodsGame

    Joined:
    Jun 28, 2014
    Posts:
    580
    Well, partially the problem with threads like this is that the audience and the teachers are in different classrooms. It is nice to have you guys doing the deep thinking type stuff, but I would guess the majority of people reading this thread are more in the GC101 phase who are getting huge spikes every few seconds... in which case teaching them the big-bad things to avoid is important without confusing them with the underlying theoretical stuff. Also teaching them that they can call GC at opportune times to maybe prevent it from happening at inopportune times..
     
  37. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,272
    It's quite the opposite:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class Alloc : MonoBehaviour
    7. {
    8.     List<Vector3> VectorList = new List<Vector3>();  // list
    9.     float[] floats = new float[3]; // Array
    10.  
    11.     void Update()
    12.     {
    13.         int times = (int)Mathf.Pow (3, Time.frameCount);
    14.         for ( int c = 0; c < times; ++c )
    15.             VectorGenerator(Vector3.one);
    16.     }
    17.  
    18.     void VectorGenerator(Vector3 vector)
    19.     {
    20.         VectorList.Add (vector);
    21.  
    22.         floats[0] = vector.x;
    23.         floats[1] = vector.y;
    24.         floats[2] = vector.z;
    25.     }
    26. }
    27.  
    Screenshot 2015-10-12 19.11.59.png

    Screenshot 2015-10-12 19.12.26.png
     
  38. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Ehh no, Your system requirement failed your ambitious level, that's what I see, don't blame large HEAP size.

    Your code is also the totally opposite of how you should code properly.

    Games comes with system requirement, if you really need to fill that much memory you need to increase the system requirement.
     
    Last edited: Oct 12, 2015
  39. BornGodsGame

    BornGodsGame

    Joined:
    Jun 28, 2014
    Posts:
    580
    Not worth following this thread if people are just going to create crazy situations to disprove something that is generally good advice for most users. Are you posting in this thread to actually help people, or are you just trying to be antagonistic and confuse people who might have learned something they could put into practical use?
     
  40. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,272
    eheh, I wouldn't use code like that in any environment
    just wanted to demonstrate that the example you started with does the exact opposite of what you claimed, after reading this thread I couldn't resist: sorry.

    @Carve_Online: if not freeing resources you allocate and let GC do its job isn't educational enough for you, then I am sorry, too.
     
  41. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    I hope not, you do realize that your allocating more blocks than increasing the size of the heap right? --> int times = (int)Mathf.Pow (3, Time.frameCount);

    If you allocated that int at start, things would be very different.

    STACK size is small HEAP can be large.. Welcome to dynamic memory.
     
  42. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,272
    ehm actually no : this was a very bad artificial example; it runs out of mem cause the requested allocation size is extremely huge after a short while;- my intent was to show just that the allocation indeed occur and to see the actual number in the profiler one needs to sometime employ extreme measures :) - as was the original @superpig intention I believe
     
  43. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    My question for you is, was it the HEAP size or the STACK size? Memory is dived in to 2 parts. We can all agree that your memory went huge.
     
  44. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Code (CSharp):
    1.     void Update()
    2.     {
    3.         int times = (int)Mathf.Pow (3, Time.frameCount); // <-- your problem is here
    4.         for ( int c = 0; c < times; ++c )
    5.  
    6.             VectorGenerator(Vector3.one); // <--- not here
    7.     }
     
  45. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,272
    let's assume that the times variable is a member var and
    Code (csharp):
    1.  
    2. static int times = POSSIBLY_NOT_SO_VERY_HUGE_BUT_STILL_LARGE_IINTEGER_CONSTANT;
    3.  
    do you think that there will be allocations and that possibly there might not be enough memory since the list is not being emptied and is still referenced ?
     
  46. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,507
    If you run out of stack memory, your process crashes. Stack is generally 1 MB large, at least on Windows. Also, as soon as your function returns, everything on the stack that you allocated gets destroyed. Stuff that you put into List<T> ends up all on the GC heap.
     
    angrypenguin and Ironmax like this.
  47. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Thank you
     
  48. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Here is a good, in-depth explanation of how the GC works:
    https://msdn.microsoft.com/en-us/library/ms973837.aspx

    Wrong. Increase in Heap size triggers garbage collection. The threshold depends on the platform and version of the garbage collector so I couldn't give you any exact numbers, but it's not a lot. When pooling (as you're essentially doing), those objects become old and are moved from Gen0 to Gen1 to Gen2 (their final resting place). Gen2 is the slowest to reclaim, not efficient, but you don't care because collections of Gen2 happen very infrequently. However, if you keep increasing the size of the heap, of those objects, eventually they may be moved to the large object heap. An increase in size of the Large Object Heap will trigger Gen2 collections which are less efficient and can actually cause more problems.

    Furthermore, garbage collection will be triggered when whatever system you're on is low on memory... it does this to try to reclaim memory if possible, so sometimes even a small increase in heap size can trigger collection.

    Sorry @Ironmax, but the majority of what you're spouting is complete nonsense and you're going to lead people in the wrong direction or lead them to over-optimize things they probably shouldn't worry about which in turn might lead to degraded performance.
     
    Sebioff and hippocoder like this.
  49. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Damn you ruined all the fun by stating the obvious.
     
  50. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Ehh no, while the size is increased it doesn't 100% trigger the GC allocation. I seen to many profiles to prove this.

    That is the most silly thing I heard to day, how can you over-optimize your game? How can a well optimize game be bad? Are you telling others to not optimize there game? You must be for real..
     
Thread Status:
Not open for further replies.