同じプロセスを実行し、パフォーマンステストを行う際に、新しいプロジェクトの会社とは奇妙な問題を発見した48コア(HP580 G7のPCサーバ)サーバ120秒、4コアのPC内に取りボードに限り、90秒として、この質問で、同社はこの問題を解決するには、Microsoftのエンジニアを雇いました。
一日を過ごした後は、デバッグと最適化をトレースし、時間のかかる70秒に、プロセスは、いくつかの最適化の.NETオブジェクトを含み、実際の効果は明らかです。この記事では、段階的なノートの結論であるだけでなく、非常に有益。
、DataView.ToTableパフォーマンスの問題()の後に
エンジニアはこの方法に対処するための時間は、トラッキングコードで非常に遅い見つけ、コードの全体ロジック時間のほとんどを占めています。この方法では、効果は明らかである最適化されています。
MSDNを確認し、関係者は、パフォーマンス上のDataView.ToTable()メソッドのヒントを与えていないが、あなたはMSDNを見てみたい、この方法では、発見した外国人は3通りの方法でこれを実行するには、以下のコードに戻ってきた2006年でこの方法は、効率性に大きな違いを発見しました。(MSDN:DataView.ToTable () )。
私たちは本当に問題を再現することができ、新しいプロジェクトを作成し、コードをコピーしました。次のように全体のプロセスは、おそらく次のとおりです。
背景は、データワードが、このデータテーブルデータビューに転送される50万データテーブルデータ、があり、その後Totableによってこのデータビューから()メソッドは、データを別のデータテーブル同じアーキテクチャに転送されます。
ターゲットデータテーブルオブジェクトを作成するための最初の方法は、直接()メソッドはtoTableによって変換します。プロセスは取っ:27.0504秒。
第二の目標DATATABLE方法を作成した後、それは主キーを設定します。データは、次のコードによって、ターゲットテーブルに加えました。
foreachの(ds.TablesでのDataRow DR [0] .Rows)
{
DataRow [] drrepetido = dsRes.Tables [0] .Select( "勇気=" + DR [ "勇気"])。
もし(drrepetido.Length == 0)
dsRes.Tables [0] .ImportRow(DR)。
}
プロセスは取っ:11.7624秒。
第3の実施形態は、元のターゲットデータテーブルアーキテクチャ、データテーブルオブジェクトの新しいインスタンスを作成し、対応する列を追加し、次のように、ハッシュ表、ターゲット表書き込みサイクルを作成できません。
DataTable dtを=新しいのDataTable();
dt.Columns.Add( "勇気"、ds.Tables [0] .Columns [ "勇気"]データ型。)
HashtableのHT =新しいHashtableの();
foreachの(ds.TablesでのDataRow DR [0] .Rows)
{
(もし!ht.ContainsKey(DR [0]))
{
ht.Add(DR [0]、NULL);
DataRow newRow = dt.NewRow()。
newRow [0] = DR [0]。
dt.Rows.Add(newRow)。
}
}
プロセスがかかった:0.2184秒。
三つの方法のコントラストは、非常に怖いました。しかし、Microsoftは、与えられた理由がないように思われます。
二、StringBuilderの()パフォーマンスの問題は、ファイルによって引き起こされていません
StringBuilderのも多くの記事を読む程度前にした後、問題の開発者プログラムと前回同様に、GCのStringBuilderオブジェクトが処理され続ける)(ループ本体続けるにappandで、その結果、より多くの推奨インスタンス化する長さの値を設定していません。これは多くの時間を消費します。
それのよりのStringBuilder()オブジェクト、またはいくつかの単語について、その後。デフォルト値は16容量維持です。
StringBuilderのコストが大きなオブジェクトを作成するので、文字列連結少ないターゲットの場合には、過度の虐待は、無駄のStringBuilderのパフォーマンスではなく、節約になることができます。だけのStringBuilderに検討する前に、予測不可能な数値や文字列操作の多くは、実現しています。文字列型「+」作動接続、実際にオーバーロード演算子「+」はString.Concatが操作呼び出し、コンパイラは、コンパイラ渡される引数の数に応じて、そのような接続処理の動作を最適化します時間割り当ては、メモリに対応し、順次コピーに対応する文字列。使用中のStringBuilder起因デフォルトのメモリ割り当て、頻繁操作の容量不足に別段の指定が最適な容量値は、不適切な実装です。通常の状況下では、単純な文字列の連結、および接続文字列を完了するために、好みString.Concat String.Join他の操作で使用する必要がありますが、String.Concatボクシングの動作を監視することが可能となります。
第三に、パフォーマンスの問題を持って来るために私を可能にします
StringBuilder.toStringは()。トリム場合()かどうかがStringBuilderの値を決定するために、それは()の代わりにStringBuilder.Lenthであってもよいです。