Dal*_*zio 2 memory cocoa caching objective-c
我一直在使用NSCache来存储因性能原因而应该缓存的项目,因为重新创建它们相当昂贵.理解NSCache行为让我有些头疼.
我按如下方式初始化我的NSCache:
_cellCache = [[NSCache alloc] init];
[_cellCache setDelegate:self];
[_cellCache setEvictsObjectsWithDiscardedContent:NO]; // never evict cells
Run Code Online (Sandbox Code Playgroud)
缓存中保存的对象实现NSDiscardableContent协议.现在我的问题是NSCache类似乎在几个实例中没有正常工作.
1)首先是较小的问题.NSCache的setCountLimit:声明:
将计数限制设置为小于或等于0的数字将不会影响缓存的最大大小.
有人能说清楚这意味着什么吗?即,NSCache是最大的,并且只有在别处需要内存时才会发出discardContentIfPossible消息?或者NSCache是最小的,它会立即发出discardContentIfPossible消息?
前者更有意义,但测试似乎表明后者正在发生的事情.如果我登录来电来discardContentIfPossible在我的缓存对象的方法,我看到它被称为几乎立即-后只有2-3十几个项目已被添加到缓存(每个不到0.5 MB).
好的.所以我尝试设置一个大的计数限制 - 比我需要的更多 - 通过添加以下行:
[_cellCache setCountLimit:10000000];
Run Code Online (Sandbox Code Playgroud)
然后几乎不会立即发送discardContentIfPossible消息.我必须将更多内容加载到缓存中并在这些消息开始发生之前使用它一段时间,这更有意义.
那么这里的预期行为是什么?
2)更大的问题.文件说明:
默认情况下,如果丢弃其内容,则会自动从缓存中删除缓存中的NSDiscardableContent对象,但可以更改此自动删除策略.如果将NSDiscardableContent对象放入缓存中,则缓存在删除时会调用discardContentIfPossible.
所以我将驱逐政策设置为NO(如上所述),因此对象永远不会被驱逐.相反,当调用discardContentIfPossible时,我会根据特殊条件清除并释放缓存对象的内部数据.也就是说,我可能决定在某些情况下不会实际清除和丢弃数据(例如,如果该项目最近已被使用过).在这种情况下,我只是从discardContentIfPossible方法返回而没有丢弃任何东西.这个想法是,最近没有使用的其他一些对象会在某个时刻获得消息,而它可以丢弃它的内容.
现在,有趣的是,所有这些似乎都适用于大量使用.加载大量内容,放置和访问缓存中的对象等.经过一段时间,当我尝试访问NSCache中的任意对象时,它实际上并不存在!不知何故,它似乎已被删除 - 即使我专门将驱逐政策设置为NO.
好的.因此实现委托方法cache:willEvictObject:表明它永远不会被调用.这意味着该对象实际上并没有被逐出.但它神秘地从NSCache消失,因为它不能在未来的查询中找到-或以某种方式将其用是不再映射到原来的对象相关联的密钥.但这怎么可能发生呢?
顺便说一句,我与我的值对象(CALayer)关联的关键对象是NSURL容器/包装器,因为我不能直接使用NSURL,因为NSCache不复制密钥 - 只保留它们,以及后来的NSURL密钥用于查找可能不是最初用于加载具有该对象的缓存的确切原始对象(仅相同的URL字符串).使用NSURL包装器/容器,我可以确保它是用于将原始值对象添加到NSCache的确切原始密钥对象.
任何人都可以对此有所了解吗?
Rob*_*ier 13
你的评论"永远不会驱逐细胞"并不是-setEvictsObjectsWithDiscardedContent:
它所说的.它说它不会因为它们的内容被丢弃而驱逐细胞.这与说永远不会驱逐细胞不一样.您仍然可以超过最大尺寸或数量,但仍可以逐出.可丢弃内容的优点是您可以放弃某些内容而无需从缓存中删除自己.然后,您将根据需要重建丢弃的内容,但可能不必重建整个对象.在某些情况下,这可能是一场胜利.
这就把我们带到了你的第一个问题.是的,NSCache
当它达到最大尺寸时开始逐出.这就是它被称为"最大尺寸"的原因.您没有指出这是Mac还是iPhone,但在这两种情况下,您都不希望缓存增长,直到内存耗尽.这在许多方面都很糟糕.在Mac上,你会在内存耗尽之前开始长时间交换.在iOS中,您不希望开始向每个其他进程发送内存警告,因为一个进程对其缓存感到疯狂.在任何一种情况下,太大的缓存都会提供较差的性能.因此,投入的对象NSCache
应该始终在任何时候被驱逐.
归档时间: |
|
查看次数: |
3636 次 |
最近记录: |