Remove in-memory caches of most original image data

This commit is contained in:
Shadowfacts 2021-01-17 11:45:04 -05:00
parent c12d2db258
commit 6dee0957ea
3 changed files with 26 additions and 14 deletions

View File

@ -29,7 +29,7 @@ class ImageCache {
private var backgroundQueue = DispatchQueue(label: "ImageCache completion queue", qos: .default) private var backgroundQueue = DispatchQueue(label: "ImageCache completion queue", qos: .default)
init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry? = nil) { init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry? = nil) {
self.cache = ImageDataCache(name: name, memoryExpiry: memoryExpiry, diskExpiry: diskExpiry) self.cache = ImageDataCache(name: name, memoryExpiry: memoryExpiry, diskExpiry: diskExpiry, storeOriginalDataInMemory: diskExpiry == nil)
} }
func get(_ url: URL, completion: ((Data?, UIImage?) -> Void)?) -> Request? { func get(_ url: URL, completion: ((Data?, UIImage?) -> Void)?) -> Request? {
@ -39,9 +39,9 @@ class ImageCache {
// in performance sensitive paths. a nice optimization to DiskStorage would be adding an internal cache // in performance sensitive paths. a nice optimization to DiskStorage would be adding an internal cache
// of the state (unknown/exists/does not exist) of whether or not objects exist on disk so that the slow, disk I/O // of the state (unknown/exists/does not exist) of whether or not objects exist on disk so that the slow, disk I/O
// path can be avoided most of the time // path can be avoided most of the time
let (data, image) = try? cache.get(key) { let entry = try? cache.get(key) {
backgroundQueue.async { backgroundQueue.async {
completion?(data, image) completion?(entry.data, entry.image)
} }
return nil return nil
} else { } else {
@ -67,7 +67,7 @@ class ImageCache {
return try? cache.getData(url.absoluteString) return try? cache.getData(url.absoluteString)
} }
func get(_ url: URL) -> (Data, UIImage)? { func get(_ url: URL) -> ImageDataCache.Entry? {
return try? cache.get(url.absoluteString) return try? cache.get(url.absoluteString)
} }

View File

@ -11,10 +11,12 @@ import Cache
class ImageDataCache { class ImageDataCache {
private let memory: MemoryStorage<(Data, UIImage)> private let memory: MemoryStorage<Entry>
private let disk: DiskStorage<Data>? private let disk: DiskStorage<Data>?
init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry?) { private let storeOriginalDataInMemory: Bool
init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry?, storeOriginalDataInMemory: Bool) {
let memoryConfig = MemoryConfig(expiry: memoryExpiry) let memoryConfig = MemoryConfig(expiry: memoryExpiry)
self.memory = MemoryStorage(config: memoryConfig) self.memory = MemoryStorage(config: memoryConfig)
@ -24,6 +26,8 @@ class ImageDataCache {
} else { } else {
self.disk = nil self.disk = nil
} }
self.storeOriginalDataInMemory = storeOriginalDataInMemory
} }
func has(_ key: String) throws -> Bool { func has(_ key: String) throws -> Bool {
@ -37,29 +41,30 @@ class ImageDataCache {
} }
} }
func get(_ key: String) throws -> (Data, UIImage)? { func get(_ key: String) throws -> Entry? {
if try memory.existsObject(forKey: key) { if try memory.existsObject(forKey: key) {
return try! memory.object(forKey: key) return try! memory.object(forKey: key)
} else if let disk = self.disk, } else if let disk = self.disk,
try disk.existsObject(forKey: key), try disk.existsObject(forKey: key),
let data = try? disk.object(forKey: key), let data = try? disk.object(forKey: key),
let image = UIImage(data: data) { let image = UIImage(data: data) {
return (data, image) return Entry(data: data, image: image)
} else { } else {
return nil return nil
} }
} }
func getImage(_ key: String) throws -> UIImage? { func getImage(_ key: String) throws -> UIImage? {
return try get(key)?.1 return try get(key)?.image
} }
func getData(_ key: String) throws -> Data? { func getData(_ key: String) throws -> Data? {
return try get(key)?.0 return try get(key)?.data
} }
func set(_ key: String, data: Data, image: UIImage) throws { func set(_ key: String, data: Data, image: UIImage) throws {
memory.setObject((data, image), forKey: key) let entry = Entry(data: storeOriginalDataInMemory ? data : nil, image: image)
memory.setObject(entry, forKey: key)
if let disk = self.disk { if let disk = self.disk {
try disk.setObject(data, forKey: key) try disk.setObject(data, forKey: key)
@ -72,3 +77,10 @@ class ImageDataCache {
} }
} }
extension ImageDataCache {
struct Entry {
let data: Data?
let image: UIImage
}
}

View File

@ -85,8 +85,8 @@ class LoadingLargeImageViewController: UIViewController, LargeImageAnimatableVie
overrideUserInterfaceStyle = .dark overrideUserInterfaceStyle = .dark
view.backgroundColor = .black view.backgroundColor = .black
if let (data, image) = cache.get(url) { if let entry = cache.get(url) {
createLargeImage(data: data, image: image, url: url) createLargeImage(data: entry.data, image: entry.image, url: url)
} else { } else {
createPreview() createPreview()
@ -115,7 +115,7 @@ class LoadingLargeImageViewController: UIViewController, LargeImageAnimatableVie
} }
} }
private func createLargeImage(data: Data, image: UIImage, url: URL) { private func createLargeImage(data: Data?, image: UIImage, url: URL) {
guard !loaded else { return } guard !loaded else { return }
loaded = true loaded = true