14

フレームワーク 4.5 用の VB.NET で書かれた WinForms アプリケーションがあります。アプリケーションの起動時間が異常に長いことに気付きました (私が作成した他のアプリケーションは、起動時にさらに多くの作業をほぼ瞬時に開始します。このアプリケーションには 5 秒以上かかります)。複数回起動しても起動時間は変わらないので、推測しますアプリケーションの最初の起動時にキャッシュされていない CLR コードの場合ではありません。

起動時の時間を書き留めて、いくつかのテストを行いました。

Module modMain
    Public MyLog As System.Text.StringBuilder

    <STAThread>
    Public Sub Main()
        MyLog = New System.Text.StringBuilder

        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        MyLog.AppendLine("Before run: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
        Application.Run(frmMain)
    End Sub
End Module

Sub Main()アプリケーションのエントリ ポイントです。それは実行されfrmMain、そこで私が制御できる最初の実際のものはSub InitializeComponent()、デザイナーによって生成された です。

<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
    MyLog.AppendLine("Init Start: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
    'All the control initializations
    MyLog.AppendLine("Init End: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
End Sub

Form.Loadそしてついにイベントに到着

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    MyLog.AppendLine("Form_Load Start: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
    '...
    MyLog.AppendLine("Form_Load End: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
End Sub

これで、MyLog の出力は次のようになります。

Before run: 15.12.2014 19:56:47,579
Init Start: 15.12.2014 19:56:51,451
Init End: 15.12.2014 19:56:51,521
Form_Load Start: 15.12.2014 19:56:51,544
Form_Load End: 15.12.2014 19:56:51,547

Application.Run()主な一時停止は と の間で発生することがわかりますSub InitializeComponent()。他の質問から、GUI スレッドのメッセージ ループが開始されることはわかっていますが、このアプリケーションが他のアプリケーションよりもはるかに遅くなる理由がわかりません。

私の質問は次のとおりです: Application.Run とコードの制御を取り戻すポイントとの間で正確に何が起こりますか?それをスピードアップするために何かできるでしょうか? そこで行われた作業は、フォーム上のコンポーネントに何らかの形で関連していますか?

frmMain.ShowDialog()の代わりに既に使用してみApplication.Run(frmMain)ましたが、これは同じ結果につながりました。私は Visual Studio Express を使用しているため、残念ながら、より詳細なパフォーマンス プロファイラーを使用することはできません。

これを C# と VB.NET の両方としてタグ付けします。両方の言語での回答は大歓迎です。

EDIT
SLaksの回答で提案されたソリューションを含め、さらにいくつかのテストを行いました。を使用NGENしてアセンブリをプリコンパイルしても、目立った効果はないようです。したがって、コードの JIT コンパイルではないと思いInitializeComponentます。

ただし、他のシステムでは、問題のコンピューターがすべての点で遅い場合でも、プログラムはほぼ瞬時に (10 倍以上速く) 起動することに気付きました。コンピューターの違いはオペレーティング システムでした。

Windows 7: Slow start
Windows 8.1: Fast start
Windows Server 2008: Fast start

これらは単なる手がかりであり、答えに役立つかどうかはわかりません。

編集 2
起動時に ProcMon を見ると、次の行で実行がハングしていることがわかります。

"15:56:29.3547260","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources.dll","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:29.3548019","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources\Electrochemical Calculator.resources.dll","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:29.3548612","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources.exe","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:29.3549519","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources\Electrochemical Calculator.resources.exe","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:32.8796760","Electrochemical Calculator.exe","5972","CreateFile","C:\Windows\Fonts\StaticCache.dat","SUCCESS","Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened"
"15:56:32.8797088","Electrochemical Calculator.exe","5972","QueryStandardInformationFile","C:\Windows\Fonts\StaticCache.dat","SUCCESS","AllocationSize: 9,633,792, EndOfFile: 9,633,792, NumberOfLinks: 1, DeletePending: False, Directory: False"
"15:56:32.8797218","Electrochemical Calculator.exe","5972","ReadFile","C:\Windows\Fonts\StaticCache.dat","SUCCESS","Offset: 0, Length: 60, Priority: Normal"
"15:56:32.8797429","Electrochemical Calculator.exe","5972","CreateFileMapping","C:\Windows\Fonts\StaticCache.dat","FILE LOCKED WITH ONLY READERS","SyncType: SyncTypeCreateSection, PageProtection: "

この問題はさらに、リリースビルドでのみ発生し、Windows エクスプローラーからプログラムを直接起動した場合にのみ発生します。Visual Studio から開始したリリース ビルドと同様に、デバッグ ビルドは即座に起動します (5 ~ 10 秒に対して 0.3 秒)。

4

3 に答える 3

2

ハンスが言ったように、あなたはすでに明らかな問題を排除しており、私には、問題は環境にあるようです...極端な状況を考えると、これをどのようにトラブルシューティングしますか...

このプロセスには一貫して 5 秒以上かかるため (エクスプローラーから起動した場合)、この状況で私が考えているいくつかのアプローチを次に示します。

- タイミングの問題が発生する可能性があるため、適切な結果を得るには実験を数回繰り返す必要がある場合があります。明らかに、結果を保証するのはまだ難しいです... 私が個人的にそれを行っていた場合、これらの高レベルのアイデアが 100% 機能しない場合は即興で作りたいと思います..

  • Procdumpを使用してプロセスを起動し、プロセスのパフォーマンス カウンターが特定の値 (2、3、4 など) に達したらn 完全なダンプを取得します。Elapsed Time次に、これらのダンプを windbg (ほとんどの情報、使いにくい)、または VS.Net (使いやすいですが、そこにある場合でも、探したいものが表示される場合と表示されない場合があります) で開くことができます。ダンプを開く)。

  • 同様の行ですが、強力ではなく、正しく理解するのがよりトリッキーです..プロセスのプロパティを確認したときにネイティブのスタック トレースを表示するようにProcessExplorerを構成します... プロセスを開始したらすぐに、ProcessExplorer に切り替えて、スタック トレースを確認します。プロセス内のさまざまなスレッドに対して.. スレッドの数によっては、手動でスタック トレースを調べてもまったくうまくいかない可能性があるため、これはよりトリッキーです..最小限の労力で問題が明らかになります。

いずれの場合も、必ずシンボルを Microsoft のパブリック シンボル サーバーに設定してください。これにより、ネイティブ スタック トレースからほとんどの情報を取得できます。

要約すると、アイデアは次のとおりです..この場合、一部の高レベル関数は、その下の処理が完了するまでに数秒かかる場合、スタックトレースに表示される可能性が高くなるはずです。

- 高レベルの機能を理解したら、話は終わりかもしれませんし、他のシステム レベルのプロセスと相互に関連付ける必要があるかもしれません.. (ここでもウイルス対策が典型的な例です)..確かに、そのような仮説を裏付ける手がかりがさらにあると期待できます。

于 2014-12-19T08:41:18.310 に答える
2

この時間は、フォームのコントロールで使用されるすべてのアセンブリの読み込みと、InitializeComponent メソッドの JIT に費やされます。

于 2014-12-15T19:09:43.837 に答える