FileManager.contentsEqual(atPath:andPath:) very slow

Until now I was using FileManager.contentsEqual(atPath:andPath:) to compare file contents in my App Store app, but then a user reported that this operation is way slower than just copying the files (which I made faster a while ago, as explained in Making filecopy faster by changing block size).

I thought that maybe the FileManager implementation reads the two files with a small block size, so I implemented a custom comparison with the same block size I use for filecopy (as explained in the linked post), and it runs much faster. When using the code for testing repeatedly also found on that other post, this new implementation is about the same speed as FileManager for 1KB files, but runs 10-20x faster for 1MB files or bigger.

Feel free to comment on my implementation below.

extension FileManager {
    
    func fastContentsEqual(atPath path1: String, andPath path2: String, progress: (_ delta: Int) -> Bool) -> Bool {
        do {
            let bufferSize = 16_777_216
            let sourceDescriptor = open(path1, O_RDONLY | O_NOFOLLOW, 0)
            if sourceDescriptor < 0 {
                throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
            }
            let sourceFile = FileHandle(fileDescriptor: sourceDescriptor)
            let destinationDescriptor = open(path2, O_RDONLY | O_NOFOLLOW, 0)
            if destinationDescriptor < 0 {
                throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
            }
            let destinationFile = FileHandle(fileDescriptor: destinationDescriptor)
            var equal = true
            while autoreleasepool(invoking: {
                let sourceData = sourceFile.readData(ofLength: bufferSize)
                let destinationData = destinationFile.readData(ofLength: bufferSize)
                equal = sourceData == destinationData
                return sourceData.count > 0 && progress(sourceData.count) && equal
            }) { }
            if close(sourceDescriptor) < 0 {
                throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
            }
            if close(destinationDescriptor) < 0 {
                throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
            }
            return equal
        } catch {
            return contentsEqual(atPath: path1, andPath: path2) // use this as a fallback for unsupported files (like symbolic links)
        }
    }
    
}
FileManager.contentsEqual(atPath:andPath:) very slow
 
 
Q