Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 哪个具有更快的ObjectsPassingTest或filteredArrayUsingPredicate性能指标?_Ios_Objective C_Nsarray_Filtering_Performance Testing - Fatal编程技术网

Ios 哪个具有更快的ObjectsPassingTest或filteredArrayUsingPredicate性能指标?

Ios 哪个具有更快的ObjectsPassingTest或filteredArrayUsingPredicate性能指标?,ios,objective-c,nsarray,filtering,performance-testing,Ios,Objective C,Nsarray,Filtering,Performance Testing,当需要过滤NSArray以获取返回的数组中的项目子集时,哪种方法更频繁且在边缘情况下更快?以下测试(在发布模式下编译,在Mac Pro上执行)表明 filteredarrayingpredicate比indexesOfObjectsPassingTest慢,如果您使用 “文本”谓词,但如果使用基于块的谓词,则速度更快。 在我的测试中,fasted方法是一个简单的(快速枚举)循环,它添加所有匹配项 对象到可变数组 筛选10000000个字典数组的结果,其中约50%匹配谓词: 8.514334 (p

当需要过滤NSArray以获取返回的数组中的项目子集时,哪种方法更频繁且在边缘情况下更快?

以下测试(在发布模式下编译,在Mac Pro上执行)表明
filteredarrayingpredicate
indexesOfObjectsPassingTest
慢,如果您使用 “文本”谓词,但如果使用基于块的谓词,则速度更快。 在我的测试中,fasted方法是一个简单的(快速枚举)循环,它添加所有匹配项 对象到可变数组

筛选10000000个字典数组的结果,其中约50%匹配谓词:

8.514334 (predicateWithFormat) 4.422550 (predicateWithBlock) 5.170086 (indexesOfObjectsPassingTest) 3.154015 (fast-enumeration + mutable array) 8.514334(谓词格式) 4.422550(预测块) 5.170086(对象分配测试的指标) 3.154015(快速枚举+可变数组) 当然,其他谓词的结果可能不同

#import <Foundation/Foundation.h>

NSUInteger filter1(NSArray *a)
{
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"num > 1000 AND foo == 'bar'"];
    NSArray *filtered = [a filteredArrayUsingPredicate:pred];
    return [filtered count];
}

NSUInteger filter2(NSArray *a)
{
    NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *obj, NSDictionary *bindings) {
        return ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]);
    }];
    NSArray *filtered = [a filteredArrayUsingPredicate:pred];
    return [filtered count];
}

NSUInteger filter3(NSArray *a)
{
    NSIndexSet *matching = [a indexesOfObjectsPassingTest:^BOOL(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
        return ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]);
    }];
    NSArray *filtered = [a objectsAtIndexes:matching];
    return [filtered count];
}

NSUInteger filter4(NSArray *a)
{
    NSMutableArray *filtered = [NSMutableArray array];
    for (NSDictionary *obj in a) {
        if ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]) {
            [filtered addObject:obj];
        }
    }
    return [filtered count];
}

void testmethod(NSArray *a, NSUInteger(*method)(NSArray *a))
{
    @autoreleasepool {
        NSDate *t1 = [NSDate date];
        NSUInteger count = method(a);
        NSDate *t2 = [NSDate date];
        NSLog(@"%f", [t2 timeIntervalSinceDate:t1]);
    }
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSMutableArray *a = [NSMutableArray array];
        for (int i = 0; i < 10000000; i++) {
            [a addObject:@{@"num": @(arc4random_uniform(2000)), @"foo":@"bar"}];
        }
        testmethod(a, filter1);
        testmethod(a, filter2);
        testmethod(a, filter3);
        testmethod(a, filter4);
    }
    return 0;
}
#导入
NSU整数过滤器1(NSArray*a)
{
NSPredicate*pred=[NSPredicate PREDITEWITHFORMAT:@“num>1000,foo=='bar'”;
NSArray*filtered=[a filteredArrayUsingPredicate:pred];
返回[过滤计数];
}
NSU整数过滤器2(NSArray*a)
{
NSPredicate*pred=[NSPredicate谓词WithBlock:^BOOL(NSDictionary*obj,NSDictionary*绑定){
返回([obj[@“num”]intValue]>1000&[obj[@“foo”]IsequalString:@“bar”);
}];
NSArray*filtered=[a filteredArrayUsingPredicate:pred];
返回[过滤计数];
}
NSU整数过滤器3(NSArray*a)
{
NSIndexSet*matching=[a indexesOfObjectsPassingTest:^BOOL(NSDictionary*obj,NSU整数idx,BOOL*stop){
返回([obj[@“num”]intValue]>1000&[obj[@“foo”]IsequalString:@“bar”);
}];
NSArray*filtered=[a objectsAtIndexes:matching];
返回[过滤计数];
}
NSU整数过滤器4(NSArray*a)
{
NSMutableArray*已筛选=[NSMutableArray];
用于(a中的NSDictionary*obj){
如果([obj[@“num”]intValue]>1000&&[obj[@“foo”]IsequalString:@“bar”]){
[过滤的addObject:obj];
}
}
返回[过滤计数];
}
void testmethod(NSArray*a,NSUInteger(*方法)(NSArray*a))
{
@自动释放池{
NSDate*t1=[NSDate日期];
NSU整数计数=方法(a);
NSDate*t2=[NSDate日期];
NSLog(@“%f”,[t2时间间隔起始日期:t1]);
}
}
int main(int argc,const char*argv[]
{
@自动释放池{
NSMutableArray*a=[NSMutableArray];
对于(int i=0;i<10000000;i++){
[a addObject:@{@“num”:@(arc4random_uniform(2000)),@“foo”:@“bar}];
}
测试方法(a,过滤器1);
测试方法(a,过滤器2);
试验方法(a,过滤器3);
试验方法(a,过滤器4);
}
返回0;
}

我用全新的Xcode 6性能测试(Objective-C)和下面的测试用例测试了这个问题。我得到了以下结果,表明带有标志
NSEnumerationConcurrent
的enumerationBlock是大型数组的最快过滤方法:

testPerformancePredicateWithFormat - measured [Time, seconds] average: 0.189
testPerformancePredicateWithBlock - measured [Time, seconds] average: 0.093
testPerformanceEnumerationBlock - measured [Time, seconds] average: 0.092
testPerformanceIndexesOfObjectsPassingTest - measured [Time, seconds] average: 0.082
testPerformanceFastEnumeration - measured [Time, seconds] average: 0.068
testPerformanceEnumerationConcurrent - measured [Time, seconds] average: 0.036
以下是测试:

#import <XCTest/XCTest.h>

@interface TestPMTests : XCTestCase
@property(nonatomic, copy)NSArray *largeListOfDictionaries;
@end

@implementation TestPMTests

- (void)setUp {
    [super setUp];

    self.largeListOfDictionaries = [NSMutableArray array];

    // Initialize a large array with ~ 300.000 entries as Dictionaries of at least one key value pair {"id":"<any id>"}
}

- (void)testPerformancePredicateWithFormat {
    NSString *ID = @"204440e5-4069-48e8-a405-88882a5ba27e";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF.id == %@", ID];

    [self measureBlock:^{
        NSArray *filtered = [self.largeListOfDictionaries filteredArrayUsingPredicate:pred];
        NSLog(@"Count: %d", filtered.count);
    }];
}

- (void)testPerformancePredicateWithBlock {
    NSString *ID = @"204440e5-4069-48e8-a405-88882a5ba27e";
    NSString *kID = @"id";
    NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *d, NSDictionary *bindings) {
        return [d[kID] isEqualToString:ID];
    }];

    [self measureBlock:^{
        NSArray *filtered = [self.largeListOfDictionaries filteredArrayUsingPredicate:pred];
        NSLog(@"Count: %d", filtered.count);
    }];
}

- (void)testPerformanceIndexesOfObjectsPassingTest {
    NSString *ID = @"204440e5-4069-48e8-a405-88882a5ba27e";
    NSString *kID = @"id";

    [self measureBlock:^{
        NSIndexSet *matchingIndexes = [self.largeListOfDictionaries indexesOfObjectsPassingTest:^BOOL(NSDictionary *d, NSUInteger idx, BOOL *stop) {
            return [d[kID] isEqualToString:ID];
        }];
        NSArray *filtered = [self.largeListOfDictionaries objectsAtIndexes:matchingIndexes];
        NSLog(@"Count: %d", filtered.count);
    }];
}

- (void)testPerformanceFastEnumeration {
    NSString *ID = @"204440e5-4069-48e8-a405-88882a5ba27e";
    NSString *kID = @"id";

    [self measureBlock:^{
        NSMutableArray *filtered = [NSMutableArray array];
        for (NSDictionary *d in self.largeListOfDictionaries) {
            if ([d[kID] isEqualToString:ID]) {
                [filtered addObject:d];
            }
        }
        NSLog(@"Count: %d", filtered.count);
    }];
}

- (void)testPerformanceEnumerationBlock {
    NSString *ID = @"204440e5-4069-48e8-a405-88882a5ba27e";
    NSString *kID = @"id";

    [self measureBlock:^{
        NSMutableArray *filtered = [NSMutableArray array];
        [self.largeListOfDictionaries enumerateObjectsUsingBlock:^(NSDictionary *d, NSUInteger idx, BOOL *stop) {
            if ([d[kID] isEqualToString:ID]) {
                [filtered addObject:d];
            }
        }];
        NSLog(@"Count: %d", filtered.count);
    }];
}

- (void)testPerformanceEnumerationConcurrent {
    NSString *ID = @"204440e5-4069-48e8-a405-88882a5ba27e";
    NSString *kID = @"id";

    [self measureBlock:^{
        NSMutableArray *filtered = [NSMutableArray array];
        [self.largeListOfDictionaries enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSDictionary *d, NSUInteger idx, BOOL *stop) {
            if ([d[kID] isEqualToString:ID]) {
                [filtered addObject:d];
            }
        }];
        NSLog(@"Count: %d", filtered.count);
    }];
}  
而并发版本的结果比所有其他测试都要好

-[TestPMTests testPerformancePredicateWithFormat average: 0.134
-[TestPMTests testPerformancePredicateWithBlock] average: 0.079
-[TestPMTests testPerformanceEnumerationBlock] average: 0.079
-[TestPMTests testPerformanceIndexesOfObjectsPassingTest] average: 0.068
-[TestPMTests testPerformanceFastEnumeration] average: 0.054
-[TestPMTests testPerformanceEnumerationConcurrent] average: 0.029

第一:配置文件(使用仪器)会告诉你区别。但老实说,如果在这种情况下,性能对你的应用程序至关重要,那么你很可能使用了错误的方法。Objective-C本身、NSPredicates、NSString比较和更多惯用的Objective-C实现都不是真正的“快”(如果您需要的话)。即使我们为您(或您自己)进行测量,您的问题的答案也将取决于您计划对结果做什么。e、 g.每次循环调用
-indexesOfObjectsPassingTest:
调用
-objectAtIndex:
返回的
NSIndexSet
的内容可能不是最有效的方法。您可以尝试使用选项:NSEnumerationConcurrent passingTest:的IndexesofObjects,通过使用多个好的建议。我已经这样做了,有趣的是,
对象索引选项:NSEnumerationConcurrent
比非并发版本慢30%(在我的4核Intel Core i5 iMac上)。仪器显示,所有工作线程都在
OSSpinLockSlow
中花费了大量时间(这是保护对结果索引集的访问所必需的)。我使用对象的
索引选项进行了测试:NSEnumerationConcurrent
,在我的情况下,它甚至比使用快速枚举的测试稍微快一点。由于即使使用并发版本,结果索引也已排序,因此应将其用作选择的筛选方法使用Xcode 6.2 beta 3(6C101)和@blackjacx:Strange进行测试。我再次测试了代码,在我的
filter3()
函数中将
indexesOfObjectsPassingTest:
替换为
indexesOfObjectsWithOptions:NSEnumerationConcurrent passingTest:
,这会让它慢很多。嗯,是的,这真的很奇怪。您可以使用我的代码进行测试。请注意,
NSMutableArray
不是线程安全的。因此,从多个线程添加对象(如
testPerformanceEnumerationConcurrent
方法)可能会导致错误的结果或崩溃。您必须使用一些锁定来保护可变数组,防止来自不同线程的同时访问,这会使事情再次变得缓慢。比较一下我上面的评论。我自己查了一下,找到了你的评论马丁。要点很好。
testPerformanceEnumerationConcurrent
确实使我的应用程序崩溃,导致非线程安全,如果我使用锁定和解锁,那么性能与
testPerformancePredicateWithFormat
相同,我使用
TestPerformanceEnumeration
-[TestPMTests testPerformancePredicateWithFormat average: 0.134
-[TestPMTests testPerformancePredicateWithBlock] average: 0.079
-[TestPMTests testPerformanceEnumerationBlock] average: 0.079
-[TestPMTests testPerformanceIndexesOfObjectsPassingTest] average: 0.068
-[TestPMTests testPerformanceFastEnumeration] average: 0.054
-[TestPMTests testPerformanceEnumerationConcurrent] average: 0.029