我正在构建一个JavaScript性能竞赛的测试平台。其中一项任务是挑战参赛者优化负责处理画布动画的JavaScript代码。提交解决方案后,服务器使用PhantomJS运行它,并在动画播放20秒后读取平均FPS数。问题是我为优化和未优化的代码获得了3-4FPS。这使得无法判断代码是否得到了改进。
一些事实:
requestAnimationFrame
所以我不得不使用polyfill frameCounter.js
var frameCounter = (function() {
var frames = 0;
var startTime = new Date();
function bump() {
frames++;
window.requestAnimationFrame(bump);
}
bump();
return {
getFPS: function() {
var time = (new Date() - startTime) / 1000;
return (frames/time).toPrecision(4);
}
}
})();
我的问题是:如何以编程方式衡量画布动画的效果?
答案 0 :(得分:3)
几个月前我写了一个小脚本专门测量requestAnimationFrame
的FPS和消费量。
我不确定它会帮助你100%,但它可以给你一个很好的指针。
用法非常简单:
绿色表示您在最佳FPS范围内运行(大多数情况下为60)。黄色表示循环消耗超过大约16.7毫秒,速率降低到大约一半。橙色意味着您使用的预算是预算的两倍以上。
仪表使用加权FPS为您提供更准确的测量。
示例强>:
var meter = new animMeter('divElementId');
function animate(timeArg) {
/// funky stuff here
meter.update(timeArg);
requestAnimationFrame(animate);
}
<强> A demo of this in action can be found here 强>
您可以在预先最小化的底部找到仪表本身的代码。随意复制和粘贴。它附带MIT许可证。
和使用这样的仪表一样:它们自己会花费几毫秒的时间来更新图形,从而引入微小的误差范围。
另一件需要注意的事情是,rAF将始终试图达到60 FPS,因此仪表永远不会测量比这更高的帧速率。
如果您需要测量更高的帧速率,您可以不带参数调用更新方法并使用setTimeout
而不是rAF,它将使用日期/时间来衡量性能 - 稍微更不准确但您可以获得更高FPS数字(这是任意帧,因为显示器无法显示比同步时更多的帧...通常为60 fps)。
答案 1 :(得分:2)
由于幻影似乎无法在任何动画上产生超过3-4 FPS,我最终使用了真实的&#39;这个任务的浏览器。由于Chrome remote debugging protocol,我能够实现自动化。
我创建了一个node.js应用程序,每次有新的代码要测试时,都会执行以下步骤:
--remote-debugging-port=9222
标志运行)以下是我的代码中的代码段:
//connect to a tab (you can find <tab-debug-id> on http://localhost:9222/json page)
var ws = new WebSocket("ws://localhost:9222/devtools/page/<tab-debug-id>");
ws.onerror = function() {
//handle error
};
ws.onopen = function()
{
//when connection is opened hard reload the page before we start
ws.send(JSON.stringify({
id: 1,
method: "Page.reload",
params: {
ignoreCache: true
}
}));
};
ws.onmessage = function (evt)
{
var data = JSON.parse(evt.data);
if(data.id === 1) {
//reload was successful - inject the test script
setTimeout(function(){
ws.send(JSON.stringify({
id: 2,
method: "Runtime.evaluate",
params: {
expression: '(' + injectedCode.toString() + '());'
}
}));
}, 1000);
} else if(data.id === 2) {
//animation has finished - extract the result
var result = data.result.result.value;
}
};
答案 2 :(得分:0)
你可以使用Date.now()来减少对象创建浪费的时间,它应该至少提高一点精度