使用UUID的现代核心数据性能

时间:2015-04-07 11:01:43

标签: ios iphone swift core-data uuid

我有一个核心数据应用程序:

  • 549具有myJournals关系的帐户实体(一对多)
  • 24000具有myJournals关系的分类帐实体(一对多)
  • 57000与myAccount和myLedger(一对一)反向的日记实体 关系

每个实体都有一个uuidKey字符串属性,其中包含从在线数据库导入的UUID字符串。

我正在尝试在iPhone 5S上运行该应用程序。插入对象的速度相对较快,但查找和链接关系的时间比预期的要长。

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.

创建NSFetchRequest的0.092毫秒很好。 174毫秒找到Ledger?在有24k Ledgers的索引UUID字符串上?!?当我需要将其链接到57k期刊时?

更快更好。 4,5毫秒查找链接myAccount当有549个帐户时略微令人失望但可以接受。对于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的性能是否合理?我在这里阅读了很多核心数据性能问题,但其中很多都是几年前的。我希望iOS 8和更新的设备速度要快得多。我不打算在索引文本字段上进行匹配或包含搜索,只是EQUALS!

我已阅读Core Data Performance Guide。有什么我想念的东西,或者我只是期望从移动设备上得到太多东西?

1 个答案:

答案 0 :(得分:4)

您的代码中最可能的减速是您一次获取一个Ledger个实例,并且您说其中有24,000个实例。无论如何,这将是一个主要的瓶颈。无论您是否在谓词中使用字符串ID,获取都是一项相对昂贵的操作,因此您的代码将花费大部分时间来获取。

您应该分批提取而不是一次提取。将50或100左右的uuidKey值收集到一个数组中,并使用类似"uuidKey in %@"的谓词格式,并将数组作为替换变量。处理批处理,并重复完成。

有关如何有效导入数据的更多详细信息,请参阅Apple的"Efficiently Importing Data"指南,尤其是“有效实现查找或创建”一节。

顺便说一句,使用这样的println是衡量效果的一种非常糟糕的方法。使用仪器。它会以更少的开销为您提供更多细节,并且不会使代码混乱,并且可以帮助您确定瓶颈的确切位置。