Brandon Bray gave an interesting presentation at MIX09 on how the CLR (the execution engine that underlies the .NET Framework) was refactored to support for Silverlight; I thought I’d share my distilled notes from the session.
Bringing .NET to the Silverlight world was an obvious choice. Not only does it have a broad community and powerful tools ecosystem, but the CLR also offers many important and useful features for building RIAs: strong type safety, partial trust security verification and AppDomains (providing isolation for multiple applications within a single process). But the existing .NET Framework is specific to Windows, and has grown too large for deployment in a web runtime where every byte counts. So it was necessary to rework the CLR to be optimized for this purpose.
CLR Size Reductions
Looking at the .NET architecture, it was designed to support many different scenarios across client and server, including profiling and debugging, just-in-time compilation, and so on. For Silverlight, we just needed to focus on one scenario: interactive client applications. Silverlight contains “CoreCLR”, a cut down version built from the same sources that runs side-by-side with the full .NET CLR. CoreCLR is just 2MB in size. It’s worth noting in passing that CoreCLR is also embedded within other Microsoft technologies, most notably Live Mesh.
Some compromises that could be made to trim the size of the CLR right down:
- We don’t need to support full-trust applications; applications downloaded from the web are always partial trust.
- We don’t need interoperability with native or COM code.
- The versioning model is simpler: we only need one runtime at a time (we don’t need to ship older versions)
- CoreCLR can only be activated through a host (the Silverlight control): it doesn’t need to be activated through an executable or a COM object.
The Silverlight architecture is fundamentally the same: the same architectural boxes are present (albeit the surface area is much smaller in each case), with the exception of NGEN and profiling API support. The JIT does a minimum of optimization to improve startup time and reduce code size. The server-optimized garbage collector is removed, since it isn’t required; the reflection engine is substantially reduced, and Silverlight relies on the underlying operating system for collation string tables that are already standardized.
But that wasn’t enough. To get the CoreCLR down to its target size of 2MB, a good proportion of the size savings had to come from the base class library. CoreCLR includes a subset of the base class library called Small BCL. As with the rest of CoreCLR, Small BCL is built from the same source code as the full .NET BCL.
CoreCLR Security Model
One other area that has contributed significant code size savings is the notion of transparent libraries. The full desktop .NET supports Code Access Security, a very rich but complex security model. The CoreCLR security model makes reasoning about security much easier. There are three layers of code:
- SecurityCritical code: this is code that has full trust (for example, accessing native code through P/Invoke or changing an application’s global state). It also trusts any code that calls it, but can only be accessed by SafeCritical code.
- SafeCritical code is the bridge between SecurityCritical code and the outside world; it should always verify the input from any code that calls it.
- Transparent code is the code that can call into SafeCritical APIs in the Silverlight runtime. This is the only layer that can exist outside of the Silverlight runtime.
Along with the transparent code that a developer compiles into a XAP, the same concept is used for other libraries like LINQ and the DLR as well as many controls; this means that they don’t need to be installed as part of the Silverlight runtime itself but can be downloaded on-demand as part of the application download on request. In Silverlight 3, transparent libraries can be cached so they only have to be downloaded once.
In one critical way the CoreCLR in Silverlight has to do more than the full .NET CLR: it has to run on Mac OS as well as Windows. This is implemented through a Platform Abstraction Layer (PAL), based on the work done some years ago for a research project called Rotor. The PAL can be fairly simple because Silverlight only needs to support the x86 instruction set. Again, this is checked into the main CLR codebase, but is only required for the CoreCLR implementation.