Multithreading and the Singleton Pattern

In December of last year, as part of my undergraduate thesis, I developed a piece of software that statistically extrapolated electrical network data. This software required a lot of simulations - I needed a year’s worth of data at 15 minute intervals.

Doing the math:

365 days ✕ 24 hours ✕ 4 measurements/hour = 35040

Each simulation took 2.5 seconds to run, and so those 35040 simulations were going to take just over a day to run.

I was at a stage about a week out from the end of the project, and a spare day just to run simulations wasn’t really viable.

So, I did what any programmer would do - I tried to parallelise my application.

The simulator I was using, however, wasn’t particularly keen on the idea - turns out, the API implements a singleton pattern. Just for the record - it was not an appropriate choice in this situation (I’m not really sure it’s ever a great choice actually).

If I was going to parallelise this application, I was going to have to multi-process it.

Inter-process Communication

The basic procedure is:

That’s fine, but it’s a lot of boilerplate code - what if there was a way to automate it?

Aspect-Oriented Programming with PostSharp

PostSharp is a great developer tool, based on the idea of applying attributes to .NET code that somehow modify the behaviour of the attribute target. I wondered if it was possible to write a ‘RunOutOfProcessAttribute’ that could just be slapped on top of a class to force it to run in another process?

Turns out it is: PostSharp has an aspect (MethodInterceptionAspect) that pulls the method body out of a method, replaces it with your custom code, and then allows you to call the method body later.

For our purposes, what we need to do in that custom code is:

Use Procedure

The basic use procedure is:

  1. Add a new Exe project to your solution.
  2. Add classes to the Exe.
  3. For each class that you want to run out-of-process:
  4. Mark the class with the [RunOutOfProcess] attribute.
  5. Make sure the class implements IDisposable.
  6. Make sure that no initialisation logic is in the constructor - instead, just put in a call to an Init() function with the same parameters as the constructor. (this is a workaround for a PostSharp quirk)
  7. Mark your Init() function with the [Initializer] attribute.
  8. In the Exe entry point, simply add a call to IPCTK.OutOfProcessHandler.Loop(arg0, arg1);, where arg0 and arg1 are the first and second command-line parameters respectively.

Then, just add a reference to your new Exe project and start using the classes. Any classes marked with [RunOutOfProcess] will be… erm, Run Out Of Process.

A Couple of Useful Bits and Pieces

Attribute Targeting

MethodInterceptionAspects apply only to methods, not to classes. To ensure that we can put [RunOutOfProcess] on classes and obtain the desired behaviour, we define the RunOutOfProcessAttribute as follows:

[Serializable] //Required by PostSharp
//target all methods of class...
[MulticastAttributeUsage(MulticastTargets.Method)]
//...but only allow the attribute to be applied to the class
[AttributeUsage(AttributeTargets.Class)]
public sealed class RunOutOfProcessAttribute : MethodInterceptionAspect

We then add the following CompileTimeValidate hook, which silently ignores private/protected member functions:

//Applies the attribute only to:
// classes implementing IDisposable,
// only on public methods,
// or on methods marked with [Initializer]
public override bool CompileTimeValidate(MethodBase method)
{
  if (method.DeclaringType.GetInterface("IDisposable") == null)
    throw new InvalidAnnotationException(
        "Class must implement IDisposable " + method.DeclaringType);

  if (!method.Attributes.HasFlag(MethodAttributes.Public) // not public
      && !MethodMarkedWith(method,typeof(InitializerAttribute))) //not constructor
    return false; //silently ignore.

  return true;
}

Serialisation

IPCTK works by serialising/deserialising the arguments to and return values from methods and sending these along anonymous pipes. As such:

NetSerialiser would probably offer a good performance improvement, at the expense of being unable to serialise implementers of ISerializable. Maybe I’ll look into this in a future version.

More Info

For more information, take a look at the IPCTK project page on github.