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. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Official Memory Allocator Customization in Unity 2021 LTS

Discussion in 'Scripting' started by lyndon_unity, Apr 20, 2022.

  1. lyndon_unity

    lyndon_unity

    Unity Technologies

    Joined:
    Nov 2, 2017
    Posts:
    52
    Efficient memory access patterns are a key factor in creating high performance software applications. The Performance Optimization Team have recently taken a deeper look at the memory allocation systems within Unity. We identified settings that could be used to optimize for a specific applications unique needs and verified the gains in a selection of games and demos. We exposed these settings so now you too can make sure you’re getting the best memory utilization for your game. Measure how much memory is used by different allocators, then customize their size to suit your game. Check out the documentation, and let us know how it’s going – we’d love to hear about your experience.
     
    Last edited: Apr 20, 2022
    DevDunk, Petr777, makaka-org and 3 others like this.
  2. Hyp-X

    Hyp-X

    Joined:
    Jun 24, 2015
    Posts:
    421
    The documentation says:

    The examples in this documentation use the memory usage reports that are written to the log when you close the player or Editor

    How do I get the usage report on platforms where closing the player is not possible?
    (The only means to close is the OS killing the player which will obviously not cause a report to be written)

    The ideal would be that I could call a Unity function to produce a memory usage report at runtime any time (it doesn't have to be fast)
     
  3. Kim-Riber

    Kim-Riber

    Unity Technologies

    Joined:
    Feb 25, 2011
    Posts:
    25
    Hi Hyp-X
    You can call Application.Quit() to make the app exit and print the report, but I agree; we should have an api that either prints the report to the log or returns a string with the report so that you can print, parse or handle it in the way you want. I'll add that to our list.
    Thanks for the feedback
     
  4. Hyp-X

    Hyp-X

    Joined:
    Jun 24, 2015
    Posts:
    421
    I tried this on PS4 where I can enable Application.Quit() support, but the memory report was not printed.
    I will follow this up on the PS4 forums as there might be non-public information involved.
     
  5. lsunky

    lsunky

    Joined:
    Apr 5, 2022
    Posts:
    1
    hello,have you get the usage report on platforms sucessful? I want to get the usage report on Android~
     
  6. sambonfire

    sambonfire

    Joined:
    Apr 6, 2017
    Posts:
    2
    Hi,

    I just wanted to offer some feedback. I'm very excited to use these new APIs and I am sure it will have a positive impact on the editor and player.. but I'm very confused by the documentation and how to correlate the report when you quit to the allocators listed in the memory settings.

    For example, in the docs:

    https://docs.unity3d.com/2021.3/Doc...ator-customization.html#customizingAllocators

    It has this snippet showing an example output from the log file:

    [ALLOC_TEMP_TLS] TLS Allocator
    StackAllocators :
    [ALLOC_TEMP_MAIN]
    Peak usage frame count: [16.0 KB-32.0 KB]: 802 frames, [32.0 KB-64.0 KB]: 424 frames, [2.0 MB-4.0 MB]: 1 frames
    Initial Block Size 4.0 MB
    Current Block Size 4.0 MB
    Peak Allocated Bytes 2.7 MB
    Overflow Count 0
    [ALLOC_TEMP_Job.Worker 18]

    So, just looking at this output, how do I know which allocator in the Memory Settings it corresponds to? Are we expected to just match numbers against the options? I feel like I must be missing something, because it seems like the names shown in the log file should somehow corresponding to the names in the memory settings.. otherwise I don't see how you can action on much of this. Am I missing something?

    thanks
    sam
     
  7. G_Wojo

    G_Wojo

    Unity Technologies

    Joined:
    Feb 8, 2017
    Posts:
    34
    Hi,

    "ALLOC_TEMP_TLS" is the name, where "TLS Allocator" is a type of the allocator.
    If you search on the page that you shared `TLS` you will get section:
    Thread Local Storage (TLS) stack allocator

    How TLS works, it is not single allocator but it have separate instance per different thread, where each of them is categorise in some configuration groups. Lets look on your log and we have:
    • ALLOC_TEMP_MAIN
      • what it mean: Temp Allocator for main thread
      • config: Thread Local Storage (TLS) stack allocator :: Main Thread Block Size
    • ALLOC_TEMP_Job.Worker 18
      • what it mean: Temp Allocator for job worker thread 18
      • config: Thread Local Storage (TLS) stack allocator :: Job Worker Block Size

    Sadly this is not so easy. What you see at the shutdown is just summary of allocator use in single application run. This is very important as every run can have a little bit different characteristics and return different values based on the things that will happen in it.

    Our recommendation would be to tweak this values carefully. I would say that our guide would be to do it close to release where estimation of memory should be close to final product. You should then collect informations from multiple longer runs and base on them decide if you want to lower or increase values.

    In reality there is no one way of handling it that is why we gave example for every allocator where we describe logic behind changes we would do in given case.


    We tried to make whole thing as logical as we could be but sadly Unity memory system is complicated. That is why I would say that this feature has high entry point as it require some knowledge about our native memory system.

    If after this explanation you are still lost, feel free to drop some of yours examples and what you would change based on them. We will then discuss if this would work and in case not why.
     
    MartinTilo and peter_hall like this.
  8. sambonfire

    sambonfire

    Joined:
    Apr 6, 2017
    Posts:
    2
    Hi,

    I don't think I explained the issue I'm having accurately. My issue is really understanding from the "Memory Statistics" that is printed in the log file when you quit, or the profiler, and understanding which setting in the Memory Settings I should be changing.

    [Side note: if possible, I would suggest you just expose a method so we can dump this at any point we want to - that would solve the problem the mobile folks are having.]

    Let me try to give an example. Here is a snippet from my log file's Memory Statistics print out:

    Code (csharp):
    1. [ALLOC_TEMP_JOB_4_FRAMES (JobTemp)]
    2.   Initial Block Size 2.0 MB
    3.   Used Block Count 1
    4.   Overflow Count (too large) 0
    5.   Overflow Count (full) 704018
    6.  
    Based on the "Overflow Count", it looks like I really need to increase the size of this allocator.

    I also took a profile, and the unity profiler is littered with "fallback allocations" that look like this:
    FallbackAllocation.png

    So now I have some great data:
    • ALLOC_TEMP_JOB_4_FRAMES (JobTemp) - this allocator is overflowing and should be increased
    • the profiler reports that ALLOC_TEMP_MAIN is resorting to fallback allocations; I should probably increase it's size too

    So now, I open up the Memory Settings:

    MemorySettings.png

    And this is where I'm having trouble - I don't know which memory allocator to change to fix the problems, because the names don't seem to match. Does "ALLOC_TEMP_MAIN" correspond to "Fast Per Thread Temporary Allocators" or "Fast Thread Shared Temporary Allocators"? I have no idea. So I can start playing with the numbers, but I'm totally in the dark. Could the user interface be modified, or else the memory statistics and the profiler modified, so that the names are easy to correlate for a user?

    Re: suggestion that we do this when we are close to shipping: it makes me feel like you don't understand the challenges of game development -- at least those facing developers who aren't just making something extremely simple. When we are hitting these fallback allocators, it pollutes the profiles with fallback allocations -- and I assume we're taking a pretty serious performance hit! If I don't fix these, then my game will run poorer and perhaps even more importantly the editor will run slower, which impacts the entire team making the game.

    I hope that this explanation helps - do you understand the challenges that I'm having and why it's so important for me?

    thanks!
    sam
     
  9. G_Wojo

    G_Wojo

    Unity Technologies

    Joined:
    Feb 8, 2017
    Posts:
    34
    I will start with side note:
    I created task to add this API and also task to think about explicit mentioning setting that corresponding to given allocator. This should resolve the issue in the future.

    Till then let's look on final stats printed at the end of run and search for `ALLOC_TEMP_MAIN`. I got single result:


    [ALLOC_TEMP_TLS] TLS Allocator
    StackAllocators :
    [ALLOC_TEMP_CurlRequest]
    Initial Block Size 64.0 KB
    Current Block Size 64.0 KB
    Peak Allocated Bytes 0 B
    Overflow Count 0
    [ALLOC_TEMP_MAIN]
    Peak usage frame count: [8.0 MB-16.0 MB]: 1 frames
    Initial Block Size 16.0 MB
    Current Block Size 16.0 MB
    Peak Allocated Bytes 9.3 MB
    Overflow Count 0

    [ALLOC_TEMP_Background Job.worker 6]
    Initial Block Size 32.0 KB
    Current Block Size 32.0 KB
    Peak Allocated Bytes 0 B
    Overflow Count 0
    [.......​


    As you can see it is Stack Allocators entry under [ALLOC_TEMP_TLS] TLS Allocator. Quick check on page https://docs.unity3d.com/2021.3/Documentation/Manual/memory-allocator-customization.html for TLS we getting section of Thread Local Storage (TLS) stack allocator with Fast Per Thread Temporary Allocators.

    In this case it is ALLOC_TEMP_MAIN so
    Main Thread Block Size would be my choice. Some of the others are also not hard to connect:
    • ALLOC_TEMP_Background Job.worker #
      • Background Job Worker Block Size
    • ALLOC_TEMP_BakingJobs.worker #.
      • Gl Baking Block Size
    • ALLOC_TEMP_AUDIO_Audio Mixer Thread
      • Audio Worker Block Size
    • ALLOC_TEMP_Job.worker #
      • Job Worker Block Size
    • ALLOC_TEMP_UnityGfxDeviceWorker
      • Gfx Thread Block Size
    There are only few that are less obvious but you can always ask about them if you are not sure.

    Fast Thread Shared Temporary Allocators are only this 4 allocators
    • [ALLOC_TEMP_JOB_1_FRAME]
      • Job Allocator Block Size
    • [ALLOC_TEMP_JOB_2_FRAMES]
      • Job Allocator Block Size
    • [ALLOC_TEMP_JOB_4_FRAMES (JobTemp)]
      • Job Allocator Block Size
    • [ALLOC_TEMP_JOB_ASYNC (Background)]
      • Background Job Allocator Block Size
    Lastly Job Allocator Block Sizes on low memory platforms is used in place of Job Allocator Block Size when device memory is smaller than 2GB.

    We will work on giving more explicit information about it but till then I want to believe that this make it more clear.

    It is correct. If you have high overflow count you may increase this size. Important here, is that this number is accumulation of overflows over whole run. This is important because you can have situation where overflow can happen mostly while loading and not a lot while running game. In such a place your suggestion of having API to dump it at any time would be super useful.

    I understand argument of polluting the profiling and this is fair point. In case of the fallback allocator the issue is a little bit less oblivious. We recommend to not have them because they are slower. But in grand scale of things they are not that slow. What we do, when we cannot allocate memory we just fallback to less specialised allocator. In the game it should not be really noticeable till there is large quantity of them happening in one frame.

    Reasons behind overflow is not always large amount of allocations. In case of Thread Local Storage (TLS) stack allocator very important is the way how we allocate memory. If someone misuse it, it can very fast overflow while holding as little as 1 byte of data. In case of Fast Thread Shared Temporary Allocators there is similar case where just bunch of small allocations which are hold for longer period of time could result in overflow on every allocation. This is of course not always possible to track by Unity users but if you see information about leaks or large amount of overflows it is worth to contact us so we could look and see what happening there.

    Finally recommendation to tweak this value closer to the end of production is just recommendation. In my opinion this is a way to gain a little bit extra boos in product performance. When allocations becoming large performance issue in meantime of production, I would first look for the reasons why we get overflow.

    Of course at the end of the day, this is just a guide. Every production is different and have different requirement. That is why we are giving you generic tool which you can use however you want.
     
  10. chenhaogang_mt

    chenhaogang_mt

    Joined:
    Aug 5, 2019
    Posts:
    3
    CommandLine: -memorysetup-bucket-allocator-granularity=16 -memorysetup-bucket-allocator-bucket-count=64 -memorysetup-bucket-allocator-block-size=4194304 -memorysetup-bucket-allocator-block-count=11 -force-gles30

    command line not valid why?
    03-27 18:11:48.569 6066 6066 D Unity : onActivityResumed: com.mt.Activity@9e57af9

    03-27 18:11:48.569 6066 6066 I Unity : onResume

    03-27 18:11:48.592 6066 6066 I SurfaceView: onWindowVisibilityChanged(0) true android.view.SurfaceView{b3d4e3f VFE...... .F....I. 0,0-0,0 #7f0901f5 app:id/unitySurfaceView} of ViewRootImpl@6e39af3[JumpActivity]

    03-27 18:11:48.661 6066 6066 I SurfaceView: windowStopped(false) true android.view.SurfaceView{b3d4e3f VFE...... .F....ID 0,0-2190,1080 #7f0901f5 app:id/unitySurfaceView} of ViewRootImpl@6e39af3[JumpActivity]

    03-27 18:11:48.666 6066 6066 I SurfaceView: surfaceCreated 1 #8 android.view.SurfaceView{b3d4e3f VFE...... .F....ID 0,0-2190,1080 #7f0901f5 app:id/unitySurfaceView}

    03-27 18:11:48.666 6066 6202 D Unity : SetWindow 0 0xb40000714f24a540

    03-27 18:11:48.666 6066 6066 I SurfaceView: surfaceChanged (2190,1080) 1 #8 android.view.SurfaceView{b3d4e3f VFE...... .F....ID 0,0-2190,1080 #7f0901f5 app:id/unitySurfaceView}

    03-27 18:11:48.666 6066 6202 D Unity : SetWindow 0 0xb40000714f24a540

    03-27 18:11:48.714 6066 6066 I Unity : windowFocusChanged: true

    03-27 18:11:48.725 6066 6202 I Unity : MemoryManager: Using 'Dynamic Heap' Allocator.

    03-27 18:11:48.725 6066 6202 D Unity : [UnityMemory] Configuration Parameters - Can be set up in boot.config

    03-27 18:11:48.725 6066 6202 D Unity : "memorysetup-bucket-allocator-granularity=16"

    03-27 18:11:48.725 6066 6202 D Unity : "memorysetup-bucket-allocator-bucket-count=8"

    03-27 18:11:48.725 6066 6202 D Unity : "memorysetup-bucket-allocator-block-size=4194304"

    03-27 18:11:48.725 6066 6202 D Unity : "memorysetup-bucket-allocator-block-count=1"
     
  11. chenhaogang_mt

    chenhaogang_mt

    Joined:
    Aug 5, 2019
    Posts:
    3
    command line not valid why?