When the first request arrives at your web application there is a mind-numbing amount of work to do. The worker process starts, the runtime initializes, ASPX pages are parsed and compiled to intermediate language, methods are just-in-time compiled to native code - and the list goes on and on. If you want to cut out some of the overhead and improve the startup time of your application, then you’ll want to look at the precompile features in ASP.NET 2.0.
Although pre-compilation will give our site a performance boost, the difference in speed will only be noticeable during the first request to each folder. Perhaps a more important benefit is the new deployment option made available by the precompile - the option to deploy a site without copying any of the original source code to the server. This includes the code and markup in aspx, ascx, and master files.
In this article we will explore the benefits and caveats around pre-compilation and the new aspnet_compiler tool. There are two modes for pre-compilation: in place pre-compilation and pre-compilation for deployment. We will take a look at in place pre-compilation first.
In Place Pre-compilation
By default, ASP.NET dynamically parses and compiles all the ASPX pages in a folder when the first request arrives for a page inside that folder. ASP.NET also needs to compile applicable files in the special folders, like App_Code, on the first request, and any code-behind files associated with ASPX and ASCX files. The runtime caches all the compilation results in order to quickly process later requests, and does not need to recompile again unless someone edits a file. This behavior gives us a great deal of flexibility, including the flexibility to change code and markup and instantly have the changes reflected in the next browser request.
The price for this flexibility is the performance hit on the first request. Some people have found their ASP.NET applications to be slow starters. These people usually work in the sales department and perform software demos in front of customers. In place pre-compilation makes the “first hit” to a web application and forces all pages and code in the application to compile.
The tool to use for pre-compilation is the aspnet_compiler executable, which you can find in the %WINDIR%\Microsoft.NET\Framework\v2.x.xxxx directory. If we have a web application in the WebSite1 virtual directory under IIS, we could use the following command line to compile the application.
The –v parameter specifies that we are passing a virtual path to our web site. On servers with multiple websites you may need to use the –m parameter and specify the full IIS metabase path to the application (-m /LM/W3SVC/1/Root/WebSite1).
The pre-compiled code will end up inside of the Temporary ASP.NET File directory, just as it would when the runtime compiles files for a browser request. Inside of the bin directory for the compiled site, you’ll find the assemblies (dll files). The compiler generates special filenames to avoid naming collisions. In the shot below, the dll starting with App_Code contains the code from the App_Code directory – not too surprising. Each folder containing aspx, or ascx files will compile into a dll prefixed with App_Web. The files with a .compiled extension contain XML with information about which original source code file maps to which assembly.
With the compiled files in place your web application should have a slightly better startup time, but a primary benefit to in place pre-compilation will be the ability to ensure the web application is error free. If you happen to modify a class or web form and leave an error in the file, the aspnet_compiler will fail and display the compiler error. The tool will also display any warnings, but warning will not stop compilation.
Pre-compilation For Deployment
Pre-compilation for deployment creates an ‘executable’ (no source code) version of your web application. With pre-compilation for deployment you give the aspnet_compiler the path to your source code, and the path to a target directory for the compilation results, like below.
aspnet_compiler -p "C:\MyDevelopment\WebSite1" -v / C:\Staging
This command will compile the site and place the result in C:\Staging. You must still specify –v as a parameter, even though we are not using a virtual path as either a source or a destination. Instead, the compiler will use this parameter to resolve application root references (~).
The pre-compilation for deployment step will recreate your web site’s folder structure in the destination directory. All of the static files (HTML files, image files, configuration files) are copied into the folder structure exactly as they appear in the source folder hierarchy. A bin directory will appear in the target directory with all of the assemblies and .compiled files.
The target directory will contain no source code. All of the classes in the App_Code folder are now compiled into one or more assemblies in the bin directory, and no .cs or .vb files will exist in the target directory. Master page files will also compile to the bin directory and not exist. All the code and markup in ASPX, ASCX, and ASHX files, along with any associated code-behind files, will live inside of one or more assemblies in the bin directory, although these files will still exist in the target directory, they exist as nearly empty ‘marker’ files. If you open an ASPX file in a pre-compiled target directory you’ll see the following content:
This is a marker file generated by the precompilation tool, and should not be deleted!
Note: this behavior is as of beta 2 and may change. The IIS script map for the ASPX file extension leaves the “Verify that file exists” checkbox unchecked, and the site will work without any of the ASPX files present. There is, however, a problem getting IIS to serve a default document for a directory request unless the file is present.
Once the application finishes compiling you can FTP or XCOPY the target directory to a web server (or map a virtual directory to the target directory), and the application will be ready to run. A benefit to pre-compilation for deployment is that no one can make changes to the web application by tweaking the source code – no source code exists! In fact, you can’t even place a new ASPX file into the existing application directory structure without causing an error.
Making a change to your site will require you to make a change in the original source code, pre-compile the application again, and redeploy all files to the server. There is one caveat in this scenario, in that pre-compilation generates unique filenames for some assemblies in the bin folder, and these filenames will change each time the pre-compiler executes. The first time you run aspnet_compiler you might see App_Web_lufhs9vn.dll in the bin directory, the next time you might see App_Web_hviqdkt.dll with the same compiled code, even though no source file has changed. This means you might have unneeded dlls in your bin directory if you keep repeatedly copy files to the server without cleanup.
Update: use the -fixednames switch to generate repeatable assembly names.
For some people, the ability to update content on the web server by modifying aspx and ascx files is a needed feature. To support this scenario, the aspnet_compiler has the –u switch for an “updateable” pre-compilation. With updateable pre-compilation the ASPX, ASCX, ASHX, and MASTER files are copied to the target directory in tact - they do not become ‘marker’ files. You can deploy these files to the server and modify them without causing an error, because the ASP.NET runtime will dynamically parse and compile these files. All of the source code for code-behind files and in the App_Code folder will still be compiled into assemblies and will not need to be deployed.
A few other features of the aspnet_compiler include the –d switch, which tells the compiler to generate debugging symbols for the application. Debugging symbols are required if you need line numbers in the stack traces of exceptions. The –f switch will force the compiler to overwrite a target directory, even if a precompiled application already exists there. There are also options to give compiled assemblies a strong name, and allow partially trusted callers.
In addition, you can pre-compile an application directly from Visual Studio 2005 using the Build -> Publish menu item. The Publish Web Site dialog will let you select an http, ftp, or local file system destination as the target.
The precompiler also supports strong naming with the -keyfile, -keycontainer, and -delaysign switches. To allow partially trusted callers, use the -aptca switch.
Although performance is often touted as a benefit of pre-compilation, I tend to think of pre-compilation as a safety feature. Safety in knowing all of the code in a web application compiles without an error, and safety in keeping your source code out of a shared host environment.
by Scott Allen
Feel free to ask questions or leave comments about this article on my blog.