私は、疑似インテリジェント キャッシングをLINQ クエリ プロバイダーに組み込むことに取り組んでいます。私が(理想的には)やりたいことは、特定のクエリの式ツリーをいくつかのシナリオでキャッシュキーとして使用することです。ただし、オブジェクト グラフ全体を格納したくないので、式ツリーからハッシュサムのような値を取得する簡単な方法は何ですか? または、間違った方向に進んでいる場合、より良い選択肢はありますか?
3 に答える
これについて考えてみましょう。おそらく、マップに(式ツリーのハッシュ、結果)を格納したいとします。
ツリー全体を保存しないと、同一のツリーとハッシュ衝突を区別できません。
定義上、ハッシュは大きなセットを小さなセットにマップします(これがハッシュが役立つ理由です)。したがって、定義上、衝突が発生する可能性があります(少なくとも可能性があります)。
式ツリーを取得したら、それをハッシュしてから、マップで結果を検索します。これにより、次の2つの可能性が生まれます。
これはマップにないハッシュであり、これまでに見たことのないものです。結果がキャッシュされていないため、これを実行する必要があります。
これはマップ内のハッシュですが、ハッシュを生成した古い式ツリーをマップに保存していないため、新しく渡された式を古い式と比較する方法はありません。一致する場合もあれば、衝突する場合もありますが、これら2つの可能性を区別する方法はありません。衝突の可能性があるため、キャッシュされた結果を返すことはできません。
さらに、衝突ではなくても、最後に見たものとまったく同じ式ツリーであっても、データベース、リストなど、要素が追加されていないもの、または式によって返される結果がキャッシュされた結果と異なる可能性があるように削除または変更されましたか?
そうは言っても、ツリーを再帰的にハッシュすることができます。
hashATree:
if leaf node
return hash(node)
else
return hash(node) *OP* hashATree(left.child) *OP* hashATree(right.child)
ここで、OPは何らかの演算(おそらく乗算)、またはより一般的にはhash(node) *OP* accumulate( children.begin(), children.end(), *OP* );
もちろん、これは式ツリーを評価するために使用するのと同じ再帰です(私たちが呼び出すことを期待してくださいnode.eval( children);
)
おそらく、ここに示すコードを使用して実行できます。 http://petemontgomery.wordpress.com/2008/08/07/caching-the-results-of-linq-queries/
これは、閉鎖の問題を解決する方法を示し、ローカル コレクションもサポートします。
ええと、実際、これは非常に簡単かもしれないと思います。
ExpressionオブジェクトのToString()メソッドは、Expressionのテキスト表現を提供します。必要な場合は、キーの同等性を評価するだけであれば、それをハッシュできます。