私の推測: dll の読み込みと JIT コンパイルが原因である可能性が高い
1. アセンブリのロード。
.NET は、アセンブリ (dll) を遅延ロードします。FooLibrary への参照を追加しても、コードの読み込み時に読み込まれるわけではありません。代わりに、最初に関数を呼び出したり、FooLibrary からクラスをインスタンス化したりすると、CLR が移動して、それが存在する dll をロードします。これには、ファイルシステムでの検索、可能なセキュリティ チェックなどが含ま
れます。コードが適度に複雑な場合でも、「最初のテスト」で数十のアセンブリが読み込まれることが多く、明らかに時間がかかります。
すべてがすでにロードされているため、後続のテストは高速に表示されます。
2. JITコンパイル
.NET アセンブリには、CPU が直接実行できるコードが含まれていないことに注意してください。.NET 関数を呼び出すたびに、CLR は MSIL バイトコードを受け取り、それを実行可能なマシン コードにコンパイルしてから、このマシン コードを実行します。これは関数ごとに行われます。そのため
、関数
を初めて呼び出すときに、JIT コンパイル中にわずかな遅延が発生することを考慮すると、これらのことが加算される可能性があります。これは、多くの関数を呼び出したり、大規模なサードパーティ ライブラリ (エンティティ フレームワークなどを考えてください) を初期化している場合に特に問題になる可能性があります。
上記のように、関数の多くはすでに JIT コンパイルされ、メモリにキャッシュされているため、後続のテストは高速に表示されます。
では、どうすればこれを回避できますか?
アセンブリの数を減らすことで、アセンブリの読み込み時間を改善できます。これは、ファイル検索が少なくなることなどを意味します。Microsoft .NET パフォーマンス ガイドラインでは、さらに詳しく説明しています。また、それらをグローバル アセンブリ キャッシュにインストールすると (??) 役立つと思いますが、まったくテストしていないので、大まかに考えてください。GAC へのインストールには管理者権限が必要で、非常に負荷の高い操作です。問題が発生するため、開発中にそれを行うことは望ましくありません(アセンブリはファイルシステムに優先して GAC から読み込まれるため、気付かずにコードの古いコピーを読み込んでしまう可能性があります)。
ngenを使用してアセンブリをプリコンパイルすることで、JIT 時間を改善できます。ただし、GAC と同様に、これには管理者権限が必要であり、時間がかかるため、開発中にも実行したくありません。
私のアドバイス?
まず、単体テストでパフォーマンスを測定することは、特に良いことでも信頼できることでもありません。Visual Studio がバックグラウンドで他に何をしているか、テストに影響するかどうかは誰にもわかりません。
コードを取得したら、スタンドアロン アプリのベンチマークを実行し、ループしてすべてのテストを 2 回実行し、最初の結果を破棄します :-)