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






3.10/5 (5 votes)
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...
// 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:
// 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:
//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:
//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:
//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> </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.
- Using
Math.PI * 2
is faster than using avar
with the number already calculated (which is odd to me). - 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!