Explorar el Código

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 hace 5 años
padre
commit
045208acb2
Se han modificado 1 ficheros con 17 adiciones y 0 borrados
  1. 17 0
      Sources/Cache/DiskStorage.swift

+ 17 - 0
Sources/Cache/DiskStorage.swift

@@ -46,6 +46,8 @@ public enum DiskStorage {
         public let directoryURL: URL
 
         let metaChangingQueue: DispatchQueue
+        
+        var maybeCached : Set<String>?
 
         /// Creates a disk storage with the given `DiskStorage.Config`.
         ///
@@ -72,6 +74,17 @@ public enum DiskStorage {
             metaChangingQueue = DispatchQueue(label: cacheName)
 
             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.
@@ -135,6 +148,7 @@ public enum DiskStorage {
                     )
                 )
             }
+            maybeCached?.insert(fileURL.lastPathComponent)
         }
 
         func value(forKey key: String, extendingExpiration: ExpirationExtending = .cacheTime) throws -> T? {
@@ -150,6 +164,9 @@ public enum DiskStorage {
             let fileManager = config.fileManager
             let fileURL = cacheFileURL(forKey: key)
             let filePath = fileURL.path
+            guard maybeCached?.contains(fileURL.lastPathComponent) ?? true else {
+                return nil
+            }
             guard fileManager.fileExists(atPath: filePath) else {
                 return nil
             }