如何设置 iOS 缓存和磁盘存储大小以及应用程序终止后如何从磁盘存储恢复缓存?

How to set iOS cache and disk storage size and how does cache get restored from disk storage after app termination?

我已经问过了

现在我还有一些后续问题:

  1. 内存缓存受限于iPhone的内存(通常为2Gb)。但磁盘持久性受限于 64Gb 或 128Gb。对吗?

  2. 持久性比内存存储更有意义吗?如果您不想占用大量内存(并且不希望应用程序从其挂起状态终止)是否有用,即允许从磁盘存储恢复缓存然后 return 持久化结果?

控制点击 URLCache.shared 后,我看到以下评论:

  • Memory capacity: 4 megabytes (4 * 1024 * 1024 bytes)
  • Disk capacity: 20 megabytes (20 * 1024 * 1024 bytes)
  • Disk path:(user home directory)/Library/Caches/(application bundle id)

Users who do not have special caching requirements or constraints should find the default shared cache instance acceptable. If this default shared cache instance is not acceptable, +setSharedURLCache: can be called to set a different NSURLCache instance to be returned from this method. Callers should take care to ensure that the setter is called at a time when no other caller has a reference to the previously-set shared URL cache. This is to prevent storing cache data from becoming unexpectedly unretrievable.

docs

The response size is small enough to reasonably fit within the cache. (For example, if you provide a disk cache, the response [data] must be no larger than about 5% of the disk cache size.)

我自己收录了数据

所以我认为我的理由是正确的。


缓存的reading/writing/restoring整个过程是如何工作的?

  1. 我的意思是,当我第一次发出网络请求时,是不是整个 response/error/data 都被 写入 / 存储在缓存中,并且然后坚持下去?

  2. 下次如果我想读取那么它首先从缓存开始然后如果响应是不是stale/expired 然后它会 return 它。磁盘存储不会有任何变化。

    如果它已过期,那么它会发出一个新的请求,并且只有在 获得成功的响应,它将从内存和磁盘中清除响应并将新的响应写入缓存和磁盘。如果新的 请求失败则不会清除,而只会保留 stale/expired 数据,所以如果我们想要(加载过期的响应)它 会从那里加载吗?

  3. 当应用程序终止时,内存被清除。磁盘存储保持不变,除非设备内存不足或您已达到大小限制。下次启动应用程序时,内存会将磁盘存储中的所有内容重新加载到缓存中。

    此缓存恢复将开始加载最新数据 存储然后移动到较旧的数据,直到它要么 达到其大小限制或刚好达到存储项目的末尾 磁盘。对吧?

  4. 如果在正常情况下,用户在典型的 1 小时会话中使用的网络量约为 30mb,那么我是否应该将缓存大小设置为 20mb 和 30mb 的磁盘存储?如果我有图像怎么办?我听说图像的存储方式不同,因为 1mb 的图像可以占用 10mb 的大小。那么我应该如何管理呢?

我问这一切是因为我想改善应用程序的缓存体验并提高我的整体理解,所以我不会过多地增加应用程序的内存使用量*,这样它就不会被刷新由于我的应用程序内存使用率高或需要其他应用程序,内存从暂停状态减少。


*: 我们的一些网络请求将下载缩略图,所以我在增加缓存大小限制时需要考虑周到。

如果您想深入了解内存管理,您应该深入了解较低级别的 API。 URLSession、URLCache 等都是非常高级的API。那里有很多关于内存帧、图像缓存、网络缓存等的 WWDC 会议。每个部分都有很多解释。我建议您观看所有 WWDC 视频(如果您没有观看)以开始和热身。一些主题对这样的核心概念有很好的解释。

看看今年 WWDC 的这两个:

Image and Graphics Best Practices

iOS Memory Deep Dive

我们可以坐在这里讨论您的问题数周!但为了快速回答:

  1. 是的。由于 ram 大小和磁盘由于存储大小而限制内存。该设备和 iOS 可以根据需要稍微玩一下最大限制。
  2. 没错,这是使用磁盘的主要目标之一。有一个名为 Swap Memory 的概念(如果需要,可以进行更多调查和研发)

Compressed data temporarily moved to disk to make room in memory for more recently used data

但是内存在其帧中有自己的缓存。有时缓存会降低性能而不是提高性能。因为它是 frames.

  1. 不总是。默认情况下,只有成功的请求才会被缓存(如果服务器没有请求客户端到"don't cache it"中的header)。但是你可能知道,URLSession 在磁盘、内存等方面有大量的缓存配置,级别很高API。请参阅 URLSession 文档。

  2. 参见 NSURLRequestCachePolicy 文档。 this is a good tutorial about it. 根据您选择的策略,它的行为会有所不同,可以清除以前的缓存或保留它直到下一次成功。

  3. HomeDirectory 包含一些主要目录。 iOS 每个人的行为都不同。 iOS 只会清理 tmp 目录(磁盘缓存所在的位置)。您可以将缓存存储在不同的目录中,例如 Documents 以防止 iOS 删除它。但重点是 cache 这个词本身的意思。

  4. 任何少于 space 甚至更多 space 的实际需求都是至关重要的。它会破坏进程或浪费 memory/disk。还记得 link 列出发明的原因吗?您可以针对不同的目的使用不同的缓存,例如图像和 JSON。但是关于图片的重点是:

这些都是 Foundation 框架的核心,所有已知的第三方都只是它们的包装器。所以他们唯一的好处是:基于成千上万的贡献者知识和更高水平的预定义默认值APIs。

Alamofire and Kingfisher 就是很好的例子。

结论

正确的缓存大小取决于用例。取决于数据变体的数量、图像数量、每个图像的大小、访问同一图像的频率等等。例如,如果您不断更改缓存中的图像,它实际上会对电池寿命产生不利影响!决定合适的高速缓存大小的最佳方法是进行测试。 运行 Instruments 下的应用程序,用于测量性能和电池使用情况。不断增加缓存大小,直到您无法辨别性能差异为止。这是您需要的最大尺寸,至少在测试条件下是这样。然后减小尺寸,直到性能勉强可以接受以确定最小的可接受尺寸。合适的尺寸介于这两个尺寸之间,具体取决于您认为重要的尺寸。