ios - 核心数据 : "Allows External Storage" performance on large files

标签 ios swift core-data

我试图了解 Core Data 属性的 Allows External Storage 属性的行为,看看它是否可以让我免于在文件系统中手动存储文件。我想看看在处理非常大的文件时它的表现如何。为此,我创建了一个虚拟项目并使用 Core Data 存储了一个大文件 (2 GB)。然后,我在获取和处理数据时监控了内存使用情况,令我惊讶的是,它并没有超过 48 MB!这是为什么?它是否以 block 的形式获取数据?如果是这样,如何? Data 结构是否具有允许 Core Data 执行此操作的 API?

我所做的更多细节:

  1. 创建了一个只有两个属性的实体 FilefileName(字符串)和 data(数据)。

enter image description here

  1. 检查了 data 属性的 Allows External Storage 属性。
  2. File 实体中存储了一个 2 GB 的文件。我将此代码放在 viewDidLoad 方法中来执行此操作。

    do {
        // Store file
        let fileURL = Bundle.main.url(forResource: "RawData/LargeFile", withExtension: nil)!
        let file = File(context: AppDelegate.viewContext)
        file.name = fileName
        file.data = try Data(contentsOf: fileURL)
        try AppDelegate.viewContext.save()
    
    } catch {
        print(error.localizedDescription)
    }
    
  3. 关闭应用程序,然后使用 viewDidLoad 中的新代码重新启动它以获取和处理大文件的数据。

    let fileData = File.files(named: name).first!.data!
    DispatchQueue.global(qos: .userInteractive).async {
        let result = self.process(data: fileData)
        print("The result: \(result)") 
    }
    
    • File 类的 files 静态方法返回 File 实体中的所有文件。

    这里是 process 方法,它循环遍历数据,逐字节读取,然后进行异或运算,然后返回结果。它实际上可以是任何方法,这里重要的是读取数据的所有字节。

    private func process(data: Data) -> UInt8 {
        print("Processsing \(data.count) bytes")
        var accumulator: UInt8 = 0
        for byte in data {
            accumulator ^= byte
        }
        return accumulator
    }
    
  4. 我监控了内存使用情况。

我很确定它与 Core Data 而不是 Data 有关,因为从磁盘加载 data 时执行相同的步骤(Data (contentsOf: URL)) 将导致 3+ GB 的内存使用量(另外,为什么要额外使用 1 GB?)。

最后,是否有任何理由不使用 Allows External Storage 功能,而是在文件系统中手动存储文件?我知道这个问题已经讨论了很多;但是我读过的大多数建议使用手动方式的观点都提到了 Core Data 的性能问题,尽管我的小实验表明 Core Data 表现良好。

如有任何帮助,我们将不胜感激!

最佳答案

关系数据库通常不适合存储和检索大数据 block 。任何大于 1 兆字节的数据都不应存储在数据库中。核心数据使问题变得更糟。如果您直接访问数据库,则只能获取特定的列,但是随着核心数据将行变成对象,将列变成属性,您无法控制获取的内容。当您将属性设置为 Allows External Storage 时,Core-data 会将大量数据存储在文件系统中,并且仅在您访问该属性时加载它。这对很多情况来说都很好,因为它很容易并且可以大大提高性能。

问题在于,访问这样的属性可能会产生巨大的意外成本,因为加载一个仅访问属性并不清楚的大文件。相反,如果您存储了一个文件名并明确地进行了从磁盘加载文件的第二步,那就是在您加载数据时。此外,如果可以从 Internet 恢复此数据(例如,它们是从 imageURL 下载的图像),则最好在核心数据之外管理这些数据,因为您可以管理缓存,这在核心数据中很难做到。

关于ios - 核心数据 : "Allows External Storage" performance on large files,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57372449/

相关文章:

ios - 在 iOS 或 macOS 系统上复制所选文本后是否可以启动我的应用程序?

ios - UIWebView/NSURLProtocol - 离线时不可访问的外部 Assets 的占位符

ios - Collection View Controller 的顶部栏

ios - iOS 上的 MobileVLCKit 问题(夜间构建)

ios - 如何计算属性中的记录数?

iOS:调试简单的 UI 滞后(我猜是基于 CoreData)

objective-c - 什么用于核心数据排序?

ios - viewWIllTransition 没有在多个 Controller 中被调用

swift - 这个 MVP Metal main.swift 显示为空白

ios - 通过代码删除 Parse 中的列/索引