UsingMemoryProfiler.md 3.8 KB
Newer Older
O
oceanxiao 已提交
1
# 使用ProfilingMemory内存分析
O
oceanxiao 已提交
2 3

## 概述
O
oceanxiao 已提交
4
利用ProfilingMemory,我们可以分析UnityHeap(CPU主内存)的详细分配堆栈与统计数值
O
oceanxiao 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17

## 步骤
1. 导出选项时勾选"Profiling Funcs"与"Profiling Memory"
<img src='../image/memoryprofiler1.png' width="800"/>

2. 在微信开发者工具运行游戏,过程中会自动记录所有内存分配数据

3. 在微信开发者工具中选择gameContext, 并在Console输入命令: GameGlobal.memprofiler.onDump()
<img src='../image/memoryprofiler2.png' width="600"/>

   Unity将自启动监听端口34999等待调试链接,对于WebGL版本会启动websockify.js(用于websocket转发)。
此时,导出的WebGL游戏在浏览器时能自动连接到Unity Profiler。

ocean2o11's avatar
ocean2o11 已提交
18
4. 将位于游戏缓存目录/usr/下的csv内存数据拖拽并导入到sqlite数据库, 推荐使用[DB Browser for SQLite](https://sqlitebrowser.org/)
O
oceanxiao 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
   <img src='../image/memoryprofiler3.png' width="600"/>
   <img src='../image/memoryprofiler4.png' width="400"/>

5. 对表格执行格式化换行
update alloc_used set callback=replace(callback, 'at ', x'0a'


6. 使用常规SQL进行数据分析
<img src='../image/memoryprofiler5.png' width="800"/>

其中:
- callback: 堆栈
- count: 当前存活的分配次数
- size: 当前使用内存
- malloc: 总分配次数
- free: 总释放次数
典型地, 我们可以通过size进行排序分析内存最大占用的堆栈情况

常见的数据分配堆栈特征:

Unity 2021:
```
 所有内存: select sum(size) from alloc_used

ocean2o11's avatar
ocean2o11 已提交
43
 AssetBundle Storage Memory: select sum(size) from alloc_used where callback like "%AssetBundle_LoadFromMemory%" or callback like "%OnFinishReceiveData%" or callback like "%AssetBundleLoadFromStream%"
O
oceanxiao 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58


 AssetBundle Info:  select * from alloc_used where callback like "%get_assetBundle%"

 Lua: select * from alloc_used where callback like "%luaY_parser%" or callback like "%luaH_resize%" or callback like "%luaM_realloc%"

 Shader: select * from alloc_used where callback like "%ShaderLab%"

 IL2CPP runtime: select sum(size) from alloc_used where callback like "%MetadataCache%"

 MipMap: select * from alloc_used where callback like "%Mipmap%"

Other: select * from alloc_used where callback not like "%xxx%" or callback not like "%xxx%"
 ```

O
oceanxiao 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
## 常见问题
### 1. 开启ProflingMemory后非常慢,特别是在有Lua逻辑的情况
- 首先,这是正常情况,因为每次分配内存都会获取堆栈信息导致运行慢
- Lua会存在大量分配行为,会加重这个问题, 因此我们提供了专门的内存分配器忽略Lua内存,具体做法:

1.[simpledlmalloc.c](../tools/simpledlmalloc.c)添加到xLua虚拟机源码目录下参与编译,(和lauxlib.c同一目录)
2. 参考[lauxlib.c](../tools/lauxlib.c),在lua源码目录下的同名文件中增加`simple_dlmalloc`,并修改`LUALIB_API lua_State *luaL_newstate (void)` 为如下所示
   ```C
   #include "simpledlmalloc.c"
    static void *simple_dlmalloc (void *ud, void *ptr, size_t osize, size_t nsize) {
        (void)ud; (void)osize;  /* not used */
        if (nsize == 0) {
            dlfree(ptr);
            return NULL;
        }
        else
            return dlrealloc(ptr, nsize);
    }

    // using other_alloc instead of default dlmalloc to avoid print trace of lua
    LUALIB_API lua_State *luaL_newstate (void) {
        // lua_State *L = lua_newstate(l_alloc, NULL);
        lua_State *L = lua_newstate(simple_dlmalloc, NULL);
        if (L) lua_atpanic(L, &panic);
        return L;
    }
   ```

### 2. ProfilingMemory在真机上更容易出现内存崩溃
- ProfilingMemory功能需要额外的内存记录堆栈与相关统计,因此JS侧内存压力会更大
- 不建议在真机上使用该功能,只需要在微信开发者工具上进行分析即可,UnityHeap(CPU主内存)在不同端上的行为基本是一致的
 
O
oceanxiao 已提交
91