10

我有一个信息亭应用程序,它基本上显示了一堆幻灯片,上面有各种信息。一年多前,我最初开始编写此代码,当时我开始使用 Objective-C 和 iOS 开发。我发现我现在的代码风格比以前干净得多,而且我更有经验,所以我决定从头开始重写。

我使用 Allocations 工具运行我的应用程序以查看内存使用情况。考虑到这是一个信息亭应用程序,一切都需要顺利运行,没有泄漏。(当然,所有应用程序都需要在没有泄漏的情况下运行,但信息亭应用程序使这一目标变得更加重要。)我看到了一些有趣的结果,所以我也运行了旧版本的代码。

运行旧版本的代码,我看到几乎甚至运行在大约 1.15 兆字节的内存使用量。一切似乎都在必要时被分配和释放。然而,在我的新实现中,我看到了一些不同的东西。内存使用量在很小的“高原”中不断跳跃,然后最终似乎达到了大约 1.47 兆字节的使用量峰值。以下是运行 10 多个小时后新的分配报告的样子:

在此处输入图像描述

我担心有几个原因。

  1. 运行开始时的奇数模式。
  2. 分配似乎达到了 1.47 兆字节的峰值,但在一夜之间运行它表明它实际上会随着时间的推移慢慢地使用越来越多的内存。这不可能是一件好事。

旧项目和新项目之间有几个显着差异。

  • 旧项目使用 Plists 作为后备存储(我手动读取和写入 plist 文件。)新项目使用 Core Data。

  • 新项目实现了一个在旧项目没有的每个“幻灯片”上调用的库。我会更关心这个库,除了我写了它并且我检查了它以确保我发布了所有东西,并且只在手动发布不可能的地方自动发布。

  • 这两个类都使用工厂类来创建幻灯片。在旧项目中,工厂类是一个单例。我认为把它变成一个普通的类将有助于解决内存问题,因为单例从未被释放。(因此它的 属性没有被释放。在新项目中,工厂类正在被释放,所以我不确定为什么它仍然占用所有内存(如果这是导致问题的原因。

  • 旧项目在各个地方都使用了字符串常量。新代码对同一件事使用了大量的枚举。(新代码通常使用更多常量。)

我可以做些什么来追踪内存峰值?当应用程序丢弃它正在使用的任何东西时,内存都被应用程序清理了,但它似乎在应用程序终止之前并没有丢弃东西。

如果有人能帮助我指出正确的方向,我将不胜感激。

编辑:

看起来峰值是由对 KosherCocoa 库的调用引起。如果有人介意看一下它并告诉我在内存管理方面我做错了什么,我将非常感激。

4

1 回答 1

5

我可以做些什么来追踪内存峰值?当应用程序丢弃它正在使用的任何东西时,内存都被应用程序清理了,但它似乎并没有丢弃东西。

这是“废弃对象”或“使用积累”的经典案例。也就是说,您有一个应用程序,它在运行时会在内存中构建一个对象图,作为正常使用的一部分。对象没有泄漏,因为它们仍然连接到活动对象图。这些对象很可能是某种缓存(最常见的是只写缓存)或涉及历史状态的机制的一部分(撤消堆栈是增加的潜在来源)。

要修复它,您需要确保在您的应用程序运行时适当地修剪您的对象图。缓存通常应使用最近最少使用的 [LRU] 修剪算法来限制缓存大小。如果缓存键失效,该数据也应该被修剪。

对于历史信息,修剪历史至关重要。确保历史数据包含该历史状态的绝对最小表示也是如此。

使用 Heapshot 分析——它的创建是为了帮助准确追踪这类问题。

我写了一份详细的“如何做”指南; 什么时候泄漏不是泄漏?

于 2011-08-01T14:46:21.750 回答