19

NSFetchRequest をプログラムで作成するのと比較して、フェッチ リクエスト テンプレートを作成することでパフォーマンスが向上するかどうか興味があったので、これを測定するためのテストをいくつか書きました。これが github のソースです。

シミュレーターと iPhone での同じ順序の違い (一連のフェッチを実行する時間間隔を測定):

just creating an NSFetchRequest:          4.399674
creating a Fetch Request Template:        0.501369
NSFetchRequest with field indexed:        0.407068
Fetch Request Template and field indexed: 0.281876

Fetch Request Template を作成すると、約 7 ~ 9 倍のパフォーマンスが向上することがわかりました。下に適切なインデックスを作成しているのかもしれませんが、インデックス付きフィールドに一致するフェッチ リクエスト テンプレートを作成すると、さらにパフォーマンスが向上します。

これが事実であることを知ってうれしいですが、パフォーマンスの向上を説明するフェッチリクエストテンプレートの下で一体何が起こっているのか知りたいですか?

4

2 に答える 2

8

アップデート

[NSPredicate predicateWithFormat:]Instruments を使用してプロファイリングを行った結果、原因はここにあるわけではないことが判明しました。

パフォーマンスの違いの実際の原因は、ソート記述子です。

非テンプレート テストNSFetchedResultsControllerでは、ソート記述子が必要な が使用されていますが、テンプレート ベースのテストではソート記述子が指定されていません。

すべてのテストにソート記述子を追加すると、パフォーマンスは均一になります (インデックス付きのケースを除く)。


元の(間違った)答え

パフォーマンスが低下するのは、「NSFetchRequest を作成するだけ」のテストが[NSPredicate predicateWithFormat:]ループの反復ごとに呼び出されるためです。これは非常に遅いです。

考えてみてください -[NSPredicate predicateWithFormat:]文字列を解析し、基本的に Core Data で使用される内部表現にコンパイルする必要があります。

通常の解決策は、1 回だけ呼び出してから、述語によって比較される値を指定するために[NSPredicate predicateWithFormat:]使用することです。これについては、 Core Data Documentation - Efficiently Importing Dataで説明されています。[NSPredicate predicateWithSubstitutionVariables:]

書式設定された文字列から述語を作成するには、フレームワークは文字列を解析し、述語オブジェクトと式オブジェクトのインスタンスを作成する必要があります。同じ形式の述語を何度も使用していて、使用するたびにいずれかの定数値式の値を変更している場合は、述語を一度作成してから変数置換を使用する方が効率的です (「述語の作成」を参照)。

于 2012-07-02T12:38:51.367 に答える
1

ドキュメントから:

保存されたフェッチ要求には、変数置換用のプレースホルダーを含めることができるため、後で完了するためのテンプレートとして機能します。したがって、フェッチ リクエスト テンプレートを使用すると、実行時に置換される変数を使用してクエリを事前に定義できます。

また、NSManagedObjectModel Class Referenceの Stored Fetch Requests セクションも参照してください。

最大の利点は、クエリを実行時に構築する必要がないという事実から得られるように思われます。クエリは事前に構築されており、必要に応じて変数がクエリに代入されます。

于 2012-07-02T06:50:01.193 に答える