我试图了解 Core Data 属性的 Allows External Storage
属性的行为,看看它是否可以让我免于在文件系统中手动存储文件。我想看看在处理非常大的文件时它的表现如何。为此,我创建了一个虚拟项目并使用 Core Data 存储了一个大文件 (2 GB)。然后,我在获取和处理数据时监控了内存使用情况,令我惊讶的是,它并没有超过 48 MB!这是为什么?它是否以 block 的形式获取数据?如果是这样,如何? Data
结构是否具有允许 Core Data 执行此操作的 API?
我所做的更多细节:
- 创建了一个只有两个属性的实体
File
,fileName
(字符串)和data
(数据)。
- 检查了
data
属性的Allows External Storage
属性。 在
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) }
关闭应用程序,然后使用
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 }
- File 类的
我监控了内存使用情况。
我很确定它与 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/