使用 Chrome DevTools 对 HTML5 图形进行渲染测量
Posted
技术标签:
【中文标题】使用 Chrome DevTools 对 HTML5 图形进行渲染测量【英文标题】:Use Chrome DevTools for rendering measurement for HTML5 graphics 【发布时间】:2017-07-20 22:44:19 【问题描述】:我想测量 html5 中 canvas 和 svg 之间的性能。
到目前为止,我已经做到了。我在 svg 和画布中创建了多个圆圈。 两者的元素宽度和高度均为 500 x 500。
我发现我正在测量脚本编写时间。如果我使用 Chrome 中的开发工具,脚本编写时间几乎等于我测量的时间。 现在,我如何测量渲染时间?将是具有单独画布和 svg 圆创建和 devtools 的代码,用于渲染比较 svg 和画布渲染性能的好方法?
<html>
<head>
<script type="text/javascript">
var svgNS = "http://www.w3.org/2000/svg";
function createCircle1()
var t3 = performance.now();
for (var x = 1; x <= 1000; x++)
for (var y = 1; y <= 100; y++)
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(x, y, 5, 0, 2 * Math.PI);
ctx.stroke();
var t4 = performance.now();
console.log("canvas time " + (t4 - t3) + " milliseconds.")
var t0 = performance.now();
for (var x = 1; x <= 1000; x++)
for (var y = 1; y <= 100; y++)
var myCircle = document.createElementNS(svgNS, "circle"); //to create a circle, for rectangle use rectangle
myCircle.setAttributeNS(null, "cx", x);
myCircle.setAttributeNS(null, "cy", y);
myCircle.setAttributeNS(null, "r", 5);
myCircle.setAttributeNS(null, "stroke", "none");
document.getElementById("mySVG").appendChild(myCircle);
var t1 = performance.now();
console.log("svg time " + (t1 - t0) + " milliseconds.")
</script>
</head>
<body onload="createCircle1();">
<svg id="mySVG" style="border:1px solid #d3d3d3;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>
<canvas id="myCanvas" style="border:1px solid #d3d3d3;"></canvas>
</body>
</html>
不知何故,脚本编写时间和我测量的性能时间不同。 谁能告诉我这种性能比较是否有用?
我进行了多次测试,性能时间总是不同,但画布在渲染和脚本方面都比 svg 快。
为什么在渲染中?脚本应该是因为svg的DOM引用吧?
我用单独的 svg 和画布进行了这个测试,我只是先渲染了 svg,然后在下一个测试中只渲染了画布。
【问题讨论】:
【参考方案1】:SVG 的问题。
以下是在画布上绘制大圆圈和 SVG 图像的性能测试。
在我的机器和 chrome 上,每圈 30 毫秒的性能都差不多。
运行测试并查看结果。如果您观察进度,您可能会注意到它开始放慢一点。运行第一个测试时,再次单击该按钮,这一次您会注意到速度变慢了。
进行第 3 次测试,速度仍然较慢,但画布和 SVG 的每圈性能没有改变,慢是从哪里来的。
DOM 不是 javascript。
向 SVG 添加节点的代码并不关心 SVG 有多少节点,但是当向 SVG 图像添加节点并且您的代码退出时,您已经通知 DOM 您的 SVG 元素是脏的并且需要重绘。
在退出之前,我将测试分成了大约 10 组。这意味着每添加 10 个圆圈,DOM 就会从头开始重绘所有 SVG 节点,并在 javascript 上下文以及您测量或控制它的能力之外。
当您第二次单击测试时,SVG 已经有 10000 个圆圈,所以在添加前十个之后,DOM 会愉快地重新渲染 10000+10 个圆圈。
要准确衡量 SVG 性能几乎是不可能的。
使用时间轴
我用时间线记录运行了下面的代码 sn-p。我跑了两次测试。
接下来的两张图片显示的是同一时期。第一个是在测试开始时,下一个是在第二个测试结束时。
我已经标记了可能涉及渲染 SVG 的 GPU 部分。请注意它们如何从琐碎变为过度。
此图显示了在第二个测试周期中的一个测试周期 10 渲染。代码执行在大约 1 毫秒时几乎看不到,但 GPU 用了 175 毫秒的巨大时间来再次绘制所有 SVG 圆圈。
当您使用 SVG 时,您必须记住,当您对其进行更改时,DOM 将重新渲染所有内容。它不关心它是否可见。如果你改变它的大小,它会重绘。
要使用 SVG,您必须将所有调用捆绑到一个执行上下文中以获得最佳性能。
画布 V SVG
SVG 和 Canvas 都使用带有非常相似着色器的 GPU 来完成工作。在 SVG 或 Canvas 中绘制圆需要相同的时间。画布相对于 SVG 的优势在于您可以控制渲染、何时何地渲染。对于 SVG,您只能控制内容,而对渲染几乎没有发言权。
var running = false;
var test = function()
if(running)
return;
var mySVG = document.getElementById("mySVG");
var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
var myCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
running = true;
const testCount = 1000;
const groupCount = 10;
var times = [[],[]];
var names =["Canvas test.","SVG test."];
var indexs = [0,0];
var tests = [function()
now = performance.now();
ctx.beginPath();
ctx.arc(250, 250, 250, 0, 2 * Math.PI);
ctx.fill();
return performance.now()-now;
,
function()
now = performance.now();
var circle = myCircle.cloneNode();
circle.setAttributeNS(null, "cx", 250);
circle.setAttributeNS(null, "cy", 250);
circle.setAttributeNS(null, "r", 250);
circle.setAttributeNS(null, "stroke", "none");
mySVG.appendChild(circle);
return performance.now()-now;
];
for(var i = 0; i < testCount; i ++) // preallocate and zeor arrays
times[0][i] = 0;
times[1][i] = 0;
var testComplete = false;
function doTests()
for(i = 0; i < groupCount; i ++)
var testIndex = Math.floor(Math.random()*2);
times[testIndex][indexs[testIndex]] = tests[testIndex]();
indexs[testIndex] += 1;
if(indexs[testIndex] >= testCount)
testComplete = true;
return;
function getResults()
// get the mean
var meanA = 0;
var meanB = 0;
var varianceA = 0;
var varianceB = 0;
var totalA = 0;
var totalB = 0;
for(var i = 0; i < testCount; i ++) // preallocate and zero arrays
totalA += i < indexs[0] ? times[0][i] : 0;
totalB += i < indexs[1] ? times[1][i] : 0;
meanA = Math.floor((totalA / indexs[0]) * 1000) / 1000;
meanB = Math.floor((totalB / indexs[1]) * 1000) / 1000;
for(var i = 0; i < testCount; i ++) // preallocate and zero arrays
varianceA += i < indexs[0] ? Math.pow((times[0][i] - meanA),2) : 0;
varianceB += i < indexs[1] ? Math.pow((times[1][i] - meanB),2) : 0;
varianceA = Math.floor((varianceA / indexs[0]) * 1000) / 1000;
varianceB = Math.floor((varianceB / indexs[1]) * 1000) / 1000;
result1.textContent = `Test $names[0] Mean : $meanAms Variance : $varianceAms Total : $totalA.toFixed(3)ms over $indexs[0] tests.`;
result2.textContent = `Test $names[1]. Mean : $meanBms Variance : $varianceBms Total : $totalB.toFixed(3)ms over $indexs[1] tests.`;
function test()
doTests();
var p = Math.floor((((indexs[0] + indexs[1]) /2)/ testCount) * 100);
if(testComplete)
getResults();
p = 100;
running = false;
else
setTimeout(test,10);
progress.textContent = p+"%";
test()
startBut.addEventListener("click",test);
#ui
font-family : Arial;
<div id="ui">
<h3>Comparative performance test</h3>
Adding circles to canvas V adding circles to SVG.<br> The test adds 1000 * 10 circles to the canvas or SVG with as much optimisation as possible and to be fair.<br>
<input id="startBut" type="button" value = "Start test"/>
<div id="progress"></div>
<div id="result1"></div>
<div id="result2"></div>
<h3>SVG element</h3>
<svg id="mySVG" style="border:1px solid #d3d3d3;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>
<h3>Canvas element</h3>
<canvas id="myCanvas" style="border:1px solid #d3d3d3;"></canvas>
</div>
【讨论】:
以上是关于使用 Chrome DevTools 对 HTML5 图形进行渲染测量的主要内容,如果未能解决你的问题,请参考以下文章