While I was writing the Drawing API chapter in my new book I had to do some benchmarks. The first thing which came to my mind was comparing the new methods like drawPath, drawTriangles with the classics moveTo and lineTo methods.
So here is the kind of code I tried :
var container:Shape = new Shape();
var currentTime:Number = getTimer();
for (var i:int = 0; i< 15000; i++)
{
container.graphics.clear();
container.graphics.beginFill ( 0x990000, 1 );
container.graphics.drawPath ( commands, coords );
}
// outputs : 16
trace( getTimer() - currentTime );
With the code above, it took around 16ms to execute. Then, I did the same test with old methods :
var container:Shape = new Shape();
var currentTime:Number = getTimer();
for (var i:int = 0; i< 15000; i++)
{
container.graphics.clear();
container.graphics.beginFill ( 0x990000, 1 );
container.graphics.moveTo ( coords[0], coords[1] );
container.graphics.lineTo ( coords[2], coords[3] );
container.graphics.lineTo ( coords[4], coords[5] );
container.graphics.lineTo ( coords[6], coords[7] );
container.graphics.lineTo ( coords[8], coords[9] );
container.graphics.lineTo ( coords[10], coords[11] );
}
// outputs : 31
trace( getTimer() - currentTime );
As we can see, the drawPath method is actually faster than the classic moveTo and lineTo methods, which is quite logical cause we need less lines of code to produce the same result. But there is something important that we have to keep in mind.
What is actually faster here ?
What we are measuring here is not rendering time but the time it takes to push all the commands to the renderer. With the test above, we see that the execution time is faster with drawPath but we don't know yet in terms of rendering time. Don't forget that Flash Player rendering is asynchronous, so rendering will occur on next frame and we have to take care of that.
The trick is to force the Flash Player to call the renderer synchronously. The only method which can do that for us is BitmapData.draw(). So if you want to measure rendering time performance you would write the following :
var bitmap:BitmapData = new BitmapData ( 400, 400 );
var container:Shape = new Shape();
for (var i:int = 0; i< 15000; i++)
{
container.graphics.clear();
container.graphics.beginFill ( 0x990000, 1 );
container.graphics.drawPath ( commands, coords );
}
var currentTime:Number = getTimer();
// forces the player to render graphics synchronously
bitmap.draw ( container );
// outputs : 1
trace( getTimer() - currentTime );
If we then calculate rendering time with old methods :
var bitmap:BitmapData = new BitmapData ( 400, 400 );
var container:Shape = new Shape();
for (var i:int = 0; i< 15000; i++)
{
container.graphics.clear();
container.graphics.beginFill ( 0x990000, 1 );
container.graphics.moveTo ( coords[0], coords[1] );
container.graphics.lineTo ( coords[2], coords[3] );
container.graphics.lineTo ( coords[4], coords[5] );
container.graphics.lineTo ( coords[6], coords[7] );
container.graphics.lineTo ( coords[8], coords[9] );
container.graphics.lineTo ( coords[10], coords[11] );
}
var currentTime:Number = getTimer();
// forces the player to render graphics synchronously
bitmap.draw ( container );
// outputs : 1
trace( getTimer() - currentTime );
If we want to have a global benchmark, including commands submit and rendering time we could write :
var bitmap:BitmapData = new BitmapData ( 400, 400 );
var container:Shape = new Shape();
var currentTime:Number = getTimer();
for (var i:int = 0; i< 15000; i++)
{
container.graphics.clear();
container.graphics.beginFill ( 0x990000, 1 );
container.graphics.drawPath ( commands, coords );
}
// forces the player to render graphics synchronously
bitmap.draw ( container );
// outputs : 17
trace( getTimer() - currentTime );
So the final conclusion is that drawPath or drawTriangles gives better performance than traditional moveTo, lineTo in terms of ActionScript code execution. So you will get nice improvements with the new Graphics methods if most of the time you were wasting was sending the commands to the renderer. Otherwise in terms of rendering performance, the new Graphics methods does not really bring any performance improvements.
Thank you Lee from the Flash Player team for telling me about the BitmapData.draw() synchronous trick