관리자 (IP : 184.108.40.206)
[WPF] WPF 앱 시작 시간을 줄이는 9가지 팁
9 Tips to Reduce WPF App Startup Time
Native Image Generator (Ngen.exe) is the first tool you should consider when optimizing startup for a .NET Framework app (.NET/.NET Core projects don’t support Ngen). As you may know, .NET Framework projects produce assemblies with Microsoft Intermediate Language (MSIL) code. This code needs to be translated to machine code before executing the application. Translation from MSIL to machine code begins at startup - a process that may require significant time.
You can use Ngen.exe to generate native image libraries that already contain native code. It’s important to note that Ngen.exe should be used on the machine where your application will be used. You can run it on your machine to test performance, but to optimize cold start for an end user, you need to use Ngen.exe on the user machine.
The best way to run Ngen on a user’s machine is to incorporate Ngen.exe within your application installer. You’ll need to execute the following line during the installation process and Ngen.exe will automatically process all assemblies associated with your project:
If you distribute your application as Click Once or an archive (and don’t have an installer), you can call Ngen.exe from code during application startup. To only run Ngen.exe for the first startup, calculate a hash for your executable file and check this hash during subsequent startups:
Windows 8 (and newer versions of the Windows OS) include a Native Image Task that automatically generates native images for frequently used .NET Framework 4.5+ applications when a computer is idle. Nonethless, you still need to run Ngen.exe manually, because Native Image Task only works with assemblies located in GAC or Windows Store app package.
The image below illustrates startup benefits you can expect from Ngen.exe:
2. MultiCore JIT
Alternatively, you can optimize the translation of Microsoft Intermediate Language (MSIL) to machine code by translating most frequently used methods asynchronously at application startup. You can use MultiCore JIT for this purpose (available for .NET and .NET Framework 4.5+ apps). MultiCore JIT logs methods used by your application and saves them to disk. When the application is executed for the second time, saved methods are compiled to native code in a separate process.
You simply need to use the following two lines of code in your app constructor to enable MultiCore JIT:
MultiCore JIT is not as effective as Ngen.exe in terms of startup optimization. The good news is that it supports both .NET Framework and .NET/.NET Core projects. You can combine MultiCore JIT with the ReadyToRun option (described later) and benefit from both optimization strategies.
ReadyToRun (R2R) is a form of ahead-of-time (AOT) compilation. Applications published with R2R contain both MSIL and native code sections, which eliminates the need of just-in-time compilation (to a certain extent).
The R2R option is available only in .NET/.NET Core projects. To enable R2R, modify your “.csproj” / “.vbproj” file and add the
To proceed with this strategy, publish your project:
As mentioned earlier, R2R can be used together with MultiCore JIT in .NET/.NET Core applications. The image below illustrates startup benefits you can expect from R2R and MultiCore JIT.
If your application contains a DevExpress Ribbon Control with multiple items, on-demand page loading may help you reduce startup time.
To enable deferred
Please refer to the following help topic for additional information: Deferred RibbonPage Content Loading.
5. Use LoadingDecorator for “Heavy” UI Elements
Since WPF works with the UI in the main thread, the entire window remains frozen until all elements are loaded. The DevExpress LoadingDecorator allows you to load separate UI sections asynchronously:
By implementing this strategy, your app can display “lighter” UI elements before loading “heavier” elements on screen. In the animation above, I wrapped the right section of the view within LoadingDecorator to display our lightweight navigation menu first. The right section is displayed only when it’s fully loaded:
6. Cache Tabs on Selection
If your application uses a tabbed interface, you can fine-tune performance using different tab cache modes. This feature is available within our WPF Tab Control (DXTabControl) and our WPF DockLayoutManager (when tabbed DocumentGroups or LayoutGroups are used).
Tabs are not cached by default, which is fine for initial startup. However, if you decide to open the same tab a second time, its content will be loaded once again. To use previously loaded elements, cache tabs after selection. This behavior is controlled by the
If tab switching is more important than startup performance, you can set
7. Load Data on Demand
While your application may work with large amounts of data, your users may not need to view all data in one shot. Many of our WPF controls allow you to load data on demand. The following WPF DevExpress WPF components support virtualization/on-demand data loading:
8. Preload Theme Resources
DevExpress components contain many XAML resources used by themes. WPF parses all these resources when a component is displayed for the first time. You may have noticed that displaying the same control for the second time takes much less time even if this control was displayed previously in a different view.
DevExpress themes allow you to partially load theme resources before a component is displayed on-screen. Although this won’t speed up the main view, all child views will open faster. You can use the following code to implement this strategy:
If your application uses a Splash Screen, you can preload theme resources within it. Please refer to the following example for more information on this startup strategy: Synchronous Theme Preload With Splashscreen.
9. Use a Performance Profiler to Detect Issues
Certain operations in View/ViewModel initialization may generate unwanted startup delays. These delays may occur if you synchronously communicate with a remote service, process large files, or execute other resource-intensive operations in a View/ViewModel constructor.
Visual Studio includes a built-in Performance Profiler to help determine the exact cause of performance-related issues. To discover time-consuming operations, follow the steps below:
You can click individual methods to navigate to a detailed call tree.
As you can see from the image above (taken from a test application), significant resources were consumed by the