首页 > 解决方案 > 如何在一个简单的应用程序上调试大量内存问题

问题描述

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

该应用程序很简单,一个带有图像画廊视图的视图控制器(网格视图就像 Instagram 探索;带有 xib 单元格的集合视图),当您点击一个时,它会将您带到下一个屏幕,这是同一组图像,但作为一个垂直列表(带有xib单元的uitableview)。图像是从网络异步下载的。

当我在两个屏幕中滚动时,应用程序使用的内存不断增加,每次打开列表屏幕时也会更快。然后,使用的内存减少的唯一时刻(我的意思是从 1.8GB 大幅减少到 200MB)是它达到设备的限制,然后问题一次又一次地出现。此外,有时,系统无法减少使用的内存并且应用程序崩溃(“由于内存问题而终止的 iOS 应用程序”)。

我不认为这是布局问题,我已经检查了所有这些,还使用了内存图调试器,并且只发现了“malloc”问题,这让我无处可去,没有课程,没有行,什么都没有。另外, Instruments 工具太复杂了,我还不知道如何处理它。

我已经阅读了一些教程并尝试了一些解决方案,但没有任何效果。包括:https ://krakendev.io/blog/weak-and-unowned-references-in-swift , http://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=1697s , https://developer.apple.com/videos /播放/wwdc2018/416/

有人可以给我一些其他建议或教程,说明如何正确调试内存问题以找出它们的确切来源吗?

标签: iosxcodememory-leaksxcode-instrumentsmemory-graph-debugger

解决方案


大多数当代内存调试策略都适用于识别和解决强引用循环。但这不是你的问题。当您面临内存压力时,大部分内存都会被恢复,这一事实表明存在缓存问题。无论您做什么进一步的诊断,都只会确认这种行为。

要解决这个问题,请为您的缓存设置合理的限制,并避免不给您控制的缓存(例如UIImage(named:)),问题可能会得到解决。如果不了解图像是如何被检索的(例如确保缓存URLSession是合理的)以及它们在下载后如何被缓存(例如第三方异步图像检索库通常让您控制缓存),我们无法进一步评论。

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

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

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

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

  • 如果您确实缓存了UIImage对象,请确保根据您的 UI 调整它们的大小。

    例如 100x100 的 3x 比例的图像将占用 120kb,但如果图像是 1000x1000px,即使图像视图只有 100x100pt,未压缩的图像也将占用 4mb,即每像素 4 字节,无论压缩的 jpg/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,我认为你已经做了足够的诊断来确定问题的根源(它在内存压力下被清除的事实确实指向缓存问题),但是如果你想学习 Instruments 中的“分配”工具,检查出这些旧的 WWDC 视频修复内存问题iOS 应用程序性能:内存。它们很老,专注于 Objective-C,但如果你想加快 Instruments 的速度,那里列出的技术仍然适用。但是,就像我说的,我认为您已经确定了问题所在。


推荐阅读