Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 核心数据:;允许外部存储“;大文件上的性能_Ios_Swift_Core Data - Fatal编程技术网

Ios 核心数据:;允许外部存储“;大文件上的性能

Ios 核心数据:;允许外部存储“;大文件上的性能,ios,swift,core-data,Ios,Swift,Core Data,我试图了解核心数据属性的允许外部存储的行为,并查看它是否可以避免我手动将文件存储在文件系统中。我想看看它在处理非常大的文件时会有什么表现。为此,我创建了一个虚拟项目,并使用核心数据存储了一个大文件(2GB)。然后,我在获取和处理数据时监视内存使用情况,令我惊讶的是,它没有超过48MB!为什么呢?它是否以块的形式获取数据?如果是,怎么做?Datastruct是否有允许核心数据执行此操作的API 我所做的更多细节: 创建了一个实体文件,该实体只有两个属性,文件名(字符串)和数据(数据) 选中了数据

我试图了解核心数据属性的
允许外部存储的行为,并查看它是否可以避免我手动将文件存储在文件系统中。我想看看它在处理非常大的文件时会有什么表现。为此,我创建了一个虚拟项目,并使用核心数据存储了一个大文件(2GB)。然后,我在获取和处理数据时监视内存使用情况,令我惊讶的是,它没有超过48MB!为什么呢?它是否以块的形式获取数据?如果是,怎么做?
Data
struct是否有允许核心数据执行此操作的API

我所做的更多细节:

  • 创建了一个实体
    文件
    ,该实体只有两个属性,
    文件名
    (字符串)和
    数据
    (数据)
  • 选中了
    数据
    属性的
    允许外部存储
    属性
  • 文件
    实体中存储了一个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
      静态方法返回文件实体中的所有文件
    这里是process方法,它循环遍历数据,逐字节,读取和XORing,然后返回结果。实际上,它可以是任何方法,重要的是读取数据的所有字节

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

  • 我很确定它与核心数据有关,而不是
    数据
    ,因为在从磁盘加载
    数据时执行相同的步骤(
    数据(contentsOf:URL)
    )将导致3+GB内存使用率(还有,为什么会增加1 GB?)

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


    任何帮助都将不胜感激

    一般来说,关系数据库在存储和检索大量数据时并不好。任何大于1兆字节的数据都不应该存储在数据库中。核心数据使问题更加严重。如果您直接访问数据库,则只能获取特定列,但由于核心数据将行转化为对象,将列转化为属性,您无法控制获取的内容。当您将属性设置为“允许外部存储”
    时,核心数据将在文件系统中存储大数据块,并且仅在您访问该属性时加载它。这对于许多情况都很好,因为它很容易,并且可以极大地提高性能


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

    如果您将所有数据都保存到变量中,您希望如何不使用3gb的RAM?@Lu_uu也许您是对的,但我希望管理大数据的开销略高于2GB,而不是1GB!谢谢你的回答
    问题是,访问此类属性可能会导致加载大型文件的大量意外成本
    ,但正如我在问题中所示,加载和处理2GB文件所用内存不会超过48 MB。我知道您只是对实体进行了故障诊断。您是否访问了包含此大数据的属性?