Prism Module InitializationMode Comparison
Introduction
As part of my self-improvement challenge, I have been watching the Introduction to Prism course from Pluralsight. I chose this course so I am better equipped for my team’s Prism application project at work where I was recently tasked to improve the startup performance.
At this time, the project contains sixty-nine IModule
implementation types; however, that number is continuing to grow. All of these modules will not be loaded at once and some of them may not be used/loaded at all. Some of them are conditionally loaded during runtime when certain criteria are met.
While watching the Initializing Modules video I found myself wondering if anything would change if I were to change these conditionally loaded modules InitializationMode
from the default WhenReady
to OnDemand
. My reasoning behind this is because Brian Lagunas explains that WhenReady
initializes modules as soon as possible or OnDemand
when the application needs them in the video. Brian recommends using OnDemand
if the module is not required to run, is not always used, and/or is rarely used.
I have a few concerns:
- Impacting features because the module is not loaded beforehand or the Module initialization is not done manually.
- No performance impact because this project handles module initialization itself to parallelize it instead of letting Prism manage it.
In the end, only benchmarking each option will provide information to make a decision. To do this I used JetBrains dotTrace, focusing on the timings for App.OnStartup
, Bootstrapper.Run
, Bootstrapper.ConfigureModuleCatalog
, and Bootstrapper.InitializeModules
. Since we try to load modules in parallel, I ended up adding the timing for this as well - otherwise, the timing may have appeared off.
Baseline - InitializationMode.WhenAvailable
The first step was to gather baseline metrics.
Profile #1 | Profile #2 | Profile #3 | Profile #4 | Profile #5 | Min | Average | Median | Max | STD | ||
---|---|---|---|---|---|---|---|---|---|---|---|
App.OnStartup | 5845 | 4687 | 4220 | 4545 | 4973 | 4220 | 4854 | 4687 | 5845 | 551.6462635 | |
Bootstrapper.Run | 5954 | 3986 | 2598 | 3293 | 2779 | 2598 | 3722 | 3293 | 5954 | 1215.581013 | |
Bootstrapper.ConfigureModuleCatalog | 1148 | 767 | 363 | 511 | 1.5 | 1.5 | 558.1 | 511 | 1148 | 385.1511911 | |
Bootstrapper.InitializeModules | 184 | 109 | 117 | 85 | 71 | 71 | 113.2 | 109 | 184 | 39.0404918 | |
Asynchronous Module Initialization | 1821 | 2233 | 2311 | 2571 | 2564 | 1821 | 2300 | 2311 | 2571 | 274.6590614 |
Not terrible, but not ideal. The application splash screen is displayed for about 4.5 seconds on average on a developer machine with only a few conditional modules enabled.
InitializationMode.OnDemand
With the baseline determined, a comparison can be made when switching the modules to be loaded OnDemand
.
Profile #1 | Profile #2 | Profile #3 | Profile #4 | Profile #5 | Min | Average | Median | Max | STD | ||
---|---|---|---|---|---|---|---|---|---|---|---|
App.OnStartup | 5419 | 3969 | 4391 | 5919 | 5490 | 3969 | 5037.6 | 5419 | 5919 | 733.0750575 | |
Bootstrapper.Run | 2770 | 2197 | 2017 | 2086 | 2238 | 2017 | 2261.6 | 2197 | 2770 | 266.0320281 | |
Bootstrapper.ConfigureModuleCatalog | 408 | 374 | 340 | 352 | 388 | 340 | 372.4 | 374 | 408 | 24.40983408 | |
Bootstrapper.InitializeModules | 143 | 67 | 69 | 69 | 66 | 66 | 82.8 | 69 | 143 | 30.1224169 | |
Asynchronous Module Initialization | 1926 | 1639 | 1699 | 1603 | 1632 | 1603 | 1699.8 | 1639 | 1926 | 117.3292802 |
All the Bootstrapper
methods seemed to have improved, but overall the App.OnStartup
took approximately the same amount of time.
Summary
There was an impact, but not in the overall startup time - which I find a little peculiar. It seems as though the overhead may have been shifted elsewhere in the startup process.
This may mean a hybrid approach to Bootstrapper.InitializeModules
does have merits although not as much as I had hoped. Another option may be to change the Bootstrapper.ConfigureModuleCatalog
to conditionally determine to add modules instead of applying a ‘safe’ default. Or perhaps I am diagnosing the wrong problem and should at other options - such as switching Dependency Injection frameworks.
In any case, I am going to discuss this as an option with my team - and see if additional testing can be done with more conditional modules enabled.