I have a WinForms application written in VB.NET for Framework 4.5. I noticed that the startup time of the application is unusually long (other applications I have written that are doing even more work on startup start nearly instantly, this application needs >5 seconds) The startup time does not change after multiple starts, so I guess it is not a case of uncached CLR code during the first start of the application.
I did some testing by writing down times during startup:
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()
is the applications entry point. It runs frmMain
, and there the first real thing I have control over is Sub InitializeComponent()
, generated by the designer:
<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
And finally I arrive at the Form.Load
event
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
Now, the output of MyLog is as follows:
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
You can see, that the main pause occurs between Application.Run()
and Sub InitializeComponent()
. I know from other questions, that there a message loop is started for the GUI thread, but I don't know why it should be so much slower for this application than for other applications.
So my question is: What exactly happens between Application.Run and the point I regain control over my code, and can I do something to speed it up? Is the work done there in any way related to the components on the form?
I already tried using frmMain.ShowDialog()
instead of Application.Run(frmMain)
, but this led to the same results. I am using Visual Studio Express, so unfortunately I can't use a more in depth performance profiler.
Tagging this as both C# and VB.NET, because answers in both languages are very welcome.
EDIT
I have done some more tests, including the proposed solution in SLaks answer. Using NGEN
to precompile the assembly did not seem to have any noticable effect. So I guess it is not the JIT compilation of the InitializeComponent
code.
I however noticed, that on other systems the program started practically instantaneously (>10 times faster), even if the computer in question was slower in all respects. The difference between the computers was the operating system:
Windows 7: Slow start
Windows 8.1: Fast start
Windows Server 2008: Fast start
These are just more clues, I don't really know if it is helpful for an answer.
EDIT 2
Looking at ProcMon during startup I find that the execution hangs at the following lines:
"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: "
The problem further occurs only in a Release build, and only when I start the program directly from the Windows Explorer. A debug build launches instantly (0.3 seconds, compared to 5-10 seconds), as does a Release build when started from Visual Studio.
Well, you eliminated all the normal sources of startup delays. It most definitely doesn't have anything to do with Application.Run(), that doesn't start until after the form's InitializeComponent() method finishes running. And you eliminated jitting overhead by using Ngen.exe. Be sure to distinguish between cold and warm start delays, if it is only slow the first time you start the program then it is a hardware problem, you need a faster disk. The fact that it is only slow on some machines strongly points to an environmental problem.
Triggered by the code that runs in InitializeComponent(). In other words, all the constructors and property setters of the controls on your form. That normally takes very little time, but there are certainly trouble-makers around. You need to look for a non-trivial control, particularly the kind that uses COM (aka ActiveX) under the hood. Like WebBrowser. There are many more possibilities, anything whose class name starts with "Ax". Such controls can load a lot of other DLLs and are apt to be interesting to security software.
Some debugging tips:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With