Recently I was tasked with speeding up an Azure Worker Role. Once a night, a Worker Role would recalculate rates for each customer using data in their database. Some customers had a lot of data and the Worker Role would run for more than 16 hours recalculating their data. This Worker Role needs to be sped up, but where to start?
The easiest way to figure out where to start looking for optimizations is to profile the app. How do you do that you say? Profiling an Worker Role running in Windows Azure is actually pretty easy.
The Sample App
The Sample App provided is extremely small and does basically nothing. It’s just an example that can be used to show off profiling.
In the solution, there are the following projects:
- RecalculatorService – the Azure Service
- RecalculatorWorkerRole – the Worker Role for the service
- Recalculator – a separate assembly that contains the Recalc class that the Worker Role will use
As the Worker Role runs, it will spin in a loop, constantly creating an new instance of Recalc and calling Recalculate on it.
public override void Run()
{
Trace.WriteLine("RecalculatorWorkerRole entry point called", "Information");
while (true)
{
Recalc recalc = new Recalc();
recalc.Recalculate();
Trace.WriteLine("Working", "Information");
}
}
Here is the Recalc class in its entirety:
public class Recalc
{
public void Recalculate()
{
Debug.WriteLine("Recalculating");
foreach (DataValue value in values)
{
value.Calculate();
}
}
private readonly List<DataValue> values = new List<DataValue>()
{
new DataValue(), new DataValue(), new DataValue()
};
}
And here is the DataValue class:
public class DataValue
{
public void Calculate()
{
Debug.WriteLine("Calculating");
short int16MaxValue = Int16.MaxValue;
for (int i = 0; i < int16MaxValue; i++)
Debug.WriteLine(String.Format("Calculating... {0}", i));
}
}
Nothing too fancy. When Recalculate is called, it will loop through its list of DataValues and call Calculate on every one. The Calculate method of DataValue just loops and writes a message out to Debug.
Prerequisites
If you’re using Visual Studio 2010, you will need Visual Studio Premium or Ultimate. If you’re using Visual Studio 2012, every version except Test Professional should have the profiling tools available.
This post will be specific to Visual Studio 2010.
You should also have the Windows Azure 1.7 SDK and any of its dependencies. You can get this through the Web Platform Installer.
You may also want to setup your _NT_SYMBOL_PATH, but it shouldn’t be necessary for this post.
Profiling Locally
Now that we’re all setup and ready to go, open the sample solution and make sure it builds. Next, make sure that RecalculatorService is set as the Startup Project and run it from Visual Studio.
Running this project locally will start the Compute and Storage Emulators on your machine. When everything is loaded, you’ll start seeing messages in the Debug Output window as I runs.
Now that the service is running, we can profile it.
Open up the Performance Explorer window (View –> Other Windows –> Performance Explorer) and click the Attach button.
This will open up a window where you can select a process for the performance profiler to attach to. Scroll way down until you find “WaWorkerHost”, select it and click attach.
Once it has attached, it will open a view saying that it is profiling.
Once it’s had a chance to run for a few minutes, click the “Stop profiling” link. It will stop the application running in the Azure emulator and prepare a report.
If everything is setup correctly, you should see the profiling report appear.
When you profile the Azure application locally by attaching to it like we did above, you can profile it in two ways: Sampling and Concurrency.
The profiling report we generated we generated is a Sampling report. This profiling method “samples” the application periodically to see what the application is doing. It’s non-invasive and can give you a good feel on where to start looking for optimizations because it will tell you where the application seems to be spending most of it’s time.
A Concurrency profiling report will show you what your application threading looks like. It can be used to see where an application might be blocking. It can be generated using the same method as above, but when you go to Attach to the WaWorkerHost, you’ll have to create a new Performance session and select Concurrency in the pull down before clicking the Attach button.
Profiling in the Cloud
Profiling in the cloud is just a little bit easier than profiling locally. In order to profile in the cloud, you must use Visual Studio to publish your application to the cloud.
When you are going through the Publish wizard, go to the Advanced Settings tab and enable profiling.
You can also go into the profile settings to pick which type of profiling you want to use.
Once you have that setup and your application is published to Azure, you can right click on your service instance in the Server Explorer and select “View Profiling Report”.
After that, it’s just the same as before. Visual Studio will download the profiling report, analyze and open it.
Simple, right?
Wrapup
In this post, we’ve seen how we can profile and Azure application both locally and in the cloud. If you’d like to read more about profiling in general, MSDN has some good documentation.