You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调整块大小优化copyfile拷贝速度:需考虑的技术问题

关于copyfile函数块大小设置的技术疑问

使用copyfile函数拷贝大量文件时,发现其速度始终慢于cp或Finder拷贝。此前并不知晓可设置块大小,而该参数对文件拷贝速度影响显著,现提出以下技术疑问:

  • 手动设置块大小前需考虑哪些因素?
  • 采用非2的幂次的块大小是否合理?
  • 某些块大小(如过大的值)是否会引发错误(针对运行代码的Mac设备或源/目标设备)?
  • 何时应/不应偏离默认块大小?
  • 是否有方法确定给定源和目标设备的最优块大小,或至少找到比默认值性能更优的设置?

我编写了示例代码尝试测量不同块大小下的平均耗时,但不确定这是否为最佳测量方式,因为每次循环的耗时差异极大:

class AppDelegate: NSObject, NSApplicationDelegate {
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let openPanel = NSOpenPanel()
        openPanel.runModal()
        let source = openPanel.urls[0]
        openPanel.canChooseDirectories = true
        openPanel.canChooseFiles = false
        openPanel.runModal()
        let destination = openPanel.urls[0].appendingPathComponent(source.lastPathComponent)
        let date = Date()
        let count = 10
        for _ in 0..<count {
            try? FileManager.default.removeItem(at: destination)
            do {
                try copy(source: source, destination: destination)
            } catch {
                preconditionFailure(error.localizedDescription)
            }
        }
        print(-date.timeIntervalSinceNow / Double(count))
    }
    
    func copy(source: URL, destination: URL) throws {
        try source.withUnsafeFileSystemRepresentation { sourcePath in
            try destination.withUnsafeFileSystemRepresentation { destinationPath in
                let state = copyfile_state_alloc()
                defer {
                    copyfile_state_free(state)
                }
//                var bsize = Int32(16_777_216)
                var bsize = Int32(1_048_576)
                if copyfile_state_set(state, UInt32(COPYFILE_STATE_BSIZE), &bsize) != 0 || copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB), unsafeBitCast(copyfileCallback, to: UnsafeRawPointer.self)) != 0 || copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CTX), unsafeBitCast(self, to: UnsafeRawPointer.self)) != 0 || copyfile(sourcePath, destinationPath, state, copyfile_flags_t(COPYFILE_ALL | COPYFILE_NOFOLLOW | COPYFILE_EXCL)) != 0 {
                    throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
                }
            }
        }
    }

    private let copyfileCallback: copyfile_callback_t = { what, stage, state, src, dst, ctx in
        if what == COPYFILE_COPY_DATA {
            if stage == COPYFILE_ERR {
                return COPYFILE_QUIT
            }
            var size: off_t = 0
            copyfile_state_get(state, UInt32(COPYFILE_STATE_COPIED), &size)
            let appDelegate = unsafeBitCast(ctx, to: AppDelegate.self)
            if !appDelegate.setCopyFileProgress(Int64(size)) {
                return COPYFILE_QUIT
            }
        }
        return COPYFILE_CONTINUE
    }
    
    private func setCopyFileProgress(_ progress: Int64) -> Bool {
        return true
    }
    
}

内容的提问来源于stack exchange,提问作者Nickkk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:20:54