使用 UUID 的现代核心数据性能
Modern Core Data Performance with UUID
我有一个核心数据应用程序:
- 549 个具有 myJournals 关系的帐户实体(一对多)
- 24000 个具有 myJournals 关系的分类帐实体(一对多)
- 57000 个日记实体与 myAccount 和 myLedger(一对一)反向
关系
每个实体都有一个 uuidKey 字符串属性,其中包含从在线数据库导入的 UUID 字符串。
我正在尝试 运行 在 iPhone 5S 上运行该应用程序。插入对象相对较快,但查找和 link建立关系比预期的要长。
let debugTime = NSDate()
let thisRequest = NSFetchRequest(entityName: "Ledgers")
let keyLeft = NSExpression(forKeyPath: "uuidKey")
let keyRight = NSExpression(forConstantValue: ledgerKey)
let keyPredicate = NSComparisonPredicate(leftExpression: keyLeft, rightExpression: keyRight, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions.allZeros)
thisRequest.predicate = keyPredicate
thisRequest.fetchBatchSize = 1
thisRequest.fetchLimit = 1
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to create thisRequest.")
var keyError: NSError? = nil
if let keyArray = self.managedObjectContext!.executeFetchRequest(thisRequest, error: &keyError) {
if keyArray.isEmpty {
myLedger = nil
} else {
if let thisLedger = keyArray[0] as? Ledgers {
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to find thisLedger.")
myLedger = thisLedger
} else {
myLedger = nil
}
}
}
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to link myLedger.")
我得到这样的记录时间:
DEBUG COMMENT: -9.20295715332031e-05 time to create thisRequest.
DEBUG COMMENT: -0.174275994300842 time to find thisLedger.
DEBUG COMMENT: -0.174659013748169 time to link myLedger.
DEBUG COMMENT: -0.00464397668838501 time to find and link myAccount.
0.092 毫秒创建 NSFetchRequest 就可以了。
174 毫秒找到账本?当有 24k 分类帐时在索引 UUID 字符串上?!?我什么时候需要 link 这到 57k 期刊?
越快越好。当有 549 个帐户时,需要 4 毫秒才能找到 link myAccount,这有点令人失望,但可以接受。对于 Ledger 搜索,我预计大约需要 25-50 毫秒,而不是 174!
我运行在它自己的核心数据存储和上下文中使用它:
// Initialize the persistent store coordinator for the sync session.
let url = appDel.applicationDocumentsDirectory.URLByAppendingPathComponent("FoodyCoreModel.sqlite")
self.syncStore = NSPersistentStoreCoordinator(managedObjectModel: appDel.managedObjectModel)
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
let storeOptions: [NSObject: AnyObject] = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
self.syncStore.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: storeOptions, error: &error)
// Initialize the managed object contextfor the sync session
self.syncContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
self.syncContext.persistentStoreCoordinator = self.syncStore
let nmp = NSMergePolicy(mergeType: NSMergePolicyType.MergeByPropertyStoreTrumpMergePolicyType)
self.syncContext.mergePolicy = nmp
iPhone 5S 的这种性能是否合理?我在这里阅读了很多关于 Core Data 性能的问题,但其中很多都是几年前的事了。我希望 iOS 8 和更新的设备会明显更快。我不是在尝试进行 MATCHES 或 CONTAINS 搜索,只是在索引文本字段上进行 EQUALS!
我已阅读 Core Data Performance Guide。是我遗漏了什么还是我对移动设备的期望太高了?
您的代码最有可能变慢的原因是您一次获取 Ledger
个实例,而您说其中有 24,000 个。无论如何,这将是一个主要瓶颈。提取是一项相对昂贵的操作,无论您是否在谓词中使用字符串 ID,因此您的代码将花费大部分时间进行提取。
您应该分批提取而不是一次提取一个。将 50 或 100 个左右的 uuidKey
值收集到一个数组中,并使用像 "uuidKey in %@"
这样的谓词格式,并将数组作为替换变量。处理该批次,并重复直到完成。
有关如何高效导入数据的更多详细信息,请参阅 Apple 的 "Efficiently Importing Data" 指南,尤其是名为 "Implementing Find-or-Create Efficiently" 的部分。
顺便说一句,像这样使用 println
是衡量性能的一种非常糟糕的方法。使用仪器。它会以更少的开销为您提供更多详细信息,并且不会弄乱您的代码,并将帮助您准确确定瓶颈所在。
我有一个核心数据应用程序:
- 549 个具有 myJournals 关系的帐户实体(一对多)
- 24000 个具有 myJournals 关系的分类帐实体(一对多)
- 57000 个日记实体与 myAccount 和 myLedger(一对一)反向 关系
每个实体都有一个 uuidKey 字符串属性,其中包含从在线数据库导入的 UUID 字符串。
我正在尝试 运行 在 iPhone 5S 上运行该应用程序。插入对象相对较快,但查找和 link建立关系比预期的要长。
let debugTime = NSDate()
let thisRequest = NSFetchRequest(entityName: "Ledgers")
let keyLeft = NSExpression(forKeyPath: "uuidKey")
let keyRight = NSExpression(forConstantValue: ledgerKey)
let keyPredicate = NSComparisonPredicate(leftExpression: keyLeft, rightExpression: keyRight, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions.allZeros)
thisRequest.predicate = keyPredicate
thisRequest.fetchBatchSize = 1
thisRequest.fetchLimit = 1
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to create thisRequest.")
var keyError: NSError? = nil
if let keyArray = self.managedObjectContext!.executeFetchRequest(thisRequest, error: &keyError) {
if keyArray.isEmpty {
myLedger = nil
} else {
if let thisLedger = keyArray[0] as? Ledgers {
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to find thisLedger.")
myLedger = thisLedger
} else {
myLedger = nil
}
}
}
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to link myLedger.")
我得到这样的记录时间:
DEBUG COMMENT: -9.20295715332031e-05 time to create thisRequest.
DEBUG COMMENT: -0.174275994300842 time to find thisLedger.
DEBUG COMMENT: -0.174659013748169 time to link myLedger.
DEBUG COMMENT: -0.00464397668838501 time to find and link myAccount.
0.092 毫秒创建 NSFetchRequest 就可以了。 174 毫秒找到账本?当有 24k 分类帐时在索引 UUID 字符串上?!?我什么时候需要 link 这到 57k 期刊?
越快越好。当有 549 个帐户时,需要 4 毫秒才能找到 link myAccount,这有点令人失望,但可以接受。对于 Ledger 搜索,我预计大约需要 25-50 毫秒,而不是 174!
我运行在它自己的核心数据存储和上下文中使用它:
// Initialize the persistent store coordinator for the sync session.
let url = appDel.applicationDocumentsDirectory.URLByAppendingPathComponent("FoodyCoreModel.sqlite")
self.syncStore = NSPersistentStoreCoordinator(managedObjectModel: appDel.managedObjectModel)
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
let storeOptions: [NSObject: AnyObject] = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
self.syncStore.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: storeOptions, error: &error)
// Initialize the managed object contextfor the sync session
self.syncContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
self.syncContext.persistentStoreCoordinator = self.syncStore
let nmp = NSMergePolicy(mergeType: NSMergePolicyType.MergeByPropertyStoreTrumpMergePolicyType)
self.syncContext.mergePolicy = nmp
iPhone 5S 的这种性能是否合理?我在这里阅读了很多关于 Core Data 性能的问题,但其中很多都是几年前的事了。我希望 iOS 8 和更新的设备会明显更快。我不是在尝试进行 MATCHES 或 CONTAINS 搜索,只是在索引文本字段上进行 EQUALS!
我已阅读 Core Data Performance Guide。是我遗漏了什么还是我对移动设备的期望太高了?
您的代码最有可能变慢的原因是您一次获取 Ledger
个实例,而您说其中有 24,000 个。无论如何,这将是一个主要瓶颈。提取是一项相对昂贵的操作,无论您是否在谓词中使用字符串 ID,因此您的代码将花费大部分时间进行提取。
您应该分批提取而不是一次提取一个。将 50 或 100 个左右的 uuidKey
值收集到一个数组中,并使用像 "uuidKey in %@"
这样的谓词格式,并将数组作为替换变量。处理该批次,并重复直到完成。
有关如何高效导入数据的更多详细信息,请参阅 Apple 的 "Efficiently Importing Data" 指南,尤其是名为 "Implementing Find-or-Create Efficiently" 的部分。
顺便说一句,像这样使用 println
是衡量性能的一种非常糟糕的方法。使用仪器。它会以更少的开销为您提供更多详细信息,并且不会弄乱您的代码,并将帮助您准确确定瓶颈所在。