尝试性能测试... 圆圈的奇怪结果






3.10/5 (5投票s)
这段代码旨在说明在使用 .arc()
方法将圆绘制到画布上时,使用常量与始终使用 2*Math.PI
之间的性能差异。
引言
在特定的 HTML5 画布上绘制(大量)圆圈(或任何内容)都可能严重降低性能。这段代码旨在说明在使用 .arc()
方法将圆绘制到画布上时,使用常量与始终使用 2*
之间的性能差异。Math.PI
背景
我有一个项目涉及在 HTML5 画布元素上绘制大量的圆圈。在开发过程中,我遇到了性能问题。圆圈的数量一度几乎呈指数级增长,因此性能也同时下降(呈指数级)。
性能问题本身已经通过其他方式解决,但当问题出现时,它促使我编写了这段 JavaScript 代码。
我想通过计算 2 *
并将结果放入一个变量中,由绘制圆圈函数调用,来节省一些时间,而不是每次调用 Math.PI
drawCircle()
时都让代码计算这个数字。所以... 我写了一个快速脚本,结果对我来说有点反直觉... 所以我想分享一下。
Using the Code
我将说明整个脚本(它相当小),以便您可以自行运行。您可以将我放在这里的代码部分转储到 <script></script>
标签之间的 HTML 文件中,或者单独的 .js 文件中... 随您意愿。
该脚本本身会创建 Canvas
元素,因此除了一个空的 HTML 页面之外,没有其他 HTML 要求。
首先,让我们设置画布并创建上下文
这将为我们提供一些可以绘制的东西...
// 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");
现在,让我们创建一些基本变量来控制测试并保存结果
// 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
创建一个函数来绘制圆圈
//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();
};
放置一些循环来绘制圆圈
//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)
}
最后... 让我们显示结果
//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);
关注点
您会看到,运行这个小脚本几次后,会开始出现一种模式。
- 使用
Math.PI * 2
比使用已经计算好的数字的var
更快(这对我来说很奇怪)。 - 每次运行测试,无论哪种测试方式,性能都会上升或下降约 30-50%。
请查看下面的结果表,看看我的意思。
预先计算 | 计算 | 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 |
我只是觉得结果很有趣,所以分享一下... 享受吧!