Recently a situation came up with an application I was working on. My client had implemented a proprietary algorithm in a legacy desktop application. This algorithm is very compute intensive. It happened that it was an actuarial calculation, but the specifics don’t really matter. The computation was written in highly optimized C code.
In thinking about how to port this application to Azure it was clear to me that I did not want to re-write all that code! In fact that was not even an option. The client wanted to be sure that that specific code (which they knew and trusted) was what was executing. The solution I chose was to host the application natively in a worker role. That way I felt I could pretty much drop in the existing code, run it through the C++ compiler and linker and party on from within Visual Studio.
This post highlights some of the considerations that exist when implementing a worker role that hosts an application in this way. For my example here I have replaced the actuarial calculation with another intensive task: calculate pi to an arbitrarily large number of decimal places. For that algorithm I adapted some nifty C code posted on Planet Source Code. I also borrowed liberally from a project I found in the MSDN Code Gallery. Both of these are excellent resources.
The first thing I did was to create a new C++ project in Visual Studio. Then I dropped the algorithm code into a new source file. After verifying that the code compiled properly and functioned as expected I was ready to add a new cloud service project to the solution.
Since the C++ application (in this case it is called “MyPI”) is to be hosted in the worker role I added a link to the executable in the worker role project items. Setting the “Copy to Output Directory” property to “Copy if Newer” ensures that the latest bits for that program always get added to the deployment package.
Figure 1 – MyPI Solution
The architecture of the solution is pretty straightforward. The web role asks for the precision of the calculation. It then places that into a queue which is read by the worker role. The worker role launches the native process with the desired precision passed as a command line argument. Standard output is redirected into a StreamReader object which is read into a string variable in the worker role. This string (which may be very long!) is then uploaded to an Azure blob. Back in the web role, the blob is read back into a string and used to populate a text box.
Click here for the screencast.
As usual the actual production version of the code (and ultimate deployment to Azure!) was a little more complicated than presented here. Still, this simple demo gives an overview of how it is possible to leverage existing code written in C/C++ to port computationally intensive legacy applications to the Azure cloud.