Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web

The Odd Results From Trying to Performance Test... Circles

3.10/5 (5 votes)
24 Oct 2013CPOL2 min read 13.2K  
This little bit of code is an attempt to illustrate the performance difference between using a constant vs. always using 2*Math.PI when using the .arc() method to draw a circle to a canvas.

Introduction

Drawing (a lot) of circles (or anything for that matter) on a particular HTML5 canvas can really bog down performance. This little bit of code is an attempt to illustrate the performance difference between using a constant vs. always using 2*Math.PI when using the .arc() method to draw a circle to a canvas.

Background

I have a project that involves drawing an insane amount of circles to an HTML5 canvas element. During development, I ran into a performance issue. The number of circles drew went up almost exponentially at one point and so the performance went down (exponentially) at the same time.

The performance issue itself has since been solved by other means, but when the issue arose, it prompted me to write this little bit of JavaScript code.

I figured I could save some time by calculating 2 * Math.PI and placing the result into a variable to be called by a draw circle function, vs. having the code calculate the number every time drawCircle() as called. So... I wrote a quick script, the results were counter intuitive to me... so I thought I'd share them.

Using the Code

I'm going to illustrate the entirety of the script (it's fairly small) so you can run this on your own. You can take the sections of code I place here and either dump it in an HTML file between <script></script> tags or a separate .js file... as you wish.

The script itself creates the Canvas element, so there really aren't any HTML requirements besides having an empty HTML page.

First, let's go ahead and set up our canvas and then create our context:

This will give us something to draw on...

JavaScript
// Create a canvas element.
var canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
document.body.appendChild(canvas);
// Set the context
var ctx = canvas.getContext("2d");

Now, let's create some basic variables to control the test and hold the results:

JavaScript
// Some basic variables for time tracking and loop 
// control.
var startTime;                 //Time each loop starts
var timeList = new Array();    //Array to store the time difference between start and end
var timeList2 = new Array();   //Same as above for the second loop 
var circleDraws = 1000;        //How many times to draw a circlce per test set
var testLoops = 10;            //How many times to run the circle test loops
var preCalcTP = 6.28318530718  //Pre Calculated 2*Math.PI

Create a function to draw a circle:

JavaScript
//Draws a simple circle
//tpr = 2 * pi (where we normally would put 2*Math.PI
var drawCircle = function(tpr) {        
    ctx.beginPath();        
    ctx.arc(50,50,50,0,tpr);
    ctx.stroke();
};

Put some loops in place to draw the circles:

JavaScript
//First test set where we test if putting the
//previously calculated 6.28318530718 
for (x = 0; x < testLoops; x++){      
    //Clear the canvas
    ctx.clearRect(0,0,canvas.width,canvas.height);
    //Capture the start time
    startTime = Date.now();
    //Draw a circle i times
    for (i = 0; i <= circleDraws; i++)
     {
      drawCircle(preCalcTP);        
    }
    //Capture the time difference in an array
    timeList.push(Date.now() - startTime)
}

//Second test set where we put in the normal
//Math.PI * 2
for (x = 0; x < testLoops; x++){    
    //Clear the Canvas
    ctx.clearRect(0,0,canvas.width,canvas.height);        
    //Capture the start time
    startTime = Date.now();
    //Draw a circle i times.
    for (i = 0; i <= circleDraws; i++)
    {
      //Draw the circle
      drawCircle(2*Math.PI);
    }
    //Capture the time difference
    timeList2.push(Date.now() - startTime)
}

And finally... let's display the results:

JavaScript
//Start a simple HTML table to pack the results.
var resultTable = "<table><thead><tr><th>Pre-" + 
  "Calculated</th><th>Calculated</th><" + 
  "th>Difference</th></tr></thead><tbody>"

//Pack a td with a value
var packTD = function(value) {
if (value != null) {
  return "<td>" + value + "</td>";
} else {
    return "<td>&nbsp;</td>";
  }
};

//calculate and format the results
for (i = 0; i < timeList.length; i++)
{
 //New Row for the Result Table
 resultTable += "<tr>";
 //Append the Pre-Calculated time to the row
 resultTable += packTD(timeList[i]);
 //Append the Calculated time to the row
 resultTable += packTD(timeList2[i]);
 //Append the Difference
 resultTable += packTD(timeList[i] - timeList2[i]);
 //Close the New Row
 resultTable += "</tr>";
}

//Close the result table
resultTable += "</tbody></table>";
   
//Display the results
var tableResults = document.createElement("tableResults");
tableResults.innerHTML = resultTable;
document.body.appendChild(tableResults);

Points of Interest

You'll see that after running this little script a few times, a pattern starts to emerge.

  1. Using Math.PI * 2 is faster than using a var with the number already calculated (which is odd to me).
  2. The performance for each run goes up and down by about 30-50% each time you run it (for either set of test).

Take a look at the result table below to see what I mean.

Pre-Calculated Calculated Difference
133 85 48
82 161 -79
161 84 77
85 160 -75
160 87 73
85 158 -73
84 87 -3
158 162 -4
84 87 -3
161 156 5

I just thought the results were interesting and that I would share... enjoy!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)