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

读取超3万条JSON数据时Call Directory Extension因内存过高被杀死,求优化

解决Swift读取大JSON数组时的内存溢出问题

你的问题核心是一次性将整个大JSON文件加载到内存并解码,当元素超过3万时,内存占用会突破Extension的系统限制,导致进程被杀死。之前的分块处理没效果,大概率是分块逻辑仍未避免一次性加载全量数据。

下面是针对大JSON数组的优化方案,核心是流式解析,逐元素读取解码,彻底降低内存峰值:

优化后的代码

public func readReportFile() -> [ReportModel] {
    let fileURL = self.reportStoreUrl.appendingPathComponent(fileName).appendingPathExtension("json")
    guard let stream = InputStream(url: fileURL) else {
        print("Error: Could not open file stream at \(fileURL)")
        return []
    }
    
    stream.open()
    defer { stream.close() }
    
    let jsonDecoder = JSONDecoder()
    var result: [ReportModel] = []
    
    do {
        // 流式解析JSON,不一次性加载全量文件
        let parserResult = try JSONSerialization.jsonObject(with: stream, options: [])
        guard let jsonArray = parserResult as? [[String: Any]] else {
            print("Error: JSON content is not an array")
            return []
        }
        
        // 逐个解码元素,控制内存占用在单个模型级别
        for jsonItem in jsonArray {
            guard let itemData = try? JSONSerialization.data(withJSONObject: jsonItem) else {
                print("Error: Failed to convert JSON item to data")
                continue
            }
            if let model = try? jsonDecoder.decode(ReportModel.self, from: itemData) {
                result.append(model)
            }
        }
    } catch {
        print("Error: Stream parsing failed: \(error)")
        return []
    }
    
    return result
}

针对5万+元素的进阶优化

如果未来数据量持续增长,即使返回全量[ReportModel]数组也会占用大量内存,建议根据业务场景调整:

  • 边解析边持久化:解析一个元素就写入Core Data/Realm等本地存储,无需在内存中保留全量数组
  • 异步流返回:将函数改为返回AsyncThrowingStream<ReportModel, Error>,通过异步流逐个输出元素,完全规避全量内存占用

为什么之前的分块处理无效?

如果之前的分块是先读取整个文件到内存再拆分,本质还是一次性加载了所有数据,内存峰值没有降低。必须从文件读取阶段就采用流式处理,才是真正的内存优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:28:27