Ios CoreData—(频繁数据的性能)注意事项

Ios CoreData—(频繁数据的性能)注意事项,ios,performance,core-data,Ios,Performance,Core Data,背景 我们有一个应用程序,接收传感器数据在100赫兹。每个传感器数据包含三个浮点数。偶尔(最多1/s)也会收到一些需要保存的其他元数据。UI在图形中显示最新的1000个传感器值。没有撤消要求-所有接收到的数据都必须保存到文件中。每次会议至少持续10分钟,但可能(在极少数情况下,主要是由于错误)长达一小时 当前方法 型号:SensorData与会话具有多对一关系元数据与会话具有多对一关系 CoreData:设置UIManagedDocument以处理CoreData。主线程上有一个MOC,私有队列

背景

我们有一个应用程序,接收传感器数据在100赫兹。每个传感器数据包含三个浮点数。偶尔(最多1/s)也会收到一些需要保存的其他元数据。UI在图形中显示最新的1000个传感器值。没有撤消要求-所有接收到的数据都必须保存到文件中。每次会议至少持续10分钟,但可能(在极少数情况下,主要是由于错误)长达一小时

当前方法

型号:
SensorData
会话具有多对一关系<代码>元数据
会话
具有多对一关系

CoreData:设置UIManagedDocument以处理CoreData。主线程上有一个MOC,私有队列上有一个子MOC。子MOC创建对象并将其添加到对象图中。每100个数据,保存子MOC。会话结束后,将主MOC保存到PSC

编辑:当前方法的问题是在子MOC中的保存滞后,这意味着当会话结束时,并非所有数据都已处理,并且处理时间随着运行时间的增加而增加

问题

  • 使用CoreData作为~100 Hz的存储机制是否可行,或者我是否应该考虑一些替代方案(如保存到csv文件)
  • 我必须采取哪些措施来确保适当/最佳的性能
  • 我遇到过保存时间过长和阻塞UI的性能问题。我怎样才能避免这种情况?即,我应该使用什么储蓄政策
  • 当前方法的缺点和优点

    • 我认为核心数据可以做到这一点

      您可以使用Marcus Zarra的三种上下文方法来确保实际的保存也发生在后台

      RootContext (background) saves to persistent store  ---> is parent of
      MainContext (main thread) to update the UI          ---> is parent of one or more
      WorkerContext (background) to create new data from sensor
      
      然后,您可以更频繁地在后台直接保存到持久性存储,而不会影响UI响应。这也会提高内存使用率。保存工作上下文将把更改推送到UI,UI可以相应地更新

      为了提高性能,请确保批量保存—使用三个浮点值,我会估计大约每1000到5000条记录(您需要进行实验以找到最佳值)

      关闭撤消管理器。(
      context.undoManager=nil


      另一个需要考虑的问题是,可能需要仔细考虑您希望在UI中显示什么,并且可能需要计算动态显示的值并将其发送到UI,而不是让UI依赖整个会话的数据集进行自我更新。

      我在详细介绍中遇到了这个问题

      我的任务是以高达100Hz的速率记录(例如)核心运动和核心位置的实时传感器数据,同时运行平滑的动画界面,该界面可以包含任何核心图形、核心动画、OpenGL和实时视频。有大约20-40个独立的数据项需要跟踪,大部分是双倍的,只有一个或两个字符串,而且它们的同步速率并不相同

      保存过程中的任何停顿,无论多么轻微,都会立即影响界面

      我对使用核心数据与直接写入SQL数据库(使用sqlite3)进行比较感兴趣。到目前为止,我的个人经验(这是一项正在进行的工作)是,SQL方法比核心数据更适合这种类型的问题。事实上,这并不是核心数据优化的真正目的(而是通过撤销、持久化和高效故障处理来管理复杂的文档对象模型)。核心数据模型几乎假设持久保存速度会非常慢(例如,保存到iCloud),而它的许多工程设计都是为了解决这个问题

      我尝试过各种核心数据模式、背景、父/子上下文、同步、异步、批处理保存。。。每次持续保存时,我总是会发现明显的口吃

      另一方面,SQL方法简单易懂,效率高,并且完全没有明显的故障

      很可能我还没有找到这个问题的最佳核心数据模式(我将对此进行更深入的研究,因为这是一个有趣的边缘案例)。但是,如果在更广泛的应用程序环境中对您有意义的话,我肯定会建议您看看直接到SQL的方法

      在稍有不同的数据流使用情况下(例如,通过蓝牙传输的250-500Hz信号),我选择了音频接口使用的信号处理技巧—随着数据速率的提高,环形缓冲区、队列和回调会变得非常有用。在某种程度上,数据速率会变得太高,数据库编写过程无法跟上:然后——正如您所建议的那样——直接保存到文件将更加高效。在不进行采样时,您可以随时从文件中读取数据,并填充数据库(或核心数据)

      Matt Gallagher对核心数据和数据库进行了很好的比较。
      . 关于使用高频数据流编写平面文件优于数据库的好处,也有一些有用的讨论(也同样过时了)。

      核心数据肯定可以做到这一点(过去也是以这种速度)。经常保存孩子(正常情况下,每秒1次就足够了),不经常保存到磁盘(每隔几秒钟),并且你不应该有内存问题或数据丢失问题(除非应用程序崩溃)。好吧,过了一段时间,我就开始工作了。我犯了两个错误。1) 我使用的是在根上下文的主队列上创建的UIDocument。2) 虽然我只批量保存,但我并没有批量创建实体。但是,这是在另一个项目上,我没有使用MainContext。感谢您的关注!我从未解决该问题,而是放弃了该功能。使用CoreData的原因是,许多其他数据非常适合