这里的问题是您“忙于等待” adaptor.assetWriterInput.readyForMoreMediaData
,即在一个紧密的循环中一遍又一遍地调用它。一般来说,这是不好的做法。标头声明此属性是 Key-Value Observable,因此您最好重组代码以侦听 Key-Value 更改通知,以推进整个过程。更糟糕的是,根据AVAssetInputWriter
工作方式(我不确定它是否基于运行循环),这里的忙等待行为实际上可能会阻止资产输入编写器进行任何实际工作,因为运行循环可能有效死锁等待可能不会发生的工作,直到您让运行循环继续。
现在你可能会问自己:忙等待是如何造成内存压力的?它会导致内存压力,因为在幕后,readyForMoreMediaData
每次调用它时都会分配自动释放的对象。因为你忙着等待这个值,在一个紧密的循环中一遍又一遍地检查它,它只会分配越来越多的对象,它们永远不会被释放,因为运行循环永远没有机会为你弹出自动释放池。(有关分配真正用途的更多详细信息,请参见下文)如果您想继续这种(不明智的)忙碌等待,您可以通过执行以下操作来缓解内存问题:
BOOL ready = NO;
do {
@autoreleasepool {
ready = adaptor.assetWriterInput.readyForMoreMediaData;
}
} while (!ready);
这将导致由创建的任何自动释放对象readyForMoreMediaData
在每次检查后被释放。但实际上,从长远来看,通过重组此代码以避免忙碌等待,您会得到更好的服务。如果您绝对必须忙于等待,至少usleep(500);
在循环的每次通过时都执行类似的操作,这样您就不会过多地破坏 CPU 。但不要忙等。
编辑:我还看到您想了解如何从 Instruments 中解决这个问题。让我试着解释一下。从您发布的文件开始,这就是我所做的:
我单击顶部窗格中的 Allocations 行然后我选择了“Created & Still Living”选项(因为如果这些东西被破坏了,我们就不会看到堆增长。)接下来,我通过 Option- 应用了时间过滤器-在您看到的大“斜坡”中拖动一个小范围。此时,窗口如下所示:
在这里,我看到列表中有大量非常相似的 4K malloc'ed 对象。这是吸烟枪。现在我选择其中一个,然后展开窗口的右窗格以显示堆栈跟踪。此时,窗口如下所示:
在右侧面板中,我们看到了创建该对象的堆栈跟踪,我们看到它被分配AVAssetInputWriter
到-[AVAssetWriterInput isReadForMoreMediaData]
. 在autorelease
回溯中有一个提示,这与自动释放的对象有关,并且像这样处于紧密循环中,标准的自动释放机制永远没有机会运行(即弹出当前池)。
我从这个堆栈中得出的结论是 , 中的某些东西-[AVAssetWriterInput isReadForMoreMediaData]
(可能是_helper
下一个堆栈帧中的函数)[[foo retain] autorelease]
在返回其结果之前执行了 a 。自动释放机制需要跟踪所有被自动释放的东西,直到自动释放池被弹出/耗尽。为了跟踪这些,它需要为其“等待自动释放的事物列表”分配空间。这就是我对为什么这些是 malloc 块而不是自动释放对象的猜测。(即没有分配任何对象,而只是空间来跟踪自池被推送以来发生的所有自动释放操作 - 其中有很多,因为您正在紧密循环中检查此属性。 )
这就是我诊断问题的方式。希望这对您将来有所帮助。