这样的过滤之间的性能(在任何一个方向上)都存在很大差异:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id,NSDictionary*)];
NSArray *filtered = [sourceArray filteredArrayUsingPredicate:predicate];
与此类过滤:
BOOL (^filterPredicate)(id,NSDictionary*) predicate = ^BOOL(id sourceObject, NSDictionary *bindings) {};
foreach (id sourceObject in sourceArray) {
if (filterPredicate(sourceObject)) {
filtered addObject:sourceObject;
}
}
我的直觉是,如果有任何差异,第二种方式会更快,因为第一种方式会有NSPredicate
级别的额外包袱。
如果存在差异,它是什么,它有多大,它的来源是什么?
答案 0 :(得分:3)
Per @ wain的建议我测试了一下。
我需要扩展测试以获得更准确的阅读,但这是我的方法和结果:
SomeObject
SomeObject
属性NSString rangeOfString
<强> SomeObject.h 强>
@interface SomeObject : NSObject
@property (nonatomic, strong) NSNumber *numericProperty;
@property (nonatomic, strong) NSString *stringProperty;
@property (nonatomic, strong) NSArray *arrayProperty;
@property (nonatomic, strong) NSDate *dateProperty;
@end
<强> ViewController.m 强>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *objectsToSort = [self generateArrayOfRandomSomeObject:1000];
// Sorting with predicate
BOOL (^predicateBlock)(id, NSDictionary *) = ^BOOL(id sourceObject, NSDictionary *bindings) {
SomeObject *destinationTypeObject = (SomeObject *)sourceObject;
if (sourceObject) {
NSRange r = [destinationTypeObject.stringProperty rangeOfString:@"ab" options:NSCaseInsensitiveSearch];
if (r.location != NSNotFound) {
return true;
} else {
return false;
}
}
return NO;
};
NSPredicate *predicate = [NSPredicate predicateWithBlock:predicateBlock];
NSDate *predicateMethodStart = [NSDate date];
NSArray *filteredWithPredicate = [objectsToSort filteredArrayUsingPredicate:predicate];
NSDate *predicateMethodFinish = [NSDate date];
NSTimeInterval predicateTime = [predicateMethodFinish timeIntervalSinceDate:predicateMethodStart];
NSLog(@"predicateTime = %f", predicateTime);
NSData *blockStart = [NSDate date];
NSMutableArray *filteredWithBlock = [NSMutableArray array];
for (id sourceObject in objectsToSort) {
if (predicateBlock(sourceObject, nil)) {
[filteredWithBlock addObject:sourceObject];
}
}
NSDate *blockFinish = [NSDate date];
NSTimeInterval blockTime = [blockFinish timeIntervalSinceDate:blockStart];
NSLog(@"blockTime = %f", blockTime);
}
- (NSArray *)generateArrayOfRandomSomeObject:(NSUInteger)numberOfObjects
{
NSMutableArray *objects = [[NSMutableArray alloc] initWithCapacity:numberOfObjects];
for (int count = 0; count < numberOfObjects; count++) {
SomeObject *object = [[SomeObject alloc] init];
int length = arc4random_uniform(10) + 4;
unichar buf[length];
for (int idx = 0; idx < length; idx++) {
buf[idx] = (unichar)('a' + arc4random_uniform(26));
}
object.stringProperty = [NSString stringWithCharacters:buf length:length];
u_int32_t max = ((u_int32_t)((u_int32_t)numberOfObjects * 10));
u_int32_t randomNumber = arc4random_uniform(max);
object.numericProperty = [NSNumber numberWithUnsignedInteger:randomNumber];
[objects addObject:object];
}
return objects;
}
@end
获胜者是...... NSPredicate
。为什么?我不知道。
2015-05-13 15:17:20.708 TestingPerformance[60942:5787881] predicateTime = 0.000768
2015-05-13 15:17:20.710 TestingPerformance[60942:5787881] blockTime = 0.000923
编辑0:原始代码出错并通过初始化适当大小的数组进行测试
不管怎样,尽管我在原始代码中输入了NSData *blockStart
,但它仍然有用!我修好了。
我初始化容量为1000的可变数组。
新结果:
2015-05-13 15:26:51.950 TestingPerformance[61157:5792057] predicateTime = 0.000771
2015-05-13 15:26:51.952 TestingPerformance[61157:5792057] blockTime = 0.000864
所以predicateTime
是一致的,blockTime
通过这种小调整得到改善。
编辑1:使用传统的for循环而不使用迭代器
for (int i = 0; i < objectsToSort.count; i++) {
if (predicateBlock(objectsToSort[i], nil)) {
[filteredWithBlock addObject:objectsToSort[i]];
}
}
2015-05-13 15:30:25.464 TestingPerformance[61282:5793520] predicateTime = 0.000775
2015-05-13 15:30:25.467 TestingPerformance[61282:5793520] blockTime = 0.001079
编辑2:增加N,添加随机数组访问
- (void)viewDidLoad {
[super viewDidLoad];
NSUInteger N = 100000;
NSArray *objectsToSort = [self generateArrayOfRandomSomeObject:N];
// Sorting with predicate
BOOL (^predicateBlock)(id, NSDictionary *) = ^BOOL(id sourceObject, NSDictionary *bindings) {
SomeObject *destinationTypeObject = (SomeObject *)sourceObject;
if (sourceObject) {
NSRange r = [destinationTypeObject.stringProperty rangeOfString:@"ab" options:NSCaseInsensitiveSearch];
if (r.location != NSNotFound) {
return true;
} else {
return false;
}
}
return NO;
};
NSPredicate *predicate = [NSPredicate predicateWithBlock:predicateBlock];
NSDate *predicateMethodStart = [NSDate date];
NSArray *filteredWithPredicate = [objectsToSort filteredArrayUsingPredicate:predicate];
NSDate *predicateMethodFinish = [NSDate date];
[self doStuffWithArray:filteredWithPredicate];
NSDate *predicateStuffFinish = [NSDate date];
NSDate *blockStart = [NSDate date];
NSMutableArray *filteredWithBlock = [NSMutableArray arrayWithCapacity:N];
for (id sourceObject in objectsToSort) {
if (predicateBlock(sourceObject, nil)) {
[filteredWithBlock addObject:sourceObject];
}
}
NSDate *blockFinish = [NSDate date];
[self doStuffWithArray:filteredWithBlock];
NSDate *blockDoStuffFinish = [NSDate date];
NSLog(@"predicateTime = %f", [predicateMethodFinish timeIntervalSinceDate:predicateMethodStart]);
NSLog(@"predicate time to do stuff = %f", [predicateStuffFinish timeIntervalSinceDate:predicateMethodFinish]);
NSLog(@"blockTime = %f", [blockFinish timeIntervalSinceDate:blockStart]);
NSLog(@"block time to do stuff = %f", [blockDoStuffFinish timeIntervalSinceDate:blockFinish]);
}
这是做事情
- (void)doStuffWithArray:(NSArray *)arrayOfSomeObjects {
NSLog(@"Filtered array has %lu objects.", (unsigned long)arrayOfSomeObjects.count);
NSUInteger numberOfSpotsToCheck = ((NSUInteger)(arrayOfSomeObjects.count / 4));
for (int i = 0; i < numberOfSpotsToCheck; i++) {
u_int32_t randomIndex = arc4random_uniform((u_int32_t)arrayOfSomeObjects.count);
SomeObject *o = (SomeObject *)[arrayOfSomeObjects objectAtIndex:randomIndex];
NSLog(@"Object at index: %d \n description is %@ \n stringProprerty is %@ \n numericProperty is %i",
i,
o,
o.stringProperty,
[o.numericProperty unsignedIntValue]);
}
}
在访问和过滤方面,阻止时间仍然有点慢。
2015-05-13 16:10:26.750 TestingPerformance[62201:5810268] predicateTime = 0.086866
2015-05-13 16:10:26.750 TestingPerformance[62201:5810268] predicate time to do stuff = 0.531776
2015-05-13 16:10:26.751 TestingPerformance[62201:5810268] blockTime = 0.107424
2015-05-13 16:10:26.751 TestingPerformance[62201:5810268] block time to do stuff = 0.684613