StackExchangeは、ASP.NETとSQL Serverで構築されている。 先日、Sam Saffron氏とMarc Gravell氏はブログで、彼らが経験した.NET GC GEN-2オブジェクトの最終的なトレースに関する問題の識別とパフォーマンスの解決に関する投稿を行った。彼らの経験には、アプリケーション開発において、パフォーマンスチューニングを行うすべての人が参考になる多くのことが存在している。
この問題は、大きなオブジェクトのリストをメモリ上に保持するカスタムタグエンジンによって引き起こされていた。ブログの投稿は、どちらも一読の価値がある。Sam氏のものはより詳細で、どのように問題が診断されたかの詳細を含んでいる。主要なものは、
- プロファイラの利用。メソッド呼び出しのプロファイルのためにMVC-MiniProfiler、メモリの使用量をトラッキングするために、.NET Memory ProfilerやRedgate ANTS Memory profilerのようなメモリプロファイラを使用することができる。
- 可能なら、クエリ可能なログ。StackExchangeチームは、生ログの解析とそれを登録する大規模な、専用のSQL Serverのインスタンスというバックグラウンドプロセスを持っている。ログをクエリする能力がなければ、メトリックのグラフと傾向とパターンを見ることができない。
- どのようにCGが動作するかを理解する–.NETのガベージコレクションは、オブジェクトに3つの世代(世代0から2)を持っており、長期間滞在するデータは、GEN-2に作られる。GEN-2は、少ない頻度でスキャンされ、実行するために他のスレッドをブロックするため、最も高価な処理である。Sam氏は、より詳しく知るために、Rico氏のガベージ コレクタの基本とパフォーマンスのヒントを読むことを奨めている。
アプリケーションの特定の部分に対して、他のいくつかの最適化の中で、最後にチームは、オブジェクトの配列からインデックスの配列に切り替え、クラスから構造体に切り替えることになった。 前者は、配列がただ不変のリストに対するインデックスである場合、たいていのケースで役立つパターンだが、後者は一般的ではなく、Sam氏は、50万以上のオブジェクトがあり、第2世代に達した時点で解放される場合のみ推奨している。
StackExchangeチームは、パフォーマンスを非常に重視している – どのようにStackOverflowがキャッシュを使って、3つのレベルでレスポンス時間を向上させ、サーバーロードを削減しているかを見ることができる。
Rob Howard氏の記事を含むMSDNだけでなく、InfoQのパフォーマンスとスケーラビリティに関する記事など、いくつかの参考になるリソースが存在している。結局のところ、Sam氏の言葉を引用すると、“トン以下の作業を行うことは、多くの作業をおこなうよりも安価な作業が常に起こっています!”
あなたは、ASP.NETアプリケーションのスケールにおけるボトルネックを発見し、解決したという共有できる同じような経験をお持ちだろうか?