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

如何通过并行处理优化6000个JSON文件的Codable解析速度?

并行解析JSON文件优化方案

针对6000个JSON文件的串行解析耗时问题,以下是几种实用的并行处理方案,可大幅缩短解析时间:

一、Swift Concurrency(Async/Await,iOS 15+/macOS 12+ 推荐)

利用Swift原生的并发框架,代码简洁且自动管理并发调度:

func parseAllDrugs() async throws -> [Drug] {
    let drugMonographURLs = [/* 你的URL数组 */]
    let decoder = JSONDecoder() // 复用解码器,减少对象创建开销
    
    return try await withThrowingTaskGroup(of: Drug.self) { group in
        // 为每个URL添加并行解析任务
        for url in drugMonographURLs {
            group.addTask {
                let data = try Data(contentsOf: url)
                return try decoder.decode(Drug.self, from: data)
            }
        }
        
        // 串行收集所有解析结果(自动保证线程安全)
        var drugs = [Drug]()
        for try await drug in group {
            drugs.append(drug)
        }
        return drugs
    }
}

二、GCD并发队列方案

兼容iOS 15以下版本,手动控制并发流程:

func parseAllDrugs(completion: @escaping (Result<[Drug], Error>) -> Void) {
    let drugMonographURLs = [/* 你的URL数组 */]
    // 创建自定义并发队列,避免占用全局高优先级队列
    let concurrentQueue = DispatchQueue(label: "com.your.drug.parser", attributes: .concurrent)
    let group = DispatchGroup()
    let syncQueue = DispatchQueue(label: "com.your.drug.sync") // 串行队列保证数组线程安全
    
    var drugs = [Drug]()
    var parseError: Error?
    let decoder = JSONDecoder()
    
    for url in drugMonographURLs {
        group.enter()
        concurrentQueue.async {
            guard parseError == nil else {
                group.leave()
                return
            }
            
            do {
                let data = try Data(contentsOf: url)
                let drug = try decoder.decode(Drug.self, from: data)
                // 串行队列同步写入数组
                syncQueue.sync {
                    drugs.append(drug)
                }
            } catch {
                syncQueue.sync {
                    parseError = parseError ?? error
                }
            }
            group.leave()
        }
    }
    
    // 所有任务完成后回调结果
    group.notify(queue: .main) {
        if let error = parseError {
            completion(.failure(error))
        } else {
            completion(.success(drugs))
        }
    }
}

三、OperationQueue方案

通过操作队列灵活控制并发数:

func parseAllDrugs(completion: @escaping (Result<[Drug], Error>) -> Void) {
    let drugMonographURLs = [/* 你的URL数组 */]
    let queue = OperationQueue()
    // 根据CPU核心数设置并发上限,避免磁盘IO过度竞争
    queue.maxConcurrentOperationCount = ProcessInfo.processInfo.activeProcessorCount
    
    var drugs = [Drug]()
    let syncQueue = DispatchQueue(label: "com.your.drug.sync")
    var parseError: Error?
    let decoder = JSONDecoder()
    
    // 完成操作,等待所有解析任务结束后回调
    let completionOp = BlockOperation {
        DispatchQueue.main.async {
            if let error = parseError {
                completion(.failure(error))
            } else {
                completion(.success(drugs))
            }
        }
    }
    
    for url in drugMonographURLs {
        let parseOp = BlockOperation {
            guard parseError == nil else { return }
            
            do {
                let data = try Data(contentsOf: url)
                let drug = try decoder.decode(Drug.self, from: data)
                syncQueue.sync {
                    drugs.append(drug)
                }
            } catch {
                syncQueue.sync {
                    parseError = parseError ?? error
                }
            }
        }
        completionOp.addDependency(parseOp)
        queue.addOperation(parseOp)
    }
    
    OperationQueue.main.addOperation(completionOp)
}

关键注意事项

  • 控制并发数:磁盘IO的并发上限并非越高越好,建议设置为CPU核心数或2-4倍,过多并发会导致磁盘频繁寻址反而降低效率,需根据实际测试调整。
  • 错误处理:上述示例若单个文件解析失败会终止整个流程,若需忽略错误继续解析,可修改代码收集成功结果和错误列表。
  • 线程安全:必须保证数组写入操作的线程安全,可通过串行队列、锁或Swift Concurrency的TaskGroup自动收集实现。
  • 性能优化:复用JSONDecoder实例减少对象创建开销;若文件过大,可考虑异步读取文件内容(如FileHandle的异步API)避免内存峰值过高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:10:30