Unity内存优化 之 ManagedHeap 整理

 

要了解几个概念:

  • ManagedHeap 表示的是Mono所使用的托管堆内存,C#上任何的申请托管的内存都会在这个上面申请。
  • ManagedHeap.UsedSize 表示这个托管堆上已经使用的内存大小
  • ManagedHeap.reservedUnUsedSize 表示托管堆上未使用的内存大小

当我们申请内存时,如果ManagedHeap.reservedUnUsedSize的内存不够用,Mono会向os申请内存。并且这个内存会扩大ManagedHeap的大小,并且这个内存不会回落。

我们可以通过Profiler.GetMonoHeapSize()获取Mono堆上的总内存和mono_gc_get_heap_size是一个意思。

下面写了一个测试用例:

 

 
  1. using UnityEngine;

  2. using System;

  3. using System.Runtime.InteropServices;

  4. using System.Text;

  5.  
  6. public class TestManagedHeap : MonoBehaviour

  7. {

  8. public int arraysize = 1024 * 1024 * 200;//条件触发延迟申请的内存1

  9. public int arraysize_frame = 1024 * 1024 * 10;//条件触发延迟申请的内存2

  10.  
  11. [DllImport("mono.dll")]

  12. public static extern long mono_gc_get_used_size();

  13. [DllImport("mono.dll")]

  14. public static extern long mono_gc_get_heap_size();

  15.  
  16. //private StringBuilder builder = new StringBuilder(256);

  17. // Use this for initialization

  18. void Start()

  19. {

  20. }

  21.  
  22. // Update is called once per frame

  23. void Update()

  24. {

  25. if (Input.GetKeyDown(KeyCode.U))

  26. {

  27. byte[] array = new byte[arraysize];

  28. array = null;

  29. Debug.Log("申请200M");

  30. printMemory();

  31. }

  32. if (Input.GetKeyDown(KeyCode.A))

  33. {

  34. byte[] array = new byte[arraysize_frame];

  35. Debug.Log("申请10M");

  36. printMemory();

  37. }

  38. if (Input.GetKeyDown(KeyCode.B))

  39. {

  40. Debug.Log("调用GC");

  41. GC.GetTotalMemory(true);

  42. printMemory();

  43. }

  44. }

  45.  
  46. void printMemory()

  47. {

  48. long usedsize = mono_gc_get_used_size();

  49. long heapsize = mono_gc_get_heap_size();

  50. long reservedsize = heapsize - usedsize;

  51. builder.Length = 0;

  52. //builder.AppendFormat("使用内存:{0},剩余内存{1},托管堆内存{2}",usedsize,reservedsize,heapsize);

  53. //print(builder.ToString());

  54.     Debug.Log("使用内存=" + usedsize * 1.0f / 1024 / 1024 + "M");

  55.    Debug.Log("剩余内存=" + reservedsize * 1.0f / 1024 / 1024 + "M");

  56.     Debug.Log("托管堆内存=" + heapsize * 1.0f / 1024 / 1024 + "M");

  57.  }

 


在测试中会发现,当申请了200M的内存后,再申请10M的内存。堆上的内存mono_gc_get_heap_size并没有减少,这是因为,在Mono堆上的内存在应用程序运行期间是只增不减的,即使GC也不会把申请的内存还给os,而是设置成了未使用状态。

Memory is allocated in heap blocks. More can allocated if it cannot fit the data into the allocated block. Heap blocks will be kept in Mono until the app is closed. In other words, Mono does not release any memory used to the OS (Unity 3.x). Once you allocate a certain amount of memory, it is reserved for mono and not available for the OS. Even when you release it, it will become available internally for Mono only and not for the OS. The heap memory value in the Profiler will only increase, never decrease.

 上面是摘自Unity官方API对Profiling对Mono Memory的解释。

鉴于这个原因,在app开发时需要注意什么呢?

  1. 不要一次性申请过大的内存;
  2. 切换场景等操作时可以自己手动调用GC.Collect

///

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值