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.
The basic procedure is:
- Spawn a child process (in this case, the simulator)
- Connect some anonymous pipes between the child and parent processes
- Use stream-based I/O for communication between processes.
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:
- Test to see if this code is running in-process or out-of-process
- If it’s running in-process, forward the call to our external process
- If it’s running out-of-process, run the code, and forward the result back to the calling process.
The basic use procedure is:
- Add a new Exe project to your solution.
- Add classes to the Exe.
- For each class that you want to run out-of-process:
- Mark the class with the
- Make sure the class implements
- 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)
- Mark your
Init()function with the
- In the Exe entry point, simply add a call to
IPCTK.OutOfProcessHandler.Loop(arg0, arg1);, where
arg1are 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
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:
We then add the following CompileTimeValidate hook, which silently ignores private/protected member functions:
IPCTK works by serialising/deserialising the arguments to and return values from methods and sending these along anonymous pipes. As such:
- The toolkit is most useful when the ratio of expected compute time to input/output size is high.
- If anything needed to be optimised ever, it was serialisation for this purpose.
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.
For more information, take a look at the IPCTK project page on github.