瀏覽代碼

Reduce disk I/O when checking isCached

This is a low-cost best-effort strategy that triest to reduce as much
as possible the need for I/O to check if something is cached. A file
name we've never seen can just be skipped immediately. Something that
got added and was removed later would still end up hitting the disk to
figure that out, but that's not different from before.

Unsure about the exact multi-threading semantics of that Set though,
we might need to do some king of synchronization
Raja Baz 5 年之前
父節點
當前提交
045208acb2
共有 1 個文件被更改,包括 17 次插入0 次删除
  1. 17 0
      Sources/Cache/DiskStorage.swift

+ 17 - 0
Sources/Cache/DiskStorage.swift

@@ -46,6 +46,8 @@ public enum DiskStorage {
         public let directoryURL: URL
         public let directoryURL: URL
 
 
         let metaChangingQueue: DispatchQueue
         let metaChangingQueue: DispatchQueue
+        
+        var maybeCached : Set<String>?
 
 
         /// Creates a disk storage with the given `DiskStorage.Config`.
         /// Creates a disk storage with the given `DiskStorage.Config`.
         ///
         ///
@@ -72,6 +74,17 @@ public enum DiskStorage {
             metaChangingQueue = DispatchQueue(label: cacheName)
             metaChangingQueue = DispatchQueue(label: cacheName)
 
 
             try prepareDirectory()
             try prepareDirectory()
+            
+            do {
+                maybeCached = Set()
+                try config.fileManager.contentsOfDirectory(atPath: directoryURL.path).forEach { (fileName) in
+                    maybeCached?.insert(fileName)
+                }
+            } catch {
+                // Just disable the functionality if we fail to initialize it properly. This will just revert to
+                // the previous behaviour which is to check file existence on disk directly
+                maybeCached = nil
+            }
         }
         }
 
 
         // Creates the storage folder.
         // Creates the storage folder.
@@ -135,6 +148,7 @@ public enum DiskStorage {
                     )
                     )
                 )
                 )
             }
             }
+            maybeCached?.insert(fileURL.lastPathComponent)
         }
         }
 
 
         func value(forKey key: String, extendingExpiration: ExpirationExtending = .cacheTime) throws -> T? {
         func value(forKey key: String, extendingExpiration: ExpirationExtending = .cacheTime) throws -> T? {
@@ -150,6 +164,9 @@ public enum DiskStorage {
             let fileManager = config.fileManager
             let fileManager = config.fileManager
             let fileURL = cacheFileURL(forKey: key)
             let fileURL = cacheFileURL(forKey: key)
             let filePath = fileURL.path
             let filePath = fileURL.path
+            guard maybeCached?.contains(fileURL.lastPathComponent) ?? true else {
+                return nil
+            }
             guard fileManager.fileExists(atPath: filePath) else {
             guard fileManager.fileExists(atPath: filePath) else {
                 return nil
                 return nil
             }
             }