Who should read this article: ASP.NET developers interested in the technical
details of how just-in-time compilation happens with .ASPX pages
Several months ago, I began a discussion on an
ASPFriends.com e-mail list about when and
how ASP.NET
pages get compiled into native code (x86 processor instructions). Some documentation
said that native code stays
in memory between page requests, and some said it was compiled again for every page
request. Microsoft's documentation available at the time (before the final 1.0
release) was ambiguous on the topic.
Scott Swigart spelled out the process very clearly for me, and Scott Guthrie
at Microsoft confirmed it and elaborated on a couple points. Thanks to their
explanations, I was able to understand the process and describe it here:
- Machine boots.
- Request for MyPage.aspx comes in (first time).
- MyPage.aspx compiles to an assembly*
(we'll call it MyPage.dll* ).
- The portions of MyPage.dll that are needed for execution are
JITed* to
memory.*
- Page execution completes. The JITed code stays in memory.
- A new request for MyPage.aspx comes in. The page hasn't changed. The
JITed code that is still in memory runs.
- The source for MyPage.aspx changes.
- A new request for MyPage.aspx comes in. MyPage.aspx compiles to an
assembly, JITs, and executes. The JITed code stays in memory.
- A new request for MyPage.aspx comes in. The page hasn't changed. The
JITed code that is still in memory runs.
- IIS is stopped and started.
- A new request for MyPage.aspx comes in. The page hasn't changed. Because
IIS was stopped and started, the JITed code is no longer in memory. The existing
MyPage.dll JITs and executes. This new JITed code stays in memory.
The JITing process is similar with any .NET code, including .DLL's in your ASP.NET
application and .DLL's and .EXE's in WinForms applications. Since there's no page,
and since the assembly is already created, these steps don't take place. Instead,
methods in the assembly are JITed to native code in memory when they're called
(step 4 above), and
unloaded from memory when the calling application (the Windows .EXE, or IIS and the
ASP.NET worker process as in step 10 above) is closed.
Notes:
- Step 3: Note that a code file (.CS for C# code, .VB for Visual Basic code
or no code) gets created from the .ASPX page first, then this file gets compiled
into an assembly (.DLL).
- Step 3: The MyPage.dll assembly won't have a friendly name like that. Expect more like "yxgq4-hz.dll". Whatever it's called, it will be under a directory called something like "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files".
- Step 4: "JITed" is shorthand for
"just-in-time compiled."
In .NET, methods from your assemblies are compiled into native binary code when
they are called. In ASP.NET, this happens when pages are requested by the web
browser--at runtime, and thus, just in time before serving the response.
Contrast this with COM components, which must be compiled to binary code ahead
of time, before they can be called.
- Step 4: This is just a one-time performance hit, and
even so, it shouldn't be of concern. In Scott Guthrie's words: "Note that
in practice, the cost of dynamic JITing the first access of a page's code is
minimal. Because most of the overall page code path actually lives within [.NET]
Framework libraries (for example: the code within the page base class, the
code within System.Data, System.XML, etc.), the number of instructions
generated from your actual code are pretty minimal. Because we can
dynamically JIT millions of instructions to native code per second, this
one-time cost ends up being noise in the grand scheme of things."