単語と手がかりのリストにアクセスするワードゲームアプリがあります。これは約10万エントリです。データベースはアクセスされるだけで、変更されることはありません。SQLメソッドを使用してアプリを構築しましたが、iOS 6ではかなりうまく機能しますが、データベースから新しい手がかりを取得する時間はiOS5では非常に遅くなります。
- iOS 5は、SQLを使用して100Kから1つのレコードを取得するのに、約12秒かかります。
- iOS 6は、SQLを使用して100Kから1つのレコードを取得するのに、約700〜1000ミリ秒かかります。
これらは両方とも32GBのiPodTouchに搭載されています。
このパフォーマンスを考慮して、CoreDataを使用してバージョンを作成しました。私のアプローチでは、最初にクエリに適合するレコードをカウントし、次にランダムに1つを選択することで、ランダムなデータベースエントリを取得します。コードは次のとおりです。私が読んだすべてのことは、コアデータがより高速になることを示唆していました:
- iOS 5では、レコードのカウントに約4秒かかり、それらのレコードの1つを取得するには約50〜1500ミリ秒かかります。合計時間は約5秒です。
- iOS 6では、レコードのカウントに2秒強かかり、それらのレコードの1つを取得するには約300〜500ミリ秒かかります。合計約3秒。
そのため、コアデータはiOS 5では高速ですが、iOS6ではSQLと比較して低速です。いずれにせよ、私に関する限り、パフォーマンスは遅すぎます。オーバーヘッドは以下に示すメソッドから発生することを知っています(Core Dataバージョンの場合)。したがって、2つの質問:
- この問題を理解し、パフォーマンスを向上させることを目的とした、この問題に関する一般的なアドバイスはありますか?
- 具体的には、以下に追加されているCore Dataコードについてはどうでしょうか。速度を落とすような愚かなことをしたことがありますか?または、スピードアップするために追加する必要があるものはありますか?これは、CoreDataでの私の最初の試みです。
ありがとう。
- (NSArray *) randomClue {
NSManagedObjectContext* context = [self managedObjectContext];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"A"];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"WL28"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [self createSearchQuery];
[fetchRequest setPredicate:predicate];
NSError *error;
NSDate *date1 = [NSDate date];
NSString *timeString1 = [formatter stringFromDate:date1];
int resCount = [context countForFetchRequest:fetchRequest
error:&error];
NSDate *date2 = [NSDate date];
NSString *timeString2 = [formatter stringFromDate:date2];
int t1 = [timeString1 intValue];
int t2 = [timeString2 intValue];
int d1 = t2-t1;
NSLog(@"randomClue:");
NSLog(@" Time to count array entries: %i", d1);
int ranNum = arc4random_uniform(resCount-1);
int ranNum2 = ranNum + 1;
// Now we fetch just one answer object, not a whole database or even a piece of it!
[fetchRequest setReturnsObjectsAsFaults:YES];
[fetchRequest setPropertiesToFetch:nil];
[fetchRequest setFetchLimit:1];
[fetchRequest setFetchOffset:ranNum2];
NSDate *date3 = [NSDate date];
NSString *timeString3 = [formatter stringFromDate:date3];
self.wl28 = [context executeFetchRequest:fetchRequest error:&error];
NSDate *date4 = [NSDate date];
NSString *timeString4 = [formatter stringFromDate:date4];
int t3 = [timeString3 intValue];
int t4 = [timeString4 intValue];
int d2 = t4-t3;
NSLog(@" Time to retrieve one entry: %i", d2);
return self.wl28;
}
編集:createSearchQueryを以下に追加
- (NSPredicate *)createSearchQuery {
NSMutableArray *pD = [[GameData gameData].curData valueForKey:@"persData"];
NSNumber *currMin = [pD objectAtIndex:0];
NSNumber *currMax = [pD objectAtIndex:1];
NSNumber *dicNo = [pD objectAtIndex:2];
NSString *dict = nil;
if ([dicNo intValue] == 0) dict = @"TWL";
if ([dicNo intValue] == 1) dict = @"LWL";
NSPredicate *dictPred = [NSPredicate predicateWithFormat:@"dict == %@", dict];
NSPredicate *lowNoCPred = [NSPredicate predicateWithFormat:@"noC >= %@", currMin];
NSPredicate *highNoCPred = [NSPredicate predicateWithFormat:@"noC <= %@", currMax];
NSPredicate *query = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray
arrayWithObjects:dictPred, lowNoCPred, highNoCPred,nil]];
NSLog(@"%@", query);
return query;
}