Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Is Object Pooling redundant?

Discussion in 'Editor & General Support' started by Freaking-Pingo, Jan 26, 2017.

  1. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    310
    Hi Uniteers, I saw this answer on stackoverflow today that basically stated:

    "From about 2014, you absolutely do not pool in Unity.
    Many hobbyists have not learned this new information, and it causes considerable confusion.
    Unity completely reengineering Instantiate and game objects, so you must not pool.
    Nowadays you very, very, VERY rarely need to pool in Unity."


    I have been taught always to pool my objects, and I can't find any information about Unity doing automatic object pooling. Can someone enlighten me on this answer whether there is some truth to it or wether it is simply bogus?

    Link to thread: http://stackoverflow.com/questions/...ct-on-return-to-pool-perhaps-using-scriptable
     
  2. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    967
    Pooling in Unity is used to prevent memory allocations in order to avoid later garbage collection which can cause hitches in the game. It is *not* generally used because instantiation takes too long. So creating objects at runtime in Unity most definitely does allocate memory, and if those objects go out of scope at some point they *will* be collected by the garbage collector, and if that happens enough times you will get hitches.

    So yeah, that advice seems absolutely wrong.
     
    Boodums and Propagant like this.
  3. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    in my experience it is pretty much a necessity to pool if your game is destroying and instantiating lots of objects. If i do not do so the destroy process creates a lot of garbage for the garbage collector to cleanup which causes micro stutter.
     
  4. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    Pooling also helps prevent instantiation freeze. For games that have objects being created and destroyed regularly (mobs in RPGs for instance), pooling is very necessary. It cuts instantiation freeze and keeps garbage down to a minimum. Also all the above points.
     
  5. RockoDyne

    RockoDyne

    Joined:
    Apr 10, 2014
    Posts:
    2,234
    It's mostly a matter of extremes. If you only instantiate something every couple minutes, then it's pretty safe to not pool. If you are going through objects every few frames, then a pool is absolutely necessary. What you do in that middle ground is mostly down to your programming dogma/mindset.
     
  6. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    1,035
    No wonder I see indie games moving 3 polygons lagging.... People should stop giving advices like this, especially without context.
    Although it's true that optimization tips are often outdated, pooling can never be outdated.
    Unity can optimize whatever they want, but moving an object( which is what you do when you pool) can never take as long as instantiating multiple classes, and fire all its initialization methods, PERIOD.
    So maybe if all you do is instantiate few meshes and your target is a pc then MAYBE you may not need it, but if you need to instantiate something like a character with an animator component, plus some other script attached which all have start, awake and so on and your target is mobile, good luck then!
    It takes so little to pool that it's not even worth benchmarking the first scenario, it will take more to do the benchmark than write the pooling code.
     
    Propagant, SparrowGS, Ryiah and 2 others like this.
  7. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    man, this guy should really tell the Unity engineering guys that you don't need to pool any more.

    those scrub guys working on UnityEngine.dll even pool List<T>!

    Scrubs!
     
    Westland, Ryiah, MV10 and 1 other person like this.
  8. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    This.

    It is nothing to do with Unity even. In every language and API for the past decades I've always allocated storage for a max # of objects.

    Except I do it in non generic way. Bullet pool. Enemy pool. Collectible pool. Etc. And it NEVER allocates. A developer should know how many instances are needed to handle the max # of objects that can / will be active at any one time. Heck the game can and perhaps should be built around the limit. That's what I do anyway.

    Bad advice out there. You wonder if people just are so bored they write nonsense or they truly don't understand it is not even a Unity-specific thing.
     
  9. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    967
    What surprises me is that from the photo of that user it appears to be one of the top 25 users on Unity Answers who mostly gives out useful advice. But yeah, this one is just way off.
     
    Freaking-Pingo and GarBenjamin like this.
  10. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    What I would like to know is why he said that. In which way did Unity redesign instantiation in 2014? The answers in this thread are very unhelpful - bluntly stating it's wrong, seemingly based off past experience. But the entire point of the guy's post is that something has changed in the internal instantiation code. Why hasn't anyone addressed this point specifically? I suppose I'll have to test it myself when I get a chance...
     
  11. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    I wish this was true but sadly it's not.

    The interesting thing is could this become true?

    [Idea] The Unity Zombie Pool
    What if Unity could dynamic pool/instantiate/destroy under the hood. Any destroyed gameobject is just disabled and put in a 'zombie pool' if memory is low zombies are cleared from memory to make way for new objects. If another same object is instantiated Unity could reanimate an object from the zombie pool.

    Ideally the zombie pool could have parameters or even learn as the game is played so it knows roughly how many objects are used in a given scene.
     
    Mystic_Quest likes this.
  12. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    Object pooling definitely helps performance, even on PC, when there are a bunch of objects in a scene. Creating/instantiating and destroying objects is dramatically slower than re-using objects through an object pooling system.

    For the absolute best performance, I would suggest eliminating the individual game objects completely and using what I call an "instancing pool". With an instancing pool, you do not have any object overhead. You just have an array of a custom struct to represent the data for the objects (such as position, location, movement vector, TTL, etc) and an array of Matrix4x4 to shovel the data into the Graphics.DrawMeshInstanced method. The instancing pool will use less memory and offer far better performance than even the best object pool.
     
    JasonBricco likes this.
  13. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    This would be a terrible idea. A zombie pool would just be dead weight for most of us. Every competent programmer can easily build an object pool and customize it to their own needs. We do not want the overhead of a zombie pool running in the engine like you are describing.
     
    Ryiah and MV10 like this.
  14. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    It doesn't matter why he said it, it's still wrong and the answers in this thread are correct.

    Alloc, Release, GC ... Always.
     
  15. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    I also want to address a misconception some people have regarding pooling. Some people have come to the conclusion that they do not need object pooling because it did not seem to improve performance when they tried it. The truth is that object pooling will always offer better performance than creating and destroying game objects.

    There are a number of possible reasons people might not immediately see the benefit of object pooling. Here are two of the big ones:
    1) The overhead of the Update functions in the individual game objects might be causing a large delay. For added performance, rename the Update function in the individual game objects to something like ManualUpdate and call those from the Update function in the object pool manager. This will dramatically reduce the number of Update functions in the scene, and that will improve performance.
    2) There may simply be a draw call bottleneck, even on PC. For example, if you have a scene with thousands of objects (lasers, bullets, missiles, rocks, grass, asteroids, balls, etc), you need to figure out how to reduce the draw calls. Object pooling does not automatically ensure better dynamic batching or better instancing.

    The only way to ensure perfect GPU instancing is to build an instancing pool (instead of an object pool) and then use the Graphics.DrawMeshInstanced method. This will dramatically reduce draw calls, which will dramatically improve frame rate.

    If there is somebody claiming pools are no longer needed when doing large numbers of object, then that person is wrong. If that person could not find performance using pools, they need to try harder. In scenes with thousands of objects, I can consistently get at least ten times as much performance using an instancing pool than I would by instantiating and destroying game objects over and over.
     
    zombiegorilla and GarBenjamin like this.
  16. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    It need not be mandatory, and actually could be a component or inherited MonoBehaviour sub class so you can use it or not as you see fit.

    And you are correct any half competent programmer can build an object pool (List<GameObject> pool;), however a pooling system that is built into Unity the game engine could do things your programmer cannot under the hood of the Unity game engine, where a lot of your object elements are actually used, Physics, Meshes, Materials, Shaders are all things Unity handles for you.

    After all your object pool is just GameObject class instances with references to subcomponents and things stored in the Unity Engine.

    Therefore a Unity object pooling subsystem might just be better (more efficient/faster) than any a programmer can write this side of the game engine source code.

    But this would need to be tested and analysed by Unity themselves, who knows it could pay massive dividends or hardly any but ease of use.

    Note: Unity did mention in their last event that they are looking at making a leaner/better gameObject/component API, as MonoBehaviour (MB) has become the kitchen sink of objects e.g. what is the life cycle event order of an Instantiated MB?
     
  17. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    It could be that back in 2014 Unity made some kind of change along these lines under the hood in the way they allocate and manage objects. And the guy who wrote the original answer misinterpreted this to mean aha! Unity is doing it for us now we don't need to.
     
  18. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    Unity was claiming they were going to do delayed transform updates, but I don't think that improvement made it into Unity 5.6. That improvement will improve the performance of existing object pools, especially when re-enabling an existing game object and setting a new position and rotation.

    Building a zombie pooling system like you described in this thread would only create more overhead. It would provide no benefit to users. It could never truly work without any user intervention, because there are custom variables that need to be reset when enabling a game object, and the specifics will vary with every project. The Unity Engine could never automagically determine which variables needed to be reset.

    A better solution would simply be to have somebody at Unity make an official object pooling asset and release it for free through the Asset Store. That way new users could grab and and tweak it as needed for their specific purposes. That would definitely be better than have a "zombie pool".
     
    Martin_H likes this.
  19. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Probably unlikely. A reference is a reference, wherever it's stored. The pool just keeps it off the GC radar. Nothing particularly magical about that.

    Which is completely unrelated to the rationale for object pooling.
     
  20. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,042
    It's usually safe to ignore the advice of anyone claiming "always" or "never" about something. It is a silly post. Read @ShilohGames post above.
     
    PlayCreatively, Ryiah and Martin_H like this.
  21. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I just wanted to add that pooling to improve efficiency is not limited to GameObjects. This holds true for any reference type (class) in .NET. If you have code that creates and destroys a lot of classes, even if they're not GameObjects, you'll be allocating to the heap and triggering more GC cycles. So pooling is important.

    That being said, too much pooling can have a detrimental effect too, depending on the complexity of your objects. If the objects you're pooling have references to lots of other objects, which also have references to other objects, etc... this creates what's referred to as heap complexity. The number of objects on the heap isn't super important, but the complexity is, as the GC has to follow the reference paths of every object referenced to determine if it's still being used and can be destroyed.

    That being said, long lived pools do avoid this a bit. There are essentially 3 generations of allocations. Gen0, Gen1 and Gen2. When a GC cycle runs, any objects that are still being referenced in Gen0 are moved to Gen1. When a collection runs against Gen1 any objects that are still alive are moved to Gen2. Now Gen2 (the third generation) is collected far less frequently. This helps relieve GC pressure by not re-evaluating objects that are less likely to be dereferenced. If they're not sort lived, why check them every cycle?

    That does come at a bit of another cost though, depending on the size of your object, and that's memory consumption. Gen2 is collected less frequently making the GC cycles themselves more performant, but the memory used by Gen2 objects may take a long time to get reclaimed. So even if you've removed references to those objects and aren't using them anymore they may hang out in physical memory for awhile. Games that have multiple scenes / transitions can avoid this issue as well a little more easily by forcing a GC.Collect between scenes to make sure the stragglers are cleaned up.
     
    DiogoDB, BTStone, Ryiah and 1 other person like this.
  22. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    See my above post... not off the radar, just keeps it from being collected. Generational mechanisms as a side effect of pooling do take it mostly "off the radar" though.
     
  23. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    OK so how do I reset a disabled gameobject from a pool?

    What if the object has a rigidbody/a particle fx/a trial renderer?

    What if the object contains links to other game objects/components that need to be reset e.g. status/score/ui/status/map blip/sfx?

    Pooling can bring about a lot of complexities when things interact or you reuse subelements e.g. turrets on starships/homing missiles linked to a units targeting system?

    I think if pooling were built into the API events/method calls could be triggered that are expected when a pooled object is zombified and reanimated.
     
  24. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    You just listed reasons why your zombie pool idea won't work. With custom object pools, the dev can reset things in the enable function, including position, rotation, particle systems, health, AI state, etc. If there was a magic zombie pool built into the engine, it would be very difficult for the engine to figure out what needed to be reset.

    Anyway, this is completely unrelated to the core topic of this thread.
     
    MV10 and zombiegorilla like this.
  25. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,042
    You can do that now very easily, that is why overly generalized solutions make no sense. Pooling is trivial to write, but endlessly customizable. Having extra stuff you don't specifically need defeats the purpose in the first place.
     
    MV10 and Martin_H like this.
  26. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    My point is there could be benefits within the Unity game engine if it supported pooling in the API.

    What about the potential for in engine memory optimisations, pooled resources can be stored in contiguous memory sectors speeding up their access times.

    With more upfront information from the developers for expected numbers of gameObjects, pre-allocated contiguous memory blocks (Physics/Materials/Shaders/Meshes/Animations) could boost performance.

    Contiguous memory allows very fast cache hit memory access times.

    Maybe Unity has a very clever memory allocation system that does well but I suspect with this approach it could improve the engine further.

    Side Note: Gamasutra used to have some very in depth articles on building a memory pooling system for your game engine that would provide contiguous memory blocks for performance.

    Good article on the performance impacts of good memory management -> http://www.gamasutra.com/blogs/Mich...a_Game_Engine_from_Scratch__Part_2_Memory.php
     
  27. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    As someone who reads these threads to learn, I don't come here to see so-called 'authorities' stating whether something is correct or not, as though one should believe something because someone else said so.

    I like some reasoning. Some explanation. The reasoning and explanation provided in this thread, from my perspective, is referring to how it has 'always been'.

    And then in that post someone suggests that things have changed. Are people saying that things haven't changed? That hasn't been made clear. Why would someone say that Unity re-designed the instantiation code if it never happened?

    And if it did happen, how did it happen? And is it really relevant for the need to pool objects or not?

    It's pointless now, though, since I can just test it myself. I didn't have a chance to when I posted that message earlier.

    And yes, object pooling in general tends to improve performance. I was just under the impression, from that guy's post, that Unity did something internally to make it unnecessary (they implemented pooling themselves, as a potential example).

    I don't really know what code runs internally when I call Instantiate or Destroy. That's the thing.
     
    PlayCreatively and Moonjump like this.
  28. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    967
    I don't pool for instantiation speed since it's not relevant to my needs, so I can't answer you there. Most of my instantiation is actually non-monobehavior objects, so what Unity is doing internally doesn't matter. However, I do have to create a lot of objects at runtime and if I didn't pool them, which is how I started out, some frames have hundreds of kilobytes of allocations and performance suffers noticeably. So pooling is still very, very relevant in the latest versions of Unity which is what I'm using.

    As I said, I started out not pooling. Then I tested and profiled and found stuttering because of all the allocations. I spent days moving nearly every allocation into a pool and I no longer have those issues.

    In other words, the usual advice to "profile before optimizing" always applies.
     
  29. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,553

    The guy who wrote it either have very little experience or never made a game for a mobile platform or.

    Pooling is absolutely necessary on mobile platform, especially if it is a low-power device. It speeds things up quite a bit, on at least one occasion it prevented random crashes. It is still useful.
     
  30. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,042
    Memory pooling != gameobject pooling. I understand it is confusing as they both use the word pool, but they aren't related.
     
  31. Moonjump

    Moonjump

    Joined:
    Apr 15, 2010
    Posts:
    2,572
    I agree with what you are saying. The change is potentially interesting. It doesn't matter if it actually makes pooling redundant. The point is something has changed, which might affect individual projects (for good or bad), or have the potential to improve a project.

    Reading the linked thread, the person seems to be only saying instantiate was made much faster, making the need redundant (he also says it was a screw-up by Unity that it wasn't fast before, which adds more doubt to his understanding).
     
  32. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    There are always changes Unity can make to improve performance, but it is extremely unlikely Unity will ever make a change that will completely eliminate the advantages of an object pool. Instantiate and destroy operations will probably always use more CPU time than comparable Enable/Disable operations.

    I have done extensive testing within my space game with thousands of laser projectiles flying around, and instantiating/destroying was always slower than object pooling and massively slower than instancing pools. The absolute best performance in all of my testing was with instancing pools using the Graphics.DrawMeshInstanced method.
     
  33. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    Okay, maybe I missed that part. I was under the impression (as posts in this reply are saying as well) that we pool for memory reasons, not because the call itself is slow. And I thought that's what he was referring to as well.

    I'm still interested in knowing about these redesigns Unity does and how they may impact my projects, though, and I wish Unity would be a bit more vocal about them.
     
  34. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    In scenes with lots of game objects getting rapidly created/destroyed, there is a significant performance advantage to using pooling instead of instantiating and destroying game objects. There are also memory reasons for using pooling.
     
    zombiegorilla likes this.
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    This guy has a habit of making authoritative statements about things that are categorically and provably 100% wrong. As to why, I dunno. Drugs? Mind-controlled by aliens? He lives in an alternate universe where logic and evidence don't apply? Who knows. ;)

    --Eric
     
    zombiegorilla likes this.
  36. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    There will be 3 generations when Unity finally updates their Mono properly. As of now, Unity's still on Mark And Sweep.

    :((((((
     
    liortal likes this.
  37. greg-harding

    greg-harding

    Joined:
    Apr 11, 2013
    Posts:
    523
    You mean 3 generations of waiting, right...? :)
     
    perevezentsev and MV10 like this.
  38. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Zing!
     
  39. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    I just misunderstood what you referred to when you wrote the thread was unhelpful. The comments here are correct, but I guess if you want to know what internal improvements were made, then yeah, the thread is unhelpful -- because it isn't about improvements, it's about pooling.
     
  40. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Actually it depends on the platform currently. If you're building UWP with .NET Backend it's not using Mono. But yeah it *will* be 3 generations and given that .NET 4.x is being tested in the editor and talk of Netstandard support I don't think it'll be too long, though with IL2CPP I'm not sure how the GC is managed. At any rate, I based that post on what is upcoming (will I think very soon), otherwise it would soon be outdated. With Mark and Sweep, you do end up with the issue of heap complexity negatively impacting performance every GC cycle and an even bigger emphasis on avoiding unnecessary cycles.
     
  41. Harinezumi

    Harinezumi

    Joined:
    Jan 7, 2013
    Posts:
    54
    Hi there,

    I just created my object pool implementation (can share code if needed), trying to make it as lightweight and efficient as possible (using LinkedList for the pool, avoiding setting transform.parent, etc.). Then I compared it to instantiating-destroying prefabs and it turned out the object pool does not perform much better.

    Tests: I created a script that requests a number of prefab instances a second. It either instantiates them or gets them from an object pool. When the prefab instance falls into a trigger, it gets destroyed or returned to the pool, depending on which method is being used.
    The prefab I used for this test is 2 rectangular cubes linked (with box collider), the parent having a rigidbody.

    Results (first fps value is with instance-destroy, second is with object pool):
    1200 instances / second: 56 fps vs 57 fps
    1500 instances / second: 30 fps vs 32 fps
    1700 instances / second: 19 fps vs 22 fps

    So the object pool is slightly better, but not as much as I expected. I also checked it in the profiler, and there isn't any significant difference in where the performance goes (obviously, since the results are pretty close). So I started searching, and found this thread saying that possibly object pooling is unnecessary (which goes completely against my knowledge).

    So I'm not saying I agree with the quoted post from stackoverflow, but I'm wondering: in what cases would an object pool significantly improve performance?
     
  42. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    Try the test again but with instantiating something more complex like a character avatar with scripts attached, and see what the results are.
     
    Harinezumi likes this.
  43. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Keep in mind also that your overall average for probably won't be that much different, unless the objects are complex. What the object pools helps though is avoiding gc cycles which will help avoid intermittent stutter.
     
    Harinezumi and Whippets like this.
  44. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    Yep, stutter on instantiation and stutter on GC.
     
  45. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Instantiation is just memcopy right, you take a prefab/memory template and copy it into a block of memory and return a reference to the created instance?

    Destorying an object is just de-allocating that memory and it's reference.

    Pooling is disabling the object and re-enabling it when you need it to save the time it takes to memcopy a new one.

    Therefore pooling should be hugely faster than Instantiation. Unless it's the overhead of the elements of gameObjects within the Unity engine that cause it to be about the same in both e.g. Meshes/Colliders/Rigidbodies/Navmesh Agents/Monobehaviour and Unity Engine House Keeping.

    A simple test would be to create lots of none-unity objects and delete them and create more then do the same with a pooling system then compare with varying Unity components and Prefabs...?
     
  46. Harinezumi

    Harinezumi

    Joined:
    Jan 7, 2013
    Posts:
    54
    Thanks for the suggestions. I have not yet tried with more complex objects, but I did try creating objects in big bursts with instantiate-destroy and object pooling, and there the advantage is obvious.

    Test: I modified the test script to request a number of objects in the same frame every # seconds. The request was either completed by instantiate or by getting it from the object pool. The rest of the parameters were the same as in the previous test (simple prefab with rigidbody, destroyed or returned to pool when it entered a trigger).

    Results (first fps value is with instantiate-destroy, second with object pool):
    1200 instances / every 5 seconds: 47 ms (~22 fps) vs 27.5 ms (~36 fps)
    1500 instances / every 5 seconds: 60 ms (~16 fps) vs 34.5 ms (~29 fps)
    1700 instances / every 5 seconds. 67 ms (~15 fps) vs 39 ms (~25.5 fps)
    2000 instances / every 5 seconds: 80 ms (~12.5 fps) vs 48 ms (~21 fps)

    Memory-wise, there is not much surprise: instantiate-destroy has big spikes in GC Allocated and Total Allocated when requesting the objects, while the object pool has a low, continuous load, and the object request is not noticeable.

    So an object pool seems to be useful at least in case of bursts of objects.
     
  47. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Even in "non-burst" scenarios it is useful. You're not going to see it so much in a test scenario, but what happens is after so many megs of memory are allocated, the garbage collector kicks in and runs a cycle to reclaim dereferenced memory. So even in non-burst scenarios, it could trigger GC cycles at unexpected times and result in stutters when you don't want them.

    That being said, I've mentioned this before, but heap size and complexity (mostly complexity - i.e. references referencing other references, etc) also impact GC speed and the Unity GC is not generational. This means that in some cases, pooling can cause some performance degradation because it makes each GC cycle that does run take longer. In the vast majority of cases though, pooling will be a big benefit... especially for objects that are instantiated and destroyed frequently.
     
  48. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    It should be pretty straightforward to see the value in the Profiler.

    Anything that reduces garbage is going to be highly desirable in the long term. Unless you're making something very simple in scope then you definitely won't be ignoring anything that reduces garbage and improves framerate.

    It's always good to test the advice you find on the internet. Don't just assume that someone knows what they're doing because they made a blog post.
     
    Dustin-Horne likes this.
  49. Harinezumi

    Harinezumi

    Joined:
    Jan 7, 2013
    Posts:
    54
    I did check the profiler, and the difference I noticed was in the allocation pattern, not the amount. Perhaps I'm not using the profiler right, what other differences do you think I should see?

    I'm doing these tests specifically because I don't believe everything I read, I test it myself. Intuition told me that I should benefit from an object pool over instantiate-destroy, and when I didn't see it, I started searching for the reason, asking questions, and testing.
     
  50. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    How and when it allocates with or without pools very much affects performance. There might be a point where the garbage collector has a massive "stop the world" event. Perhaps it's after half the memory is garbage, in which case that pause could be quite significant. If you've reused objects well the GC never reaches a massive amount where sorting out the garbage can take several frames.

    The points at which the GC decides to kick in with its cleanup may differ from release to release and VM to VM (Mono vs. IL2CPP could differ in allocation behaviour), and it might be configurable outside whichever app you're running in. Don't rely on any specific number, just go easy on the memory pressure. When a game runs over many hours it all piles up if done less optimally.