egret_内存分析-泄漏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangxuan0261/article/details/81260498

查找 js 的内存泄漏, 这并不是真正的泄漏, 只是我们不需要了但还是一直被引用住了. 不想 c/c++ 那样 alloc 了一块内存并用指针指向它, 切断了这个指针就无法找到这块内存, 这才是真正的泄漏.


快照

!!! 打快照的要清空控制台 !!!

打快照前, 会自动执行gc.

控制台中打印一些对象时, 会导致引用住对象, 快照数据中会存在此对象的数据, 会 误认为泄漏, 以此, 打快照时最好清一下控制台信息, 以保证快照信息的准确性.

console.log(Object) 也会引用对象, 在 Chrome 中调试工具中 会出现 DevTools 字样.

实际操作

打两个快照, 比如打开 n个ui 前, 打一个快照 s1, 打开 n个ui并关闭 后, 再大一个快照 s3, 使用快照 s3 对比 s1, 搜索对应ui 类名看是否存在, 如果存在则说明泄漏了

查找引用链

1 是 泄漏的类, 展开后是 泄漏的实例对象a , 后面有个 @2886161 是实例的唯一id

2 是这个实例对象a 被那些字段引用住了. 这里我用一个全局变量 gRef1 故意引用住了

扫描二维码关注公众号,回复: 2960288 查看本文章

ps: 按顺序查找, 后面的引用可能是 前面的引用造成的, 所以优先前面的引用, 如 gRef1. 解决完后 重新测一下, 后面的引用可能就不存在了.

回调函数引发的泄漏

比如使用观察者模式, 有个事件中心, 对象a 去事件中心注册了 事件b, 但是忘了反注册 事件b, 就会造成 对象a 一直被事件中心 给引用住.

回调泄漏也是容易查找的, 引用链中可以看到回调的一些参数, 很容易定位 问题代码在哪里.

可以看到被一个回调引用住了, 并且这个回调函数有个参数 event, 还可以跳转到对应的 js 查看具体的函数名

gEventCenter.on(Events.RefreshBagUI, this.onRefreshBagUI, this);
// gEventCenter.off(Events.RefreshBagUI, this.onRefreshBagUI, this); // 这里我是故意注释掉反注册

弱引用

es6 标准中提供了一个 弱引用表 WeakMap, key是需要检测的对象, value: any. 重复的实例对象 set 进去, 只会保留最后一个. 奇怪的是这个表 可以直接通过 Chrome 控制太打印, 但是没有提供运行时遍历表的方法, 所以无法写工具 实时显示检测对象, 必须手动控制台打印该表对象.

实际使用

一定要在浏览器上执行几遍 gc, 弱引用表内的数据才真实有效

导出内存数据, 防止内存堆积导致卡顿问题.
仅仅适用于web上浏览器打开操作. 都使用 Chrome 浏览器跑吧


玩游戏时, 时不时执行以下操作, 导出数据.
游戏时长越久, 数据越好. (能所有 UI 跑两边以上遍 及 跳多几次场景 是最好的)

  1. F12 打开调试栏. 点三次 垃圾桶 (这一步很重要, 执行 gc操作)

  2. 输入指令. DebugMgr.instance._objMap , 然后按 回车

    展开所有小箭头, 复制所有数据 (复制到最底下就对了)

  3. 将 复制结果 丢到一个 新建文件. 每次导出顺序递增命名. 如 (1.txt, 2.txt, 3.txt … 等等), 打包发给 客户端

动图操作

猜你喜欢

转载自blog.csdn.net/yangxuan0261/article/details/81260498
今日推荐