我有一个循环,随着它的进行性能下降(第一个循环可能是3秒,最后一个可能是500次迭代400)。我把它缩小了一行代码。 。 。将唯一的NSNumber值附加到核心数据对象。目录大小通常为20K-150K。
以下是在外循环中运行的摘录。由于一行代码,外部循环每次都变得越来越慢:
for(int i = 0 ; i < 500 ; i++){
NSString *key = @"somerandomstring" ;
NSNumber* sampleIdNumber = [NSNumber numberWithInt:13] ;
for (it = catalog.begin(); it != catalog.end(); it++) {
// it->second->id changes each time in the inner-loop
NSNumber* tagNumber = [NSNumber numberWithInt:it->second->id];
DatumMO *newDatumMO = [NSEntityDescription insertNewObjectForEntityForName:@"Datum" inManagedObjectContext:moc];
// **TagNumber changes each inner loop**
// **Each time outer loop is calculated it gets slower**
// **This does not happen if tagNumber is constant**
newDatumMO.tagId = tagNumber ;
newDatumMO.name = key;
newDatumMO.sampleId = sampleIdNumber;
}
}
其他几点:ARC代码,autoreleasepool在循环周围定义,但没有任何区别。 'tagId'和'sampleId'都是我的核心数据数据模型中的Integer32。
到目前为止我尝试过的事情: - 将tagId重新定义为int32_t(无变化) - 使用STL映射预定义NSNumber *并进行查找(无更改) - 分配tagId常量(修复问题,但不对) - 分配一个随机的int tagId(当然,让它变得更糟)
这似乎很接近,但目前还不清楚这是否是实际问题,或者目前这是处理核心数据中标量的最佳做法。
http://blog.lorentey.hu/2010/10/31/core-data-scalars/
更新1 我实现了上面链接中描述的标量模型,行为没有变化。要对它进行进一步的仪器操作。 CPU变得饥饿(最初被挂起)并且内存是恒定的,因此要么将内容交换/加载到内存中,要么超出需要,或者写入核心数据会使内存减速。调整核心数据写入频率在这种效果上没有差别(尽管明显影响性能)。删除autoreleasepool调用也会在此过程中产生明显的效果。接下来尝试切换到使用NSString *,因为我没有想法。
答案 0 :(得分:0)
Duh,DatumMO.tagId是一个索引列(与sampleId一样)。显然,如果我创建了100K唯一的索引插入,随着插入数量的增加,似乎会导致显着的减速(必须在某处进行线性扫描?)。不确定它是否会提供足够的加速或者需要进行后加载索引,自定义或其他方式,但这是另一个问题。