如何在简单的应用程序上调试大量内存问题

时间:2019-03-05 16:38:08

标签: ios xcode memory-leaks xcode-instruments memory-graph-debugger

我的应用程序中遇到内存问题,但是我还没有找到一种方法来找出哪些对象/类正在使用该内存。

该应用程序很简单,它是一个具有图像画廊视图的视图控制器(网格视图类似于Instagram Explore;带有xib单元的集合视图),当您点击其中一个时,它将带您进入下一个屏幕,即同一组图片,但作为垂直列表(带有xib单元的uitableview)。图片是从Web异步下载的。

当我在两个屏幕中滚动时,应用程序使用的内存在不断增加,并且每次打开列表屏幕时,它的存储速度都在增加。然后,唯一减少内存使用的时间(我的意思是,从1.8GB急剧减少到200MB)是它达到设备的极限,然后问题又一次出现。另外,有时,系统无法减少使用的内存,导致应用程序崩溃(“由于内存问题而终止了iOS应用程序”)。

我不认为这是布局问题,我已经检查了所有问题,还使用了内存图调试器,仅发现了“ malloc”问题,这使我无处不在,无类,无行,一无所有。而且,Instruments工具太复杂了,我还不知道如何处理它。

我已经阅读了一些教程并尝试了一些解决方案,但没有任何效果。其中包括:https://krakendev.io/blog/weak-and-unowned-references-in-swifthttp://iosbrain.com/blog/2018/07/22/finding-memory-leaks-with-the-xcode-memory-graph-debugger-and-fixing-leaks-with-unowned/https://www.youtube.com/watch?v=1LnipXiSrSM&t=1697shttps://developer.apple.com/videos/play/wwdc2018/416/

有人可以给我一些其他建议或教程,以了解如何正确调试内存问题以找到其确切来源吗?

1 个答案:

答案 0 :(得分:2)

大多数现代内存调试策略都适用于识别和解决强大的参考周期。但这不是您的问题。当您面临内存压力时,大多数内存都会恢复,这一事实表明存在缓存问题。无论您做任何进一步的诊断,都只能确认此行为。

要解决此问题,请为您的缓存设置合理的限制,并避免使用那些无法控制您的缓存(例如UIImage(named:)),这样就可以解决问题。我们无法进一步评论,而无需查看图像的检索方式(例如,确保URLSession的缓存是合理的)以及下载后如何对其进行缓存(例如,第三方异步图像检索库通常可让您控制缓存)。

并且,假设您(或您的第三方库)正在缓存,请确保:

  • 在模拟器上测试您的应用,手动选择“调试”»“模拟内存警告”。这将有助于确认应用程序是否响应内存压力。根据您的描述,我认为我们已经知道了这种情况,但这是很好的诊断方法。

    请注意,尽管我们始终希望确保我们的应用程序能够正确响应内存警告,但是当您遇到内存警告时,可能已经来不及了(例如,该应用程序可能正在执行一系列分配操作,并且可能在您的应用程序执行之前失败有机会对警告做出反应)。您想在内存警告发生之前尽一切可能来管理缓存。

  • 您要缓存原始有效负载(包含压缩的jpg / png资产的Data对象),而不是UIImage对象(一旦使用,它们将被解压缩并缓存)如果您不小心可能会很大),或者

  • 如果您确实缓存了UIImage对象,请确保将其调整为适合您的UI的大小。

    例如,以3x比例缩放的100x100图像将占用120kb,但是即使图像为1000x1000px,即使图像视图仅为100x100pt,无论压缩的jpg大小如何,未压缩的图像也将占用4mb,即每像素4个字节。 / png有效载荷。

  • 如果您使用的是NSCache,请设置countLimittotalCostLimit

  • 如果要对下载的图像进行自己的收集(数组或字典),请确保您对内存压力做出了响应。例如,在Swift中:

    NotificationCenter.default.addObserver(forName: UIApplication.didReceiveMemoryWarningNotification, object: nil, queue: .main) { [weak self] _ in
        // do whatever you need to remove your cached objects here
    }
    

    我不认为这是问题所在(因为您的应用正在响应内存压力),但是您可能要检查您的应用中是否有(a)大的其他内容; (b)您正在自己下载并保存在内存中,并做出相应的响应。

FWIW,我认为您已经进行了足够的诊断以找出问题的根源(在内存压力下将其清除的事实确实指向缓存问题),但是如果您想了解以下内容中的“分配”工具,仪器,请查看这些旧的WWDC视频Fixing memory issuesiOS App Performance: Memory。它们虽然很老,并且只专注于Objective-C,但是如果您想了解Instruments的最新知识,此处概述的技术仍然适用。但是,就像我说的那样,我认为您已经确定了问题。