RestKit 性能和核心数据
Posted
技术标签:
【中文标题】RestKit 性能和核心数据【英文标题】:RestKit Performance and Core Data 【发布时间】:2013-08-01 23:26:38 【问题描述】:下载 9,000 个对象时,RestKit 的性能慢得令人无法接受——在模拟器上需要 10 分钟,而在 iPad Mini 上则需要无限时间。
我有几个表格要从一个安静的界面下载。这一切都有效,但是当有许多对象时,似乎存在一个无法容忍的指数级问题。下表问题最多:
optionMapping.identificationAttributes = @[@"optionID"];
// OptionType
RKEntityMapping *optionTypeMapping = [RKEntityMapping mappingForEntityForName:@"OptionType" inManagedObjectStore:rkMOS];
[optionTypeMapping addAttributeMappingsFromDictionary:@
@"id" : @"optionTypeID",
@"option_type" : @"optionType",];
optionTypeMapping.identificationAttributes = @[@"optionTypeID"];
属性 optionTypeID 在 Core Data 中被索引,并且不是可选的。
与其他表有一些关系,我映射如下:
// Option.optionType -> OptionType
[optionMapping addConnectionForRelationship:@"optionType" connectedBy: @"optionTypeID"];
// Option.unit -> Unit
[optionMapping addConnectionForRelationship:@"unit" connectedBy:@"unitID"];
这些似乎不是问题——我将它们注释掉了,下载仍然非常非常慢。
我设置了一个响应描述符(这是一个目录,所以我只需要下载它)。请注意,以下代码显示了所有表的设置。
NSArray *reqA = @[@@"endpoint" : API_VENDORS_ENDPOINT,
@"mapping" : vendorMapping,
@@"endpoint" : API_OPTION_TYPES_ENDPOINT,
@"mapping" : optionTypeMapping,
@@"endpoint" : API_OPTIONS_ENDPOINT,
@"mapping" : optionMapping,
@@"endpoint" : API_UNITS_ENDPOINT,
@"mapping" : unitMapping,
@@"endpoint" : API_PRICE_TIERS_ENDPOINT,
@"mapping" : priceTierMapping,
@@"endpoint" : API_PRODUCT_TYPES_ENDPOINT,
@"mapping" : productTypeMapping,
@@"endpoint" : API_PRODUCTS_ENDPOINT,
@"mapping" : productMapping
];
for (NSDictionary *mapD in reqA)
RKResponseDescriptor *thisRD = [RKResponseDescriptor
responseDescriptorWithMapping:[mapD valueForKey:@"mapping"]
pathPattern:[mapD valueForKey:@"endpoint"]
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[_objMgr addResponseDescriptor:thisRD];
我正在使用对象管理器下载表格:
[_objMgr getObjectsAtPath:verbStr
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
RKLogInfo(@"%@ load complete: %@", verbStr, [NSDate date]);
NSInteger idx = [loadA indexOfObject:verbStr] + 1;
if (idx < [loadA count])
[self load:[loadA objectAtIndex:idx] stack:loadA];
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:verbStr];
[[NSUserDefaults standardUserDefaults] synchronize];
NSDictionary *options = @@"verb" : verbStr;
[[NSNotificationCenter defaultCenter] postNotificationName:OBJECTS_DOWNLOADED object:self userInfo:options];
failure:^(RKObjectRequestOperation *operation, NSError *error)
RKLogError(@"Load failed with error: %@", error);
NSInteger statusCode = operation.HTTPRequestOperation.response.statusCode;
if (401 == statusCode)
[self resetAdmin];
];
控制台输出显示映射正在快速进行,但需要很长时间。以下只是成千上万的喜欢它的一个sn-p:
2013-08-01 17:11:49.319 CarpetDirect[138:1507] D restkit.object_mapping:RKMappingOperation.m:952 Starting mapping operation...
2013-08-01 17:11:49.321 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:953 Performing mapping operation: <RKMappingOperation 0x1dda2160> for 'Option' object. Mapping values from object
id = 1307;
"option_type" = 0;
unit = "<null>";
value = "939 Puddle";
to object <Option: 0x1dd55020> (entity: Option; id: 0x1dd55060 <x-coredata:///Option/t3ABD9C1C-1BBA-4C39-AEF7-EB3D1D9AFC0B1334> ; data:
optionID = 1307;
optionType = nil;
optionTypeID = 0;
orderedItems = (
);
products = (
);
unit = nil;
unitID = 0;
value = nil;
) with object mapping (null)
2013-08-01 17:11:49.324 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'id' to 'optionID'
2013-08-01 17:11:49.326 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:583 Skipped mapping of attribute value from keyPath 'id to keyPath 'optionID' -- value is unchanged (1307)
2013-08-01 17:11:49.329 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'unit' to 'unitID'
2013-08-01 17:11:49.333 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:431 Found transformable value at keyPath 'unit'. Transforming from type 'NSNull' to 'NSNumber'
2013-08-01 17:11:49.334 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:572 Mapped attribute value from keyPath 'unit' to 'unitID'. Value: (null)
2013-08-01 17:11:49.336 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'value' to 'value'
2013-08-01 17:11:49.338 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:572 Mapped attribute value from keyPath 'value' to 'value'. Value: 939 Puddle
2013-08-01 17:11:49.339 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'option_type' to 'optionTypeID'
2013-08-01 17:11:49.342 CarpetDirect[138:1507] T restkit.object_mapping:RKMappingOperation.m:583 Skipped mapping of attribute value from keyPath 'option_type to keyPath 'optionTypeID' -- value is unchanged (0)
2013-08-01 17:11:49.345 CarpetDirect[138:1507] D restkit.object_mapping:RKMappingOperation.m:1021 Finished mapping operation successfully...
2013-08-01 17:11:49.348 CarpetDirect[138:1507]
关于如何加快速度的任何想法?我要做的就是将数据从服务器下载到核心数据。
【问题讨论】:
那 9000 个是单独的请求吗?如果是这样,那就是每分钟 900 次,每秒 15 次,可能不会变得更快。 这是对服务器的一次请求。 json 很快就回来了,所以这不是问题。问题在于 RestKit 将数据倒入 Core Data 所需的时间。 我弄乱了第一个代码 sn-p。应该是:RKEntityMapping *optionMapping = [RKEntityMapping mappingForEntityForName:@"Option" inManagedObjectStore:rkMOS]; [optionMapping addAttributeMappingsFromDictionary:@@"id":@"optionID",@"option_type":@"optionTypeID",@"unit":@"unitID",@"value":@"value"]; optionMapping.identificationAttributes = @[@"optionID"]; 从 Restkit 0.10.3 升级后我遇到了同样的问题。基本上完全相同的设置:导入一个大的 JSON 文件,它需要非常长的时间才能完成,或者永远不会完成。你找到这个问题的答案了吗?读完这篇文章后,我可能最终会恢复或滚动我自己的导入器:hamishrickerby.com/2012/06/04/… 我不确定这是否与核心数据相关,但一般而言,数据库和 OM 的一个问题是批量处理大量数据几乎总是呈指数级减慢。如果可能的话,如果可能的话,尝试每隔几百条记录将结果提交到数据库(或者核心数据中的任何术语)。这允许框架清除内存并为新对象腾出空间。 【参考方案1】:没有更多上下文很难说,但是您的 RestKit 日志记录选项是什么?根据我的经验,RestKit 中的映射日志记录非常冗长,将速度减慢了 10 倍。
禁用所有 RestKit 日志记录,看看是否有任何改进。然后,如果仍然存在问题,请使用 Instruments 来分析您的应用程序 - 您应该可以轻松查看大部分时间占用哪些代码路径(解析、RestKit 映射、Core Data 等)
【讨论】:
日志记录确实是 RestKit 的一个问题,性能方面。好提示!以上是关于RestKit 性能和核心数据的主要内容,如果未能解决你的问题,请参考以下文章