編集:テストの実行方法に欠陥があるため、テストを変更しました。リストの代わりにIEnumerableを使用すると、流暢なnhibernateが結果をキャッシュしないのです
最近、Fluent Nhibernateのパフォーマンスに関する問題を抱えていましたが、私は非常に奇妙だと思ったものを見つけました。 IEnumerableを作成したとき、Listのパフォーマンスが大幅に向上しました。私はなぜそれを理解しようとしていた。それはすべきではないように見え、Googleは何も変えなかった。私は同じコードを取り、ちょうどラインにsomeRepository.GetABunchOfSomethingtoを変更し、(.ToListをappened場合
//Class has various built in type fields, but no references to anything
public class Something
{
public int ID;
public decimal Value;
}
var someRepository = new Repository(uow);
//RUN 1
var start = DateTime.Now;
// Returns a IEnumerable from a session.Linq<SomeAgg> based on the passed in parameters, nothing fancy. Has about 1300 rows that get returned.
var somethings = someRepository.GetABunchOfSomething(various, parameters);
var returnValue = SumAllFunction(somethings);
var timeSpent = DateTime.Now - start; //Takes {00:00:00.3580358} on my box
//RUN2
var start2 = DateTime.Now;
var returnValue = someFunction(somethings);
var timeSpent = DateTime.Now - start2; //Takes {00:00:00.0560000} on my box
public decimal SumAllFunction(IEnumerable<Something> somethings)
{
return somethings.Sum(x => x.Value); //Value is a decimal that's part of the Something class
}
)今:
ここで私が走った基本的なテストです他
//RUN 1
var start = DateTime.Now;
var somethings = someRepository.GetABunchOfSomething(various, parameters).ToList();
var returnValue = SumAllFunction(somethings);
var timeSpent = DateTime.Now - start; //Takes {00:00:00.3580358} on my box
//RUN 2
var start2 = DateTime.Now;
var returnValue = SumAllFunction(somethings);
var timeSpent = DateTime.Now - start2; //Takes {00:00:00.0010000} on my box
何も変更します。これらの結果は非常に繰り返し可能です。だから、それはただの問題ではありません。
TLDRのバージョンはこれです:二回ループを通して同じIEnumerableをを実行している場合
セカンドランが長く、私は.ToListを(使用してリストへのIEnumerableを変更する場合よりも10〜20時間どこからでもかかります) 2つのループを実行する前に
私はSQLをチェックし、それが一覧だときに、SQLは一度だけ実行して、かなりの結果を得るために戻ってデータベースに移動することよりも、再びキャッシュされ、使用されるように表示されます。
IEnumerableの場合、IEnumerableの子にアクセスするたびに、それらを再水和するためにデータベースにアクセスします。
IEnumerableに追加/削除できないことを理解していますが、IEnumerableが最初にプロキシオブジェクトで満たされ、その後必要に応じてプロキシオブジェクトが後で水分補給されていることを理解しました。彼らが水和した後、再びDBに戻る必要はありませんが、それはそうではないようです。私は明らかにこれを回避しようとしていますが、それは奇妙だと思っていました。
実行されるSQL文をプロファイルできますか? – empi
'someFunction'は何をしますか?コードを表示できますか? (あなたの2つのコードを比較するのは簡単だと思いますか?もしあなたが "その行を....に置き換えたら"と書いていれば分かりやすいでしょうか?) –
@ L.B。 someFunctionが表示され、コードの最後の3行です。 2番目のコードブロックを変更して、何が変更されたかをより正確に示すようにしました。 empi:私はSqlプロファイルを取得し、質問を更新しようとします。 – Zipper