devxlogo

Productivity Improvements in Mono 2.4: Components and Architecture

Productivity Improvements in Mono 2.4: Components and Architecture

ono is an open source .NET development framework based on the ECMA standards for the Common Language Infrastructure (CLI) Led by Novell, the Mono project creates a .NET-compatible set of tools that enable developers to build Linux and cross-platform applications, including a C# compiler and a Common Language Runtime (CLR), that run on Linux, BSD, UNIX, Mac OS X, Solaris, and Windows. (See Figure 1 for a high-level view of the Mono 2.4 architecture.)

Figure 1. Mono 2.4 Architecture: Here is a high-level view of the Mono 2.4 architecture.

Mono’s current version is 2.4 (as of March 30, 2009). This version provides the core API of the .NET Framework, as well as support for Visual Basic.NET and C# versions 2.0 and (partially) 3.0. LINQ to objects and XML are part of the distribution, but LINQ to SQL isn’t. C# 3.0 is now the default mode of operation for the C# compiler, and Windows Forms 2.0 is also now supported.

An implementation of .NET Framework 3.0 is under development in an experimental Mono subproject called “Olive,” but a release date for a Mono framework supporting .NET 3.0 has not been announced yet. (Click here to read a brief history of Mono.)

This article explains how to install Mono 2.4 for Windows and then dives into the new version’s components and architecture.

Mono 2.4 Installation Overview

To run Mono 2.4 in Windows, you must install the following components:

  • Microsoft .NET Framework Version 3.5
  • GTK# for .NET Version 2.12.9-2
  • MonoDevelop Version 2.1.r136446 (see Figure 2)
  • Mono Libraries r135450 (only required for building MonoDevelop from sources)

Click here to download all the necessary components (see Figure 3).

You can download Mono source code from the Novell FTP site (see Figure 4).


Figure 2. Mono Development Environment: Here is a screenshot of the MonoDevelop Graphical Editor.
 
Figure 3. Required Mono Component Downloads for Windows Platform: Here are all the necessary Mono components for Windows.
 
Figure 4. Mono Source Code Location for Download: You can download Mono source code from the Novell FTP site.

Mono has support for both 32- and 64-bit systems on a number of architectures, as well as a number of operating systems. Mono also contains a number of components that are useful for building new software:

  • A Common Language Infrastructure (CLI) virtual machine that contains a class loader, just-in-time (JIT) compiler, and a garbage-collecting runtime
  • A class library that can work with any language that works on the CLR (both .NET-compatible class libraries and Mono-provided class libraries are included)
  • A compiler for the C# language (In the future, Mono might develop other compilers that target the Common Language Runtime.)
Figure 5. Mono Components After Download: Here are all the Mono 2.4 components downloaded to a single folder.

The CLR and the Common Type System (CTS) enable you to write applications and libraries in a number of different languages that target the byte code. This means, for example, that if you define a class to do algebraic manipulation in C#, that class can be reused from any other language that supports the CLI. You could create a class in C#, subclass it in C++, and instantiate it in an Eiffel program. A single object system, threading system, class libraries, and garbage-collection system can be shared across all these languages.

The MonoDevelop component is an IDE primarily designed for C# and other .NET languages. MonoDevelop enables developers to quickly write desktop and ASP.NET web applications on Linux. It makes it easy for developers to port .NET applications created with Visual Studio to Linux and to maintain a single code base for all platforms.

Figure 5 shows all the Mono 2.4 components downloaded to a single folder.

Mono 2.4 Components

Mono 2.4 consists of three groups of components:

  • Core components
  • Mono/Linux/GNOME development stack
  • Microsoft compatibility stacks

The core components include the C# compiler, the virtual machine, and the base class libraries. These components are based on the Ecma-334 and Ecma-335 standards, allowing Mono to provide a standards-compliant, free and open source CLI virtual machine.

The Mono/Linux/GNOME development stack provides tools for application development, while leveraging existing GNOME and free and open source libraries such as:

  • Gtk# for GUI development
  • Mozilla libraries for working with the Gecko rendering engine
  • UNIX integration libraries
  • Database connectivity libraries
  • A security stack
  • The XML schema language RelaxNG

Gtk# allows Mono applications to integrate into the GNOME desktop as native applications. The database libraries provide connectivity to MySQL, SQLite, PostgreSQL, Firebird, Open Database Connectivity (ODBC), Microsoft SQL Server (MSSQL), Oracle, the object-relational database db4o, and many others. The Mono project tracks developing database components at its web site.

The Microsoft compatibility stack provides a pathway for porting Windows .NET applications to Linux. This group of components includes ADO.NET, ASP.NET, and Windows Forms, among others. As these components are not covered by ECMA standards, some of them remain subject to patent protection.

C# Compiler

The Mono C# compiler (MCS) is considered feature complete for C# versions 1.0, 2.0, and 3.0. The compiler is able to compile itself and many more C# programs. It is routinely used to compile Mono?roughly four million lines of C# code?and a few other projects. The compiler is also fairly fast. On an IBM ThinkPad t40, it compiles 18,000 lines of C# code per second. You can also use the compiler as a service by using the Mono.CSharp.Evaluator class in the Mono.Sharp.dll assembly. Starting with Mono version 2.6, a new compiler dmcs will be available as a preview of C# 4.0 (it is a preview because Mono 2.6 will ship before C# 4.0 is finalized).

The compiler performs a number of simple optimizations on its input, including constant folding (which is required by the C# language spec) and dead-code elimination. Other more interesting optimizations, such as hoisting, are not possible yet because the compiler output at this point does not generate an intermediate representation that is suitable to perform basic block computation.

Adding an intermediate layer to enable basic block computation to the compiler should be a simple task, but the Mono team is considering having a generic CIL optimizer. Because all the information required to perform basic block-based optimizations is available at the CIL level, the Mono team might just skip this step altogether and have just a generic CIL optimizer that would perform hoisting on arbitrary CIL programs, not only those produced by MCS.

If this generic IL optimizer is further expanded to perform constant folding (not needed for the MCS, as it is already in there) and dead-code elimination, other compiler authors might be able to use this tool in their projects, reducing their time to develop a production compiler.

The Mono Runtime

The Mono runtime engine provides a JIT, an Ahead-of-Time compiler (AOT), a library loader, a garbage collector (the Boehm conservative garbage collector), a threading system, and interoperability functionality. You can use the Mono runtime as a stand-alone process, or it can be embedded into applications.

Embedding the Mono runtime allows applications to be extended in C# while reusing all of the existing C and C++ code.

Compilation Engine

The Mono developers have re-written the JIT compiler to support a number of features that were missing: AOT compilation, simple porting, and a solid foundation for compiler optimizations. The idea of AOT compilation is to allow developers to pre-compile their code to native code to reduce startup time, and to compile the working set that is used at runtime in the just-in-time compiler. When an assembly (a Mono/.NET executable) is installed in the system, it is then possible to pre-compile the code, and have the JIT compiler tune the generated code to the particular CPU on which the software is installed. In the .NET world, you do this with a tool called ngen.exe.

The code produced by Mono’s AOT compiler is Position Independent Code (PIC), which tends to be a bit slower than regular JITed code, but what you lose in performance you gain by being able to use all the available optimizations.

Bundles

Mono also offers bundles. Bundles merge your application, the libraries it uses, and the Mono runtime into a single executable image. You can think of bundles as “statically linking Mono” into your application.

Platform for Code Optimizations

Beyond the use of the Mono VM as JIT compiler, the Mono team needs to make Mono code generation as efficient as possible. Such a design called for a good architecture that would enable various levels of optimizations; some optimizations are better performed on high-level intermediate representations, some on medium-level, and some at low-level.

Also, you should be able to turn these on or off conditionally. Some optimizations are too expensive to be used in JIT compilation scenarios, but they can be turned on for AOT compilations or when using profile-guided optimizations on a subset of the executed methods.

Garbage Collection

Mono today uses Boehm’s GC as its garbage collection engine. The Mono development team is also working on a precise and compacting GC engine specific to Mono. The GC interface is being isolated to allow for more than one GC engine to be used or for the GC to be tuned for specific tasks.

The GC scans a few areas for pointers to managed objects:

  1. The heap (where other managed objects are allocated) ? The heap is currently handled in a mostly precise mode. The GC almost always will consider only memory words that contain only references to the heap, so there is very little chance of pointer misidentification and hence memory retention. The new GC requires a fully precise mode to improve things marginally. The details about mostly precise have to do with large objects with sparse bitmaps of references and the handling of multiple AppDomains safely.
  2. Thread stacks and registers ? These are always scanned conservatively. This will be true for the new GC too (at least for the initial versions, where the mono team will have to track the bugs that a moving generational GC will expose). Later, they will conservatively scan only the unmanaged parts of the stacks.
  3. The static data area ? The Mono team already optimized this both with Boehm and the current GC to work in precise mode.
  4. Data structures allocated by the runtime ? The Mono team already optimized this to work in mostly precise mode (i.e., some data structures are dealt with precisely, others not yet). The team needs to do more work in this area, especially for the new GC, where having pinned objects can be a significant source of pain.

Compacting GC

The Mono team is developing a new generational, precise, and compacting GC, which is currently available from SVN releases of Mono. This new compacting GC was implemented to work around some of the limitations in a purely conservative collector, specifically the memory consumption caused by heap fragmentation.

Although this GC is currently available on SVN, it is not a supported configuration and will not be a supported configuration for the Mono 2.4 release. It is available for developers who might be interested in testing their applications or who might want to work on it.

The implementation details are available on the Mono Compacting GC page.

Optimizations

The JIT engine implements a number of optimizations:

  • Opcode cost estimates (the architecture allows the Mono team to generate different code paths dynamically depending on the target CPU).
  • Inlining
  • Constant folding, copy propagation, and dead-code elimination (Although compilers typically do constant folding, the combination of inlining with constant folding produces some very good results.)
  • Linear scan register allocation
  • SSA-based framework (Various optimizations are implemented on top of this framework.)

The Mono team continues to improve its engine, but many optimizations can not be effectively done by the runtime. You will get very good results if you profile and study your application patterns. Read the Mono performance tips article for various ideas on how to tune your software.

Mono 2.4 Architecture

This section describes the pieces of the Mono 2.4 architecture (as shown in Figure 1).

Just-in-Time Engine

The Mono runtime contains a JIT engine for a number of processors: MIPS (in 32-bit mode only), x86, SPARC, PowerPC, ARM, S390 (in 32-bit and 64-bit modes), and x86-64 and IA64 for 64-bit modes. The runtime will perform a just-in-time compilation to the machine’s native code, which is cached as the application runs. It is also possible to precache the native image before execution.

However, Mono’s current conservative garbage collector (the “Boehm-Demers-Wiser Conservative Garbage Collector”) presents a serious drawback compared to commercial garbage-collected runtimes such as the Java Virtual Machine or the .NET framework’s runtime. Theoretically, you could run into memory leaks that may even result in an abrupt end to an application’s execution due to an out-of-memory condition. This is especially a grave concern for server applications meant to run for a long time. The Mono team is currently developing a modern, “real” garbage collector, but a date for incorporation into a production release has not been set.

Class Library

The class library provides a comprehensive set of facilities for application development. They are primarily written in C#, but due to the Common Language Specification they can be used by any .NET language. The class library is structured into namespaces and deployed in shared libraries known as assemblies. References to the .NET framework are primarily references to this class library.

Namespaces and Assemblies

Namespaces are a mechanism for logically grouping similar classes into a hierarchical structure. This prevents naming conflicts. The structure is implemented using dot-separated words, where the most common top-level namespace is System, such as System.IO and System.Net. There are other top-level namespaces as well, such as Accessibility and Windows. A user can define a namespace by placing elements inside a namespace block.

Assemblies are the physical packaging of the class libraries. These are .dll files, just as (but not to be confused with) Win32 shared libraries. Examples of assemblies are mscorlib.dll, System.dll, System.Data.dll, and Accessibility.dll. Namespaces are often distributed among several assemblies, and one assembly can be composed of several files.

Common Language Infrastructure and Common Language Specification

The Common Language Infrastructure (CLI)?more commonly known as the Common Language Runtime (CLR)?is implemented by the Mono executable. The runtime is used to execute compiled .NET applications. The common language infrastructure is defined by the ECMA standard. To run an application, you must invoke the runtime with the relevant parameters.

The Common Language Specification (CLS), specified in chapter 6 of ECMA-335, defines the interface to the CLI, such as conventions like the underlying types for Enum. The Mono compiler generates an image called the Common Intermediate Language that conforms to the CLS. The Mono runtime takes this image and runs it. The ECMA standard formally defines a library that conforms to the CLS as a framework.

Managed and Unmanaged Code

Within a native .NET/Mono application, all code is managed; that is, it is governed by the CLI’s style of memory management and thread safety. Other .NET or Mono applications can use legacy code, which is referred to as unmanaged, by using the System.Runtime.InteropServices libraries to create C# bindings. Many libraries that ship with Mono, such as Gtk#, use this feature of the CLI.

The Mono Option

Mono is an open source product that is still in a constant improvement phase. Hopefully, the open source and .NET development communities will benefit from the Mono platform. For users who want to run projects at a low cost based on a rapid web application development framework, Mono is one of the best options available.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist