3

いくつかのテーブルビューを強化する一連の NSFetchedResultsControllers があり、デバイスでのパフォーマンスは数秒程度でひどいものでした。すべてがメイン スレッドで実行されるため、起動時にアプリがブロックされます。これは良くありません。

私が調査したところ、述語が問題であることがわかりました。

NSPredicate *somePredicate = [NSPredicate predicateWithFormat:@"ANY somethings == %@", something];
[fetchRequest setPredicate:somePredicate];

つまり、フェッチエンティティは、それを「もの」と呼び、エンティティ「何か」と多対多の関係を持っています。この述語は、特定の「何か」と関係があるものだけに結果を制限するフィルターです。

テストのために述語を削除すると、フェッチ時間 (最初の performFetch: 呼び出し) が (極端なケースでは) 4 秒から約 100 ミリ秒以下に減少しました。これは許容範囲です。ただし、Core Data と NSFRC を使用して得ることを望んでいた多くの利点が無効になるため、これには悩まされています。

それで、私の質問は、どうすればこのパフォーマンスを最適化できるでしょうか? 述語を間違って使用していますか? モデル/スキーマを何らかの方法で変更する必要がありますか? そして、これを修正する他の方法は何ですか?この種のパフォーマンスの低下は予想されますか? (1KB 未満のオブジェクトが数百個あります。)

詳細を編集:

コードは次のとおりです。

[fetchRequest setFetchLimit:200];
NSLog(@"before fetch");
BOOL success = [frc performFetch:&error];
if (!success) {
    NSLog(@"Fetch request error: %@", error);
}
NSLog(@"after fetch");

更新されたログ (以前は、ここでパフォーマンスを低下させるいくつかのアプリケーションの非効率性がありました。これらは、現在の環境で取得できる限り最適に近い更新されたログです):

2010-02-05 12:45:22.138 Special Ppl[429:207] before fetch
2010-02-05 12:45:22.144 Special Ppl[429:207] CoreData: sql: SELECT DISTINCT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 LEFT OUTER JOIN Z_1THINGS t1 ON t0.Z_PK = t1.Z_2THINGS WHERE  t1.Z_1SOMETHINGS = ? ORDER BY t0.ZID DESC LIMIT 200
2010-02-05 12:45:22.663 Special Ppl[429:207] CoreData: annotation: sql connection fetch time: 0.5094s
2010-02-05 12:45:22.668 Special Ppl[429:207] CoreData: annotation: total fetch execution time: 0.5240s for 198 rows.
2010-02-05 12:45:22.706 Special Ppl[429:207] after fetch

述語なしで同じフェッチを行う場合 (質問の冒頭にある 2 行をコメントアウトすることにより):

2010-02-05 12:44:10.398 Special Ppl[414:207] before fetch
2010-02-05 12:44:10.405 Special Ppl[414:207] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 ORDER BY t0.ZID DESC LIMIT 200
2010-02-05 12:44:10.426 Special Ppl[414:207] CoreData: annotation: sql connection fetch time: 0.0125s
2010-02-05 12:44:10.431 Special Ppl[414:207] CoreData: annotation: total fetch execution time: 0.0262s for 200 rows.
2010-02-05 12:44:10.457 Special Ppl[414:207] after fetch

20倍のタイム差。500ミリ秒はそれほど大きくはありません.バックグラウンドスレッドでそれを行う方法や、私が考えることができる最適化する方法はないようです. (これが問題にならないバイナリ ストアに行くことは別として、私はそうするかもしれません。バイナリ ストアのパフォーマンスは、200 を超えるオブジェクトの述語クエリで一貫して ~100 ミリ秒です。)

(以前にここに別の質問をネストしましたが、現在は移動しました)。

4

3 に答える 3

0

バイナリ ストーリーはデータ セット全体をメモリにロードするため、一部のデバイスでメモリの問題が発生します。代わりに、述語を書き直す必要があります。

あなたの関係は二面性があるので (そうですか?)、反対側からも関係を築くことができます。おそらくNSFetchedResultsController、この状況では はまったく必要ありません。あなたが持っていると仮定します:

MyWidgetEntity <--->> 何かエンティティ

すでにSomethingEntityのインスタンスへの参照を持っているので、次の方法でウィジェットを要求するだけです:

id widget = [mySomethingInstance valueForKey:@"widget"];

あなたが持っている状況では:

MyWidgetEntity <<-->> 何かエンティティ

次の方法で、関連するすべてのウィジェットにアクセスできます。

NSSet *widgets = [mySomethingInstance valueForKey:@"widgets"];

NSFetchedResultsControllerこのセットを配列に変換して並べ替えることができるため、必要ありません。

于 2010-03-31T16:46:50.003 に答える
0

私にとってこれに対する実際的な解決策は、パフォーマンスがはるかに優れた Core Data バイナリストアに切り替えることでした。現在のアプリの状況で Core Data SQLite のパフォーマンスを改善できるかどうかは調査していません。

于 2010-03-31T16:10:04.927 に答える