13

私たちのアプリケーションは、再起動 (コールド スタート) 後、一度開いた場合 (ウォーム スタート) よりもはるかに長い時間がかかります。

ほとんどの場合 (すべてではないにしても)、違いは DLL のロードにあるようです。DLL がキャッシュされたメモリ ページにある場合、はるかに高速にロードされます。ClearMemを使用して再起動をシミュレートしようとしましたが (実際の再起動よりも時間がかからないため)、さまざまな結果が得られました。

私の質問を要約すると:

  1. コールド スタートとウォーム スタートで起動時間の違いを経験したことはありますか?
  2. そのような違いをどのように扱ってきましたか?
  3. 確実に再起動をシミュレートする方法を知っていますか?

編集:

コメントの説明:

  • アプリケーションはほとんどネイティブ C++ であり、一部の .NET が含まれています (ロードされた最初の .NET アセンブリが CLR の費用を負担します)。
  • ロード時間の改善を目指しています。明らかに、プロファイリングの分担を行い、コード内のホットスポットを改善しました。

忘れていたのは、すべてのバイナリを再ベース化することで改善が得られたため、ローダーがロード時にそれを行う必要がなくなったことです。

4

10 に答える 10

6

再起動のシミュレーションに関しては、仮想 PCからアプリを実行することを検討しましたか? 仮想化を使用すると、一連の条件を何度も簡単に複製できます。

また、何らかのプロファイリング アプリを使用して、タイム ラグの原因となっているコードを特定し、そのコードのどの程度が実際に必要か、または別の方法で達成できるかどうかを判断することも検討します。

于 2008-09-24T13:12:47.700 に答える
4

ソフトウェアで再起動を真にシミュレートするのは難しいでしょう。再起動すると、マシン内のすべてのデバイスでリセット ビットがアサートされ、システム全体のすべてのメモリが失われます。

最新のマシンでは、どこにでもメモリとキャッシュがあります。プログラム用にメモリのページを保存している VM サブシステムがあり、OS がファイルの内容をメモリにキャッシュしています。ハードドライブ自体のセクタのディスク バッファ。おそらくOSキャッシュをリセットすることができますが、ドライブのオンディスクバッファは? 私は方法を知りません。

于 2008-09-24T13:15:06.850 に答える
3

コードをどのようにプロファイリングしましたか? すべてのプロファイリング方法が同じというわけではなく、一部の方法は他の方法よりも優れたホットスポットを見つけます。たくさんのファイルを読み込んでいますか? その場合、ディスクの断片化とシーク時間が問題になる可能性があります。

基本的なタイミング情報をコードに貼り付けたり、ログ ファイルに書き込んだり、コールド/ウォーム スタート時にファイルを調べたりするだけでも、アプリが時間を費やしている場所を特定するのに役立ちます。

これ以上の情報がなければ、2 つの環境の違いの可能性として、ファイルシステム/ディスク キャッシュに傾倒します。その場合は、事前にファイルをロードする時間を短縮するか、ファイルをロードするより高速な方法を見つける必要があります。

例: 多数のバイナリ データ ファイルをロードしている場合は、それらを 1 つのファイルに結合してロードを高速化し、ファイル全体を 1 回の読み取りでメモリにスラープして、その内容を解析します。ディスクのシークが減り、ディスクからの読み取りにかかる時間が短縮されます。繰り返しますが、おそらくそれは当てはまりません。

ディスク/ファイルシステムのキャッシュをクリアするためのツールについてはわかりませんが、ファイルシステム/ディスクのキャッシュに別の情報が読み込まれるようにするために、ディスクから無関係なファイルの束を読み取る簡単なアプリケーションを作成できます。

于 2008-09-24T18:53:32.123 に答える
2

@ Morten Christiansenは次のように述べています。

アプリをコールド スタートで高速に (一種の) 起動する方法の 1 つは、たとえば Adob​​e Reader で使用されます。起動時にファイルの一部をロードすることで、コールド スタートをユーザーから隠します。これは、プログラムがすぐに起動しない場合にのみ使用できます。

これにより、顧客は、使用されていない場合でも、起動するたびにアプリを初期化するために料金を支払うことになります。私はそのオプションが本当に好きではありません (レイモンドも好きではありません)。

于 2008-09-25T07:27:45.460 に答える
2

アプリケーションの起動を高速化する 1 つの成功した方法は、DLL を遅延読み込みに切り替えることです。これは低コストの変更です (プロジェクト設定をいじる必要があります) が、起動を大幅に高速化できます。その後、depends.exe をプロファイリング モードで実行して、起動時に読み込まれる DLL を特定し、それらの遅延読み込みを元に戻します。必要なほとんどの Windows DLL を遅延ロードすることもできることに注意してください。

于 2008-09-25T10:53:04.140 に答える
2

アプリケーションのコールド起動時間を改善するための非常に効果的な手法は、関数リンクの順序を最適化することです。

Visual Studio リンカーを使用すると、リンクされているモジュール内のすべての関数 (またはそれらの一部のみ - すべてである必要はありません) をリストしたファイルを渡すことができ、リンカーはそれらの関数を次のように並べて配置します。メモリー。

アプリケーションの起動時に、通常、アプリケーション全体で init 関数が呼び出されます。これらの呼び出しの多くは、まだメモリ内にないページに対するものであり、その結果、ページ フォールトとディスク シークが発生します。起動が遅いのはここからです。

これらすべての機能が一緒になるようにアプリケーションを最適化すると、大きなメリットが得られます。

Visual Studio 2005 以降の Profile Guided Optimization を確認してください。PGO が行うことの 1 つは、関数リンクの順序付けです。

PGO を使用すると、アプリケーションをリンクして実行し、プロファイル実行からの出力と再リンクする必要があるため、ビルド プロセスに取り掛かるのは少し困難です。これは、ビルド プロセスにランタイム環境が必要であり、悪いビルドの後のクリーンアップなどに対処する必要があることを意味しますが、その見返りとして、通常、コードを変更することなくコールド ローンチを 10 以上高速化できます。

ここに PGO に関する詳細情報があります。

http://msdn.microsoft.com/en-us/library/e7k32f4k.aspx

于 2008-12-18T20:11:56.980 に答える
1

関数順序リストの代わりに、同じセクション内で呼び出されるコードをグループ化します。

#pragma code_seg(".startUp")
 //...
#pragma code_seg

#pragma data_seg(".startUp")
 //...
#pragma data_seg

コードの変更に合わせて簡単に保守できますが、関数順序リストと同じ利点があります。

関数の順序リストがグローバル変数も指定できるかどうかはわかりませんが、この #pragma data_seg を使用すると簡単に機能します。

于 2009-03-17T11:38:57.920 に答える
0

アプリのコールドスタートを高速化する1つの方法(一種)は、Adobe Readerなどで使用され、起動時にいくつかのファイルをロードして、ユーザーからコールドスタートを隠します。これは、プログラムがすぐに起動しない場合にのみ使用できます。

もう1つの注意点は、.NET 3.5SP1の方がコールドスタート速度が大幅に向上したと思われることですが、どれだけかは言えません。

于 2008-09-24T14:08:35.613 に答える
0

それは NIC (LAN カード) である可能性があり、ネットワークの起動を必要とする特定の他のサービスにアプリが依存している可能性があります。したがって、アプリケーションのプロファイリングだけでは、これを正確に把握できない場合がありますが、アプリケーションの依存関係を調べる必要があります。

于 2008-09-24T18:56:29.760 に答える
-1

アプリケーションがそれほど複雑でない場合は、すべての実行可能ファイルを別のディレクトリにコピーするだけで済みます。これは、再起動に似ているはずです。(カットアンドペーストは機能しないようです。Windowsは、ファイルが別のフォルダーに移動したことを認識できるほど賢く、メモリにキャッシュされています)

于 2009-03-18T11:25:34.877 に答える