【问题标题】:Reducing memory of UIImages from camera using Instruments使用 Instruments 减少相机中 UIImages 的内存
【发布时间】:2012-02-08 09:11:07
【问题描述】:

我的应用使用 ARC,执行以下操作:

  1. 上传相机拍摄的照片
  2. 压缩图片以用作缩略图。
  3. 我使用 [UIImage imageWithData:UIImageJPEGRepresentation( original, 0.1f )] 进行此操作
  4. 我将未压缩的图片引用设置为 nil,以便 ARC 释放内存

重复此序列将意味着屏幕上出现多个压缩缩略图。大约 7 或 8 张图片后,应用程序将因内存不足而崩溃。

在 Instruments 中,我尝试将分配与内存监视器结合使用来查找问题的根源。

一些仪器统计数据:

分配 - Live Bytes 在拍照后跳跃约 2 MB,但在原始图片参考设置为零后下降 1.5 MB。这似乎是一件好事,但是......

这是应用程序的最终状态。 #Living 相对于 Live Bytes 似乎非常高,对吧?

  Live Bytes  #Living   #Transitory  Overall   #Overall Bytes    
   3.72 MB    24538     80679        90.1 MB   105301

内存监视器(跟踪检查头) - 我的应用程序启动时为 7.5 MB,拍摄一张照片会导致增加约 13 MB。对于我上面列出的状态,内存监视器说应用程序占用了 72.67 MB 的“真实内存”和 123.79 MB 的虚拟内存。

鉴于 Live Bytes 非常小,我知道我在做正确的事情。 但是,鉴于其他地方的内存占用很大,我也确定我做错了什么。任何想法可能是什么,或者如何追踪它?

【问题讨论】:

  • +1 提出一个好问题。您如何加载图像以显示在屏幕上?你在用[UIImage imageNamed:]吗?
  • 这一行的目的是什么? [UIImage imageWithData:UIImageJPEGRepresentation( original, 0.1f )] 您正在压缩图像,然后立即解压缩。结果只是浪费了画质和 CPU 时间。
  • @DominikSeibold 我压缩图像以减少内存,然后将其更改为 UIImage 以便我可以将其用作缩略图按钮的背景。
  • 图像不会以压缩状态存储在内存中,因此将它们重新压缩为 JPEG 并不会真正为您带来任何好处。您可以为图像做的最重要的事情是调整图像大小并将图像裁剪为缩略图,其中的像素不超过显示所需的像素。分配工具hides some memory usage that Memory Monitor shows,包括内存中图像的总大小,因此您不能依赖其实时字节读数来了解这里的真实故事。

标签: ios uiimage uiimagepickercontroller instruments automatic-ref-counting


【解决方案1】:

Eitan27,

这不是 ARC 问题。这是关于如何管理内存中的多个大项目。 iOS 有多种机制可以帮助您。如果您将映像写入闪存,然后将其作为内存映射数据重新打开,您将主要解决您的问题。如何?操作系统使用不可变数据管理映射到您的常驻内存占用。因为这些项目是不可变的,因此永远不会变脏,所以它可以在必要时刷新映射的页面。这种机制的缺点是每个应用程序可用的文件描述符数量有限。

安德鲁

【讨论】:

  • 谢谢adonoho。您的回答听起来不错,尽管您提到了一些我有点不熟悉的事情。为什么文件描述符有限制?通过保存到闪存,您的意思是使用文件名从磁盘写入/检索它吗?还是您或多或少建议我实现类似于 TileView/CATileLayer 的东西。
  • Eitan27,每个应用程序在任何时候都可以打开的文件数量有限。文件描述符是操作系统分配的数据结构。通常,您只有 30 个左右可用。闪存,我的意思是你的持久存储。当您遇到这个空间问题时,我只是假设您在 iOS 上运行。所有 iOS 设备都使用闪存 RAM 作为其持久存储。安德鲁 P.S.别忘了用大大的绿色复选标记奖励回答您问题的人。
  • 当然,是的,我在 iOS 上运行。我不清楚文件描述符限制是针对总文件还是在给定时间打开的文件。似乎是后者,问题将通过使用 CATileLayer 仅在需要时打开/显示图像来解决。
【解决方案2】:

使用@autoreleasepool 块:

@autoreleasepool {
    //code that inits the UIImage and sets it to nil
}

参见Transitioning to ARC Release NotesARC 提供了管理自动释放池的新声明部分

【讨论】:

  • 我不确定这是否适用于我。图像被分配,然后我的上传器类的一个实例被赋予对图像的引用并上传它。然后上传者将其引用设置为 nil。因此,图像的“init”和“将其设置为 nil”发生在两个不同的地方。
猜你喜欢
  • 2013-05-21
  • 2016-12-12
  • 2021-06-30
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多