Powered by Mono

Mono with CGI on shared hosts

by Marek Habersack 1. June 2009 23:32

Some of you might want to run Mono on a shared (virtual) Linux host but your ISP/hosting company doesn't let you install mod_mono or Apache FastCGI modules. Kornél Pál has just contributed a piece of documentation which explains how to host Mono applications on CGI-only boxes without incurring the high CGI cost.

Tags:

Mono | ASP.NET | mod_mono

Tip: Mono ASP.NET application burning CPU in idle state - FileSystemWatcher

by Marek Habersack 13. May 2009 15:40

Update: added sample code to detect the watcher in use, courtesy of Robert Jordan - thanks!

mod_mono is an Apache module for hosting ASP.NET applications. The module itself doesn't run any .NET code, instead it spawns a backend server (mod-mono-server.exe for ASP.NET 1.1 and mod-mono-server2.exe for ASP.NET 2.0) which is handed all the requests coming in from the client browser and sends back response generated by the application.

If you run Mono on a VPS server (e.g. Xen, OpenVZ) then you don't usually have any control over what Linux kernel version and with what capabilities you run. It may happen that the kernel lacks capabilities used by parts of the Mono runtime and Mono will have to fall back to other methods of doing the same task. One such part is the FileSystemWatcher class which is used to monitor changes to files/directories on disk so that the application can take any steps it deems necessary in reaction to file creation/deletion/modification events.

Mono's FileSystemWatcher does its best to perform its assigned task in various environments, under various operating systems. Part of the effort is selecting the actual filesystem monitoring backend best for the runtime environment. Under Unix the supported backends are as follow:

  • FAM
  • kevent (BSD*/MacOSX only)
  • gamin
  • inotify (Linux only)
  • Managed watcher
Out of those, assuming you run Linux, inotify is the preferred backend mechanism as it requires no polling effort on userland application part, instead the Linux kernel will notify the application (in our case the Mono runtime) whenever interesting events happen. However, it requires the Linux kernel to support the mechanism and, what's more important, for your VPS operator to actually include the support in the kernel your VPS runs on.

If your kernel doesn't support inotify, Mono will attempt to use FAM and Gamin which are userland daemons doing active filesystem polling but outside of the consumer application. The consumer application will use provided FAM/Gamin libraries to receive events and react to them. Performance of this setup is worse than inotify but not tragic.

Should Mono fail to detect inotify, FAM or Gamin support, it will fall back to the last resort option - the managed watcher. This watcher is implemented in managed code and uses a separate thread for filesystem monitoring, polling for changes on selected files/directories. As the application may (and in the case of ASP.NET sometimes does) watch directories recursively, it might be a very expensive situation requiring checking changes to a big set of files. Each change detection run requires checking whether a file/directory exists (in case of the Managed watcher those are two stat (2) calls) and then checking the file metadata for changes (size, modification times etc) and, possibly, generating an event. This happens approximately every 750ms and can generate substantial load on the server's CPU.

If you notice (using top or htop applications) that your copy of mod-mono-server burns several per-cent of CPU but is otherwise in the S (Sleeping) process state, chances are your application is using the managed watcher. You can confirm that by using htop which allows you to watch individual process threads - you will see two threads consuming nearly the same amount of CPU time and one of them waking up every ~750ms.

The cure for the itch is easy, if you can live without filesystem monitoring (that means your application will not auto-restart when you modify Web.config, files won't be recompiled if you modify a code-behind .cs or an .aspx, .ascx etc. files). Mono supports a MONO_MANAGED_WATCHER environment variable which can be set to value disable with the effect of definitely disabling filesystem monitoring (it will use a "dumb" implementation of the watcher backend which does nothing) and relieve your application of the filesystem polling chores described above.

You can set the environment variable for your Apache VirtualHost by using the following mod_mono directive:

MonoSetEnv [server_alias] MONO_MANAGED_WATCHER=disable

Sample program to detect which watcher backend is used:

using System;
using System.Reflection;
using System.IO;

class Program {

    public static void Main()
    {
        object watcher = new FileSystemWatcher()
            .GetType ()
            .GetField ("watcher", BindingFlags.NonPublic | BindingFlags.Static)
            .GetValue (null);
        
        Console.WriteLine (watcher != null
                   ? watcher.GetType ().FullName
                   : "unknown");
    }
}

Tags:

Mono | mod_mono | Tip

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen | Modified by Mooglegiant