65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.10/5 (5投票s)

2013年10月24日

CPOL

2分钟阅读

viewsIcon

13699

这段代码旨在说明在使用 .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>&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);

关注点

您会看到,运行这个小脚本几次后,会开始出现一种模式。

  1. 使用 Math.PI * 2 比使用已经计算好的数字的 var 更快(这对我来说很奇怪)。
  2. 每次运行测试,无论哪种测试方式,性能都会上升或下降约 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

我只是觉得结果很有趣,所以分享一下... 享受吧!

© . All rights reserved.