Archive for January 5th, 2009

05
Jan
09

Measuring Drawing API 2.0 performance

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 :

  1. var container:Shape = new Shape();
  2. var currentTime:Number = getTimer();
  3. for (var i:int = 0; i< 15000; i++)
  4. {
  5. container.graphics.clear();
  6. container.graphics.beginFill ( 0×990000, 1 );
  7. container.graphics.drawPath ( commands, coords );
  8. }
  9. // outputs : 16
  10. trace( getTimer() - currentTime );

With the code above, it took around 16ms to execute. Then, I did the same test with old methods :

  1. var container:Shape = new Shape();
  2. var currentTime:Number = getTimer();
  3. for (var i:int = 0; i< 15000; i++)
  4. {
  5. container.graphics.clear();
  6. container.graphics.beginFill ( 0×990000, 1 );
  7. container.graphics.moveTo ( coords[0], coords[1] );
  8. container.graphics.lineTo ( coords[2], coords[3] );
  9. container.graphics.lineTo ( coords[4], coords[5] );
  10. container.graphics.lineTo ( coords[6], coords[7] );
  11. container.graphics.lineTo ( coords[8], coords[9] );
  12. container.graphics.lineTo ( coords[10], coords[11] );
  13. }
  14. // outputs : 31
  15. 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 :

  1. var bitmap:BitmapData = new BitmapData ( 400, 400 );
  2. var container:Shape = new Shape();
  3. for (var i:int = 0; i< 15000; i++)
  4. {
  5. container.graphics.clear();
  6. container.graphics.beginFill ( 0×990000, 1 );
  7. container.graphics.drawPath ( commands, coords );
  8. }
  9. var currentTime:Number = getTimer();
  10. // forces the player to render graphics synchronously
  11. bitmap.draw ( container );
  12. // outputs : 1
  13. trace( getTimer() - currentTime );

If we then calculate rendering time with old methods :

  1. var bitmap:BitmapData = new BitmapData ( 400, 400 );
  2. var container:Shape = new Shape();
  3. for (var i:int = 0; i< 15000; i++)
  4. {
  5. container.graphics.clear();
  6. container.graphics.beginFill ( 0×990000, 1 );
  7. container.graphics.moveTo ( coords[0], coords[1] );
  8. container.graphics.lineTo ( coords[2], coords[3] );
  9. container.graphics.lineTo ( coords[4], coords[5] );
  10. container.graphics.lineTo ( coords[6], coords[7] );
  11. container.graphics.lineTo ( coords[8], coords[9] );
  12. container.graphics.lineTo ( coords[10], coords[11] );
  13. }
  14. var currentTime:Number = getTimer();
  15. // forces the player to render graphics synchronously
  16. bitmap.draw ( container );
  17. // outputs : 1
  18. trace( getTimer() - currentTime );

If we want to have a global benchmark, including commands submit and rendering time we could write :

  1. var bitmap:BitmapData = new BitmapData ( 400, 400 );
  2. var container:Shape = new Shape();
  3. var currentTime:Number = getTimer();
  4. for (var i:int = 0; i< 15000; i++)
  5. {
  6. container.graphics.clear();
  7. container.graphics.beginFill ( 0×990000, 1 );
  8. container.graphics.drawPath ( commands, coords );
  9. }
  10. // forces the player to render graphics synchronously
  11. bitmap.draw ( container );
  12. // outputs : 17
  13. 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

05
Jan
09

Flasher video player with FLA source

I have just finished creating a simple custom video player for Flasher Magazine. It isn’t as full-featured as some players but I wanted to make it look and feel fairly raw to match the style of the videos. There is a basic click-to-seek functionality rather than a more traditional scrubber. Doing true scrubbing requires more work and in my opinion is not even that useful. You can download the source FLA file to see how it was made and also to use it in your own projects if you want. All I ask is that you change the style so it isn’t an exact duplicate of the one I use for Flasher.