Measuring Drawing API 2.0 performance by Thibault Imbert

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 ;)

Comments (6)

  1. Goach wrote::

    Salut Thibault,

    J’ai voulu m’offrir ton livre pour Noel et je ne l’ai pas trouver :( C’est noel et je recherche ma bible ;)
    Snif snif !
    J’espere le voir prochainement dans une bonne epicerie ;)

    Joyeux noel a toi !

    Thursday, December 25, 2008 at 9:37 am #
  2. Thibault Imbert wrote::

    Salut Seb,

    C’est pour bientôt, il est prévu pour février. Ca sera pile poil après la digestion des repas de fêtes ;)

    Thibault

    Thursday, December 25, 2008 at 2:08 pm #
  3. Pure wrote::

    Bonnes fêtes,
    comme d’habitude une super analyse.
    Merci merci.

    Saturday, December 27, 2008 at 2:53 am #
  4. Armetiz wrote::

    Salut par ici,
    Quelque chose que je n’ai pas bien compris, le synchrone/asynchrone.

    Le flash player exécute de manière asynchrone la partie graphique et l’exécution du code, c’est cela ?

    L’utilisation de la méthode BitmapData.draw () force une synchronisation des deux à un instant T (la ligne d’appel), et ensuite le traitement reprend son asynchronomité (nouveau mot :p) ?

    Je n’avais jamais fait attention à cela, mais il n’existe pas de méthode flush () qui aurai pu se trouver dans le package System, maintenant, BipmapData.draw (new BitmapData (0, 0)); permet de simuler un flush ()..
    Je m’égare je m’égare.. :p

    Joyeuses fêtes :D

    Wednesday, December 31, 2008 at 3:01 pm #
  5. Thibault Imbert wrote::

    Salut Armetiz,

    Exactement, le player exécute le code puis de manière asynchrone rend le contenu graphique à l’entrée de l’image suivante.

    La méthode BitmapData.draw() force le rendu graphique du player sur l’image en cours donc de manière synchrone.

    En effet, la méthode BitmapData.draw() peut être considérée comme un flush où les commandes passées au moteur de rendu sont toutes consommées et rendues immédiatement (lors de l’appel de la méthode).

    Bonnes fêtes ;)

    Thibault

    Wednesday, December 31, 2008 at 3:21 pm #
  6. ilja.panin wrote::

    Hi.

    Use more big cycle for test
    100 000, 1 000 000 and more iteration.

    1, 15, 31ms are not indicate faster method.

    For quality test this time must be 1000-3000 ms.

    Wednesday, January 14, 2009 at 1:45 am #

Trackbacks/Pingbacks (3)

  1. JapsBLog » Blog Archive » Performance da drawing API on Wednesday, December 24, 2008 at 6:53 pm

    [...] o link 24 Dec 08 | [...]

     
  2. [...] > Measuring Drawing API 2.0 performance by Thibault Imbert < ByteArray.org [...]

     
  3. IGraphicsData Example on Sunday, June 14, 2009 at 1:13 am

    [...] I decided to write this snippet to show just that it is rather fast. I also recalled reading some benchmark info for the new fp10 graphics stuff over at bytearray.org…. pretty nice info there… This entry was posted in Graphics, Vector, misc, motion and tagged [...]