Recently I was thinking how to overcome a first-hit slowness problem of a website.
In many of true large production environments with the custom built applications you can have the application precompiled, running on an always-on application pool and first hit will happen infrequently. But even then it will still take time to launch the application or load / combine all resources together to show every single page.
This problem is even more [annoying] in a shared hosting environment with an application that does not support precompilation. This was the case in my situation too. Having installed the very powerful DotNetNuke CMS in a not so fast environment, I observed pretty much the same behavior - application is restarted 5-10 times a week and every first hit on a page takes time to process.
The solution I came up with is a DotNetNuke Scheduler task that runs after the application starts and crawls all the pages it can and loads all modules that are used in 2 phases:
- It locates all Modules that are used by DNN in any of the Portals and loads all controls (User Controls) associated with those modules. Once they are loaded, .Net will not have to load classes associated with them into the Application Domain and generate intermediate dynamic classes any more. As a result, the Tab using those Modules will load fast even on a first hit.
However, this approach does not let loading User Controls that are used by Skin Objects as there is nothing that lets tracking them, so those would still need to load on a first hit.
Alternative to the #1 can be loading just all User Controls that are there in the Application and so I have created a method LoadAllControls(), but I am not actively using it as it loads all User Controls, including those that are not used, thus unnecessarily using resources.
This method can be effectively used in some other websites that do not have unused controls, or have lots of resources. At the same time it can also be used in any .Net application to pre-load all User Controls.
- For every website, it tries to locate an Http Alias that it can use to reach out to the website. As some of the DotNetNuke deployments cannot connect to the internet or self using an fqdn, you might need to a new Http Alias that would reference the website as localhost{/virtaulPath}.
After getting a working alias, it attempts to ping (send http GET request) to every Tab of a website, forcing .Net to compile the page, loading Skins, Skin Objects and any other controls missed by #1.
However, many pages on the website might require authorization and the scheduling task does not log in, so it can crawl only public pages (visible for All Users).
Pinger is compatible and works fine for me with DotNetNuke 5, however as DNN tries to process the jobs associated with APPLICATION_START even synchronously, attempting to run Pinger at APPLICATION_START event will result in a halt, that is why you should let it run only on some time interval basis - every 5 - 10 minutes. Once DotNetNuke application is started, and Pinger is triggered the first time, it will do its work and note that it has already ran. All subsequent job executions Pinger will ignore until the application restarts.
Please keep all of the above in mind if using the Pinger as many Modules / Controls can have various functionality triggered when they get loaded and you might not want it executed by the Pinger.
WARNING: Pinger is provided AS IS. Use it at your own risk. The author or tuchka.info are not responsible for any damage being direct or indirect result of using this module.
NOTE: You may use / modify the source code provided below keeping the reference to the original version at www.tuchka.info.