For a recent project I created a performance graph which helped me to identify which parts of my engine were responsible for performance issues. Based on that, I have developed a flexible PerformanceMonitor class which can expanded on to track performance in a number of ways. The default implementation produces a pair of graphs like so.

Each colour corresponds to a different task that my application performs. Perhaps blue represents AI execution time, red represents rendering, and teal represents mouse handling. The graph on the left reports the time spent on each task I am tracking per update. The green area gives me an indication of whether Flash is dropping frames due to the execution time of my code. On the right is a bar graph showing the relative weight of each task over the lifetime of the application. More details on use after the cut.

Get it from GitHub.

There are a few simple steps to tracking performance with this tool. The first is to create the graphs themselves.

The GraphTimePerUpdate graph is configured with a target time per update, which should be chosen depending on your frame rate. The limit specified in the next line controls the scale of the graph. In this example, an update which uses exactly 99 units of time will fill the whole vertical height of the graph. Then we create the display at the desired size and add it to the stage.

private function createPerUpdateGraph():void
{
	_perUpdateGraph = new GraphTimePerUpdate();
	_perUpdateGraph.targetTimePerUpdate(33);
	_perUpdateGraph.limitTimeForDisplay(99);
	var graphData:BitmapData = _perUpdateGraph.createDisplay(300,200);
	var graphBitmap:Bitmap = new Bitmap(graphData);
	addChild(graphBitmap);
}

Creating the GraphTotalTimeSpent graph is a much simpler process. We only need to create the display and add it to the stage.

private function createTotalGraph():void
{
	_totalGraph = new GraphTotalTimeSpent();
	var graphData:BitmapData = _totalGraph.createDisplay(24, 200);
	var graphBitmap:Bitmap = new Bitmap(graphData);
	graphBitmap.x = 300;
	addChild(graphBitmap);
}

With our two graphs constructed, we need to configure the PerformanceMonitor that drives them. The first three lines declare the performance metrics that will be tracked, and what colours to use when rendering them. The following lines plug the graphs into the PerformanceMonitor to receive updates.

private function configureMonitor():void
{
	var monitor:PerformanceMonitor = PerformanceMonitor.instance;
	monitor.initializePerformanceMetric("rendering", 0, 0xff0000);
	monitor.initializePerformanceMetric("ai", 1, 0x0000ff);
	monitor.initializePerformanceMetric("mouse", 2, 0x00ffff);
	monitor.addReporter(_perUpdateGraph);
	monitor.addReporter(_totalGraph);
}

With that configured, the PerformanceMonitor is ready to go. All that remains is to report metrics and tell the PerformanceMonitor to update. For this example, I am just randomizing the first two metrics and basing the second off of mouse movement in order to illustrate how to report them. Normally you would use getTimer to determine the time to execute some complex functionality and then report the result of that.

private function handleEnterFrame(in_event:Event):void
{
	PerformanceMonitor.instance.recordPerformanceMetric(0, Math.random()*5 + 10);
	PerformanceMonitor.instance.recordPerformanceMetric(1, Math.random()*5);
	PerformanceMonitor.instance.update();
}

private function handleMouseMove(in_event:MouseEvent):void
{
	var xDiff:Number = mouseX - _lastX;
	var yDiff:Number = mouseY - _lastY;
	var distance:Number = Math.sqrt((xDiff*xDiff)+(yDiff*yDiff)); 
	PerformanceMonitor.instance.recordPerformanceMetric(2, distance);
	_lastX = mouseX;
	_lastY = mouseY;
}