I needed to traverse a large part (500k+ files) of the file tree, and switched from passing the FileManager.default.enumerator() a String to a URL. The traverse becomes 3x faster, and I am looking to understand why.
I'm testing on my Mac with an APFS formatted drive.
This is my test code to measure this in a Swift Playground:
import Cocoa
var startingTime: Date
var pathCount = 0
var urlCount = 0
let path = "/Users/tom/myfolder/"
let pathEnumerator = FileManager.default.enumerator(atPath: path)
let url = URL(fileURLWithPath: path)
let urlEnumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: nil)
print("== URL Enumerator ==")
startingTime = Date()
while let _ = urlEnumerator?.nextObject() as? URL {
urlCount += 1
}
print("\n\(urlCount) files.")
print("\(startingTime.timeIntervalSinceNow * -1) seconds elapsed")
print("\n\n")
print("== Path/String Enumerator ==")
startingTime = Date()
while let _ = pathEnumerator?.nextObject() as? String {
pathCount += 1
}
print("\n\(pathCount) files.")
print("\(startingTime.timeIntervalSinceNow * -1) seconds elapsed")
This is the output I get:
== URL Enumerator ==
541879 files.
40.580654978752136 seconds elapsed
== Path/String Enumerator ==
541879 files.
118.60869300365448 seconds elapsed
If I change the order (do the String version first), it makes no difference, so it doesn't appear to be a caching artefact.

