赞
踩
很多童鞋在进行内存分析的时候都会遇到下面的问题:
ManagedHeap.UsedSize和ManagedHeap.reservedUnUsedSize这两个占用了很大内存,即使手动GC.Collect之后,ManagedHeap.UsedSize和ManagedHeap.reservedUnUsedSize两者的综合仍然没有发生变化,内存占用依然没有缓解。
在分析内存时,也发现了相同的问题。之前的数据表是用Json格式存储的,数据表比较大将近30M,当读取到内存的时候出现了上面的情况。
这是为什么呢?首先,我们要了解几个概念:
当我们申请内存时,如果ManagedHeap.reservedUnUsedSize的内存不够用,Mono会向os申请内存。并且这个内存会扩大ManagedHeap的大小,并且这个内存不会回落。
我们可以通过Profiler.GetMonoHeapSize()获取Mono堆上的总内存和mono_gc_get_heap_size是一个意思。
下面写了一个测试用例:
- using UnityEngine;
- using System;
- using System.Runtime.InteropServices;
- using System.Text;
-
- public class TestManagedHeap : MonoBehaviour
- {
- public int arraysize = 1024 * 1024 * 200;//条件触发延迟申请的内存1
- public int arraysize_frame = 1024 * 1024 * 10;//条件触发延迟申请的内存2
-
- [DllImport("mono.dll")]
- public static extern long mono_gc_get_used_size();
- [DllImport("mono.dll")]
- public static extern long mono_gc_get_heap_size();
-
- //private StringBuilder builder = new StringBuilder(256);
- // Use this for initialization
- void Start()
- {
- }
-
- // Update is called once per frame
- void Update()
- {
- if (Input.GetKeyDown(KeyCode.U))
- {
- byte[] array = new byte[arraysize];
- array = null;
- Debug.Log("申请200M");
- printMemory();
- }
- if (Input.GetKeyDown(KeyCode.A))
- {
- byte[] array = new byte[arraysize_frame];
- Debug.Log("申请10M");
- printMemory();
- }
- if (Input.GetKeyDown(KeyCode.B))
- {
- Debug.Log("调用GC");
- GC.GetTotalMemory(true);
- printMemory();
- }
- }
-
- void printMemory()
- {
- long usedsize = mono_gc_get_used_size();
- long heapsize = mono_gc_get_heap_size();
- long reservedsize = heapsize - usedsize;
- builder.Length = 0;
- //builder.AppendFormat("使用内存:{0},剩余内存{1},托管堆内存{2}",usedsize,reservedsize,heapsize);
- //print(builder.ToString());
- Debug.Log("使用内存=" + usedsize * 1.0f / 1024 / 1024 + "M");
- Debug.Log("剩余内存=" + reservedsize * 1.0f / 1024 / 1024 + "M");
- Debug.Log("托管堆内存=" + heapsize * 1.0f / 1024 / 1024 + "M");
- }
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开发时需要注意什么呢?
原文地址:http://www.showxyz.com/?p=96
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。