This is what I see in the documentation.
The NSCache class incorporates various auto-eviction policies, which ensure that a cache doesn’t use too much of the system’s memory. If memory is needed by other applications, these policies remove some items from the cache, minimizing its memory footprint.
But when I look into the source code: https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSCache.swift
I see nothing about it somehow deletes items, when under memory pressure. It only deletes items when you reach the cost limit.
I made a small test:
class Data {
var data = [Int]()
init() {
for i in 0..<1000000 {
data.append(i)
}
}
}
var cache = NSCache<NSNumber, Data>()
for i in 0..<10000000 {
cache.setObject(Data(), forKey: NSNumber(value: i))
}
And after that test the app eats all the memory and crashes. So. Does the documentation lie?
NSCache is really nice for a few reasons: It stores data in memory only. If our app gets killed, this memory is freed up and it's not persisted to disk. The key-value pair mechanism lets us very easily set and get cached content.
The NSCache class incorporates various auto-eviction policies, which ensure that a cache doesn't use too much of the system's memory. If memory is needed by other applications, these policies remove some items from the cache, minimizing its memory footprint.
Avoiding stale data What makes NSCache a better fit for caching values compared to the collections found in the Swift standard library (such as Dictionary ) is that it'll automatically evict objects when the system is running low on memory — which in turn enables our app itself to remain in memory for longer.
One more thing about NSCache is, it is thread safe. We can access it from any thread without worrying about managing threads while accessing NSCache. You can set & get name for cache. The default value is an empty string (“”).
First, and most importantly, swift-corelibs-foundation is not the Foundation from iOS and macOS:
This project, swift-corelibs-foundation, provides an implementation of the Foundation API for platforms where there is no Objective-C runtime. On macOS, iOS, and other Apple platforms, apps should use the Foundation that comes with the operating system. Our goal is for the API in this project to match the OS-provided Foundation and abstract away the exact underlying platform as much as possible.
Next, your test case does not carefully test NSCache
. Your Data
objects could be stored on the autorelease pool and not released. In this case that's not true, but it's the kind of thing you need to be very careful about when testing memory usage.
That said, I can't reproduce your issue. When I put this in an iOS app and run it on iOS 12, I see the kind of behavior you're probably expecting:
Big run-up in memory usage to ~1GB, at which point the cache is dumped as expected.
I also wasn't able to easily reproduce it on macOS (but I wasn't patient enough to let it crash, so it's possible it eventually would). You'll need to give a more precise example of where this crashes unexpectedly in order to diagnose why.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With