性能优化01:内存泄漏检测

张建 lol

Leaks

先看看 Leaks,从苹果的开发者文档里可以看到,一个 app 的内存分三类:

  • Leaked memory: Memory unreferenced by your application that cannot be used again or freed (also detectable by using the Leaks instrument).

真正的内存泄漏:在第一次 pop 的时候报 Memory Leak,在之后的重复 pushpop 同一个 ViewController 过程中,不报 Object Deallocated,但每次 pop 之后又报 Memory Leak。这种情况下每回进入并退出一个页面后,就报有新的内存泄漏,同时被报泄漏的对象又从来没有释放过,可以确定是真正的内存泄漏。

  • Abandoned memory: Memory still referenced by your application that has no useful purpose.

释放不及时:在第一次 pop 的时候报 Memory Leak,在之后的重复 pushpop 同一个 ViewController 过程中,对于同一个类不断地报 Object DeallocatedMemory Leak。这种情况属于释放不及时的情况。

  • Cached memory: Memory still referenced by your application that might be used again for better performance.

单例 或者被 cache 起来复用:在第一次 pop 的时候报 Memory Leak,在之后的重复 pushpop 同一个 ViewController 过程中,即不报 Object Deallocated,也不报 Memory Leak。这种情况下我们可以确定该对象被设计成单例或者 cache 起来了。

总结:
其中 Leaked memoryAbandoned memory 都属于 应该释放而没释放的内存,都是内存泄露,而 Leaks 工具只负责检测 Leaked memory,而不管 Abandoned memory。在 MRC 时代 Leaked memory 很常见,因为很容易忘了调用 release,但在 ARC 时代更常见的内存泄露是 循环引用 导致的 Abandoned memoryLeaks 工具查不出这类内存泄露,应用有限。

Allocations

  • 对于 Abandoned memory,可以用 InstrumentAllocations 检测出来。检测方法是用 Mark Generation 的方式,当你每次点击 Mark Generation 时,Allocations 会生成当前 App 的内存快照,而且 Allocations 会记录从上回内存快照到这次内存快照这个时间段内,新分配的内存信息。举一个最简单的例子:

  • 我们可以不断重复 pushpop 同一个 UIViewController,理论上来说,push 之前跟 pop 之后,app 会回到相同的状态。因此,在 push 过程中新分配的内存,在 pop 之后应该被 dealloc 掉,除了前几次 push 可能有预热数据和 cache 数据的情况。如果在数次 pushpop 之后,内存还不断增长,则有内存泄露。因此,我们在每回 push 之前跟 pop 之后,都 Mark Generation 一下,以此观察内存是不是无限制增长。

  • 用这种方法来发现内存泄露还是很不方便的:

    • 首先,你得打开 Allocations
    • 其次,你得一个个场景去重复的操作
    • 无法及时得知泄露,得专门做一遍上述操作,十分繁琐
  • Post title:性能优化01:内存泄漏检测
  • Post author:张建
  • Create time:2023-03-02 23:32:21
  • Post link:https://redefine.ohevan.com/2023/03/02/OC性能优化/性能优化01:内存泄漏/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
On this page
性能优化01:内存泄漏检测