Search Unity

Tips and Tricks : Make sure to profile your phone app's memory usage!

Discussion in 'Windows' started by Meltdown, Sep 30, 2013.

  1. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    The lower end memory WP8 devices, such as the Lumia 520, Lumia 620, Huawei W1 101 etc only have 180MB of TOTAL memory available before your game will crash.

    I'd highly suggest running the profiler against your WP8 device and making sure total memory never gets anywhere near 180MB.

    Take a look at the attached image. The vertical white line shows the point at which our app crashed. There is a small memory spike of 68.2 MB. But remember memory is also used up by other things such as the graphics driver, FMOD and Unity.

    The red rectangle in the image shows the committed limit for the device, and as you can see the committed total for the app is dangerously close to hitting the 180MB mark, which it did in fact, and caused the app to crash.

    For those testing only on high-end devices, please be aware of this fact, and PROFILE YOUR MEMORY USAGE ON LOW END DEVICES, high end devices generally use more memory, so don't try to get it under 180MB on a high mem device, test on a low end device to get accurate readings.

    If you submit your game to the store without profiling on a low mem device, you will submit your app to the store and half your userbase will come back and rate your game poorly due to low memory crashes. If you can't profile on a low memory device, then set your game to only be downloadable by high memory devices, to avoid bad reviews.


    $memory-usage-at-crash.jpg

    To set up your phone for profiling in the Unity editor.. perform the following steps...

    1.) Make sure in Build Settings you set it to 'Development Build'.
    2.) Connect your phone to your Wifi Network, then click on the wifi connection to see your phone's IP address
    3.) Enter the phone's IP address in the profiler, and press the 'Record' button and the profiler will begin profiling on your phone.
    4.) Run your game from Visual Studio, and you will see the profiling will begin.

    * - If you don't see your phone in the profiler, try this alternate method

    1.) Connect the phone to your PC
    2.) Make sure in Build Settings you set it to 'Development Build'.
    3.) Build the game to Visual Studio
    4.) Run the game in 'Debug' mode from Visual Studio
    5.) When the game is running on the device and is past any loading screens, click on the 'Active Profiler' dropdown in the profiler, and the device should be listed there.

    IMPORTANT : DO NOT profile memory on your PC or Mac, the profiling must be done on the device to get accurate usage.

    So how can you reduce your game's memory footprint?

    Reduce your audio memory usage

    One of the easiest ways is to modify the way your audio loads...
    If you look in the attached image, FMOD uses 37MB of memory. Unity uses FMOD as it's low level audio engine.
    Some of the biggest memory gains you can make are by changing your audio file import settings to 'Stream from disc' instead of 'Load into memory'.

    Note this can slightly decrease performance. So for large audio files such as background songs etc.. use this option, and if you need the extra performance, load your sound effects into memory.

    Compress your textures to DXT1 or DXT5

    The second most important thing you can do in a project to reduce your memory footprint is to compress your textures. DXT is a lossy texture compression algorithm, meaning you lose some quality.

    DXT1 can compress your texture sizes up to 8x, and supports a 1-bit alpha channel (i.e 0 or 1), meaning you shouldn't use DXT1 compression for textures that you require to be semi-transparent.

    DXT5 can compress your texture sizes up to 4x, and fully supports alpha.

    In most cases you will just set everything to DXT5, but if you need to squeeze out the extra performance, DXT1 can get you some small gains.
     
    Last edited: Jun 14, 2015
  2. tswalk

    tswalk

    Joined:
    Jul 27, 2013
    Posts:
    1,106
  3. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    Useful link. Thanks. Good to know there are options to opt-out your app from low memory device installs.
     
  4. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    793
    Very helpful post, thanks. Is the memory available always the same regardless of how many apps the user has opened?

    And do you know if the same behaviour apply to all mobile platforms?
     
  5. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    Yes, the memory limit is allocated on a per app basis.

    On 512Mb phone, you are limited to 180Mb per app.
    On 1GB phones, you are limited to 380Mb per app.
    On 2GB phones, you are limited to 570Mb per app.

    No, each platform has its own specific memory implementations.
     
    Last edited: May 28, 2014
  6. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Any other tips on reducing the memory footprint? I'm trying to get my game to work on 512MB devices at the moment. Apparently my game works well on a Lumia 630 with the Cyan update but not on other 512MB devices.

    One question, is there a way to detect the device's memory within a #if statement within Unity? Does it make sense to use quality settings that compress the textures and set the quality settings to a low value if the device is a low memory device?
     
  7. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Quick question, where can I set the compression values of textures to DXT1? I looked at the inspector window for the texture and it only has Compressed, 16 bit colour and True color?
     
  8. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    1,989
    You have to switch Texture Type to Advanced
     
  9. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Hmmm ... I still don't see that option even when I switch to advanced. Is it one of the drop down lists or somewhere else in the editor?
     
  10. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Does anyone know of a quick way to change all audio clips to stream from disc? Multi item editing isn't available on audioclips in the inspector so I can't just select them all and make the change once and have it apply to them all.
     
  11. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    Write an editor script using the AssetPostProcessor and AudioImporter
     
    Rajmahal likes this.
  12. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Cool ... thanks. Actually, it looks like one of the assets I purchased a while back has that functionality.

    I used your tips to get my first game working on low memory devices. Now struggling to do the same with my next project. Going to try streaming all audio clips (including SFX) from the disc.
     
  13. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    104
    Use this to set all properties on the selected audio clips:

    Code (csharp):
    1.  
    2. using UnityEditor;
    3. using UnityEngine;
    4. public class SetAudioSettings : EditorWindow
    5. {
    6.  
    7.     private AudioImporterFormat format;
    8.     bool threeD, mono, hardware, gapless;
    9.     private AudioImporterLoadType loadType;
    10.     private int compression = 196;
    11.  
    12.     [MenuItem("Tools/Bulk Audio Settings")]
    13.     private static void Init()
    14.     {
    15.         GetWindow(typeof(SetAudioSettings));
    16.     }
    17.     void OnGUI()
    18.     {
    19.         format = (AudioImporterFormat)EditorGUILayout.EnumPopup("Audio Format", format);
    20.         threeD = EditorGUILayout.Toggle("3D sound", threeD);
    21.         mono = EditorGUILayout.Toggle("Force to mono", mono);
    22.         loadType = (AudioImporterLoadType)EditorGUILayout.EnumPopup("Load Type", loadType);
    23.         hardware = EditorGUILayout.Toggle("Hardware decoding", hardware);
    24.         gapless = EditorGUILayout.Toggle("Gapless Looping", gapless);
    25.         compression = EditorGUILayout.IntSlider("Compression (kbps)", compression, 0, 256);
    26.  
    27.         if (GUILayout.Button("Set Settings"))
    28.         {
    29.             foreach (Object o in Selection.GetFiltered(typeof(AudioClip), SelectionMode.DeepAssets))
    30.             {
    31.                 string path = AssetDatabase.GetAssetPath(o);
    32.                 AudioImporter audioImporter = AssetImporter.GetAtPath(path) as AudioImporter;
    33.                 audioImporter.format = format;
    34.                 audioImporter.threeD = threeD;
    35.                 audioImporter.forceToMono = mono;
    36.                 audioImporter.loadType = loadType;
    37.                 audioImporter.hardware = hardware;
    38.                 audioImporter.compressionBitrate = compression * 1000;
    39.                 AssetDatabase.ImportAsset(path);
    40.             }
    41.         }
    42.     }
    43. }
    44.  
    45.  
    I didn't write this, but I can't recall who the author was
     
    TooManySugar and Rajmahal like this.
  14. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Thanks ... I managed to do it with the master audio asset.

    I'm still struggling though on reducing memory usage. Are there any other tips you guys have found? So far, I've tried:

    1 - Reducing polygon size of 3d Meshes
    2 - Making audio stream from disk
    3 - Compress textures heavily for Windows Phone

    Anything else?
     
  15. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    I'd suggest running the profiler and seeing what is causing the spikes.
    You can also divide the texture max size by 2. Although you can get away with it on some textures, and not on others.

    I'd suggest writing a script that uses the AssetPostProcessor that sets maxsize = maxsize / 2.
    Then run game and see if it helps. If so, you'll need to do it on some textures and not others.
     
  16. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Thanks ... the profiler is definitely helpful. What's odd though is that I have audio files compressed and set to stream from disk but when I run the game on my device with the profiler, it seems to load the file into memory and it's occupying the full, uncompressed amount. Does Unity stream from disk only if memory is unavailable and load it into memory if it has memory free to do so?
     
  17. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    No, it will stream from disk if you set it to. It won't load from memory.
    I'd suggest re-importing your audio assets. They shouldn't be loaded into memory. Just right-click on them and choose Re-import.
     
  18. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Thanks ... that does seem to have made a difference.

    On another note, I have quality settings in Unity set to divide textures by half or a quarter of original size. However, I don't want the texture for my GUI (using NGUI) to be affected by this as it makes text blurry. Is there some way I can exclude a particular texture from being affected by the quality setting?
     
  19. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    Don't set in quality settings. Set using a script per texture. Max Texture size.
     
  20. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Cool ... thanks
     
  21. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Sorry ... another quick question, the best place to put such a script would be on the material that the texture is on?
     
  22. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    No, its an editor script. So use AssetPreProcessor like I mentioned previously. Then when you right-click, and say re-import, it sets the texture max size. So if you wanted to set a whole bunch of textures to half their size, in the AssetPreProcessor just set maxsize = maxsize / 2;

    You could do it manually by clicking on the texture in the 'Project' pane, look at it's import settings. Under Max texture size if it was 1024, You could then set it's max texture size to 512, and click apply.
     
  23. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Okay, I'm not too familiar with the AssetPreProcessor component of Unity so I think i'll need to read up on that.
     
  24. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
  25. Rajmahal

    Rajmahal

    Joined:
    Apr 20, 2011
    Posts:
    2,051
    Thanks, I'll go through it.
     
  26. Murthy_Dumadu

    Murthy_Dumadu

    Joined:
    May 17, 2013
    Posts:
    33
    Hi, Consider the following as if need to hide or remove some part for low end mobiles (512 RAM ) and make sure the functionality available in high end mobile (1GB, 2 GB....etc) Check the Device RAM as one factor :
    DataHandler.cs
    private static float mfDeviceRAMSize=0.0f;
    public static float getDeviceRAMSize //ReadOnly
    {
    get
    {
    if(RAMSize<=0.0f)
    RAMSize=SystemInfo.systemMemorySize; //will get you the RAM size in MB

    return RAMSize;
    }
    }
    in Our Game Code
    if(DataHandler.getDeviceRAMSize<=512)
    {
    // Low end Device
    }
    else
    {
    // High end Device
    }

    is this Right way? @Meltdown
     
  27. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    @Murthy_Dumadu Yes you can use that for now. Unity 5 will have some extended API methods you can use to determine if the device is high or low memory.
     
  28. yoyo

    yoyo

    Joined:
    Apr 16, 2010
    Posts:
    112
    Note that any audio clip referenced from a scene will be loaded into memory with that scene, and any audio clip in the Resources folder will also be loaded into memory. This is true at least in the editor, and it doesn't matter whether or not the clip is set to "Streamed from disc." (At least that's what I'm seeing while trying to alleviate memory pressure in our editor environment.)
     
  29. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    True perhaps in the editor, certainly not true in the player.
     
  30. DickFeynman

    DickFeynman

    Joined:
    Jul 17, 2015
    Posts:
    16
    Hi @Meltdown,
    can you mention these API methods you are referring in this comment?
    Thank you
     
  31. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    I've been out of the Windows Phone/Windows 8 porting for a while now, sorry. I'm not sure what they are, or if they have been implemented as of yet.