对于 react 时间研究(see also this question 如果您有兴趣),我们想要控制和测量图像的显示时间。我们想考虑在不同用户的机器上重新绘制所需的时间。
编辑:最初,我只使用内联执行来计时,我认为我不能相信它能准确地测量图片在用户屏幕上的可见时间,因为绘画需要一些时间.
后来,我找到了事件“MozAfterPaint”。它需要更改配置才能在用户计算机和相应的 WebkitAfterPaint 上运行没有成功。这意味着我不能在用户的计算机上使用它,但我将它用于我自己的测试。我在下面粘贴了相关的代码片段和我的测试结果。
我还使用 SpeedTracer 手动检查了结果在 Chrome 中。
// from the loop pre-rendering images for faster display
var imgdiv = $('<div class="trial_images" id="trial_images_'+i+'" style="display:none"><img class="top" src="' + toppath + '"><br><img class="bottom" src="'+ botpath + '"></div>');
Session.imgs[i] = imgdiv.append(botimg);
$('#trial').append(Session.imgs);
// in Trial.showImages
$(window).one('MozAfterPaint', function () {
Trial.FixationHidden = performance.now();
});
$('#trial_images_'+Trial.current).show(); // this would cause reflows, but I've since changed it to use the visibility property and absolutely positioned images, to minimise reflows
Trial.ImagesShown = performance.now();
Session.waitForNextStep = setTimeout(Trial.showProbe, 500); // 500ms
// in Trial.showProbe
$(window).one('MozAfterPaint', function () {
Trial.ImagesHidden = performance.now();
});
$('#trial_images_'+Trial.current).hide();
Trial.ProbeShown = performance.now();
// show Probe etc...
比较使用 MozAfterPaint 和内联执行测量的持续时间的结果。
这并没有让我太高兴。首先,显示持续时间的中位数比我想要的短了大约 30 毫秒。其次,使用 MozAfterPaint 的方差非常大(比内联执行大),所以我不能通过将 setTimeout 增加 30 毫秒来简单地调整它。第三,这是在我相当快的计算机上,其他计算机的结果可能更差。
SpeedTracer 的结果
这些更好。图像可见的时间通常在预期持续时间的 4(有时)10 毫秒以内。看起来 Chrome 在 setTimeout
调用中考虑了重新绘制所需的时间(因此如果图像需要重新绘制,则调用之间存在 504 毫秒的差异)。
不幸的是,我无法在 SpeedTracer 中分析和绘制许多试验的结果,因为它只记录到控制台。我不确定 SpeedTracer 和 MozAfterPaint 之间的差异是否反射(reflect)了两种浏览器的差异,或者是我在使用 MozAfterPaint 时缺少的东西(我很确定我正确地解释了 SpeedTracer 输出)。
问题
我想知道
- 我如何衡量它在用户机器上实际可见的时间,或者至少获得一组不同浏览器在不同测试计算机(Chrome、Firefox、Safari)上的可比数字?
- 我能否抵消渲染和绘画时间以达到 500 毫秒的实际可见度?如果我必须依赖通用偏移,那会更糟,但仍然比在速度较慢的计算机上显示图像的时间太短以至于用户不会有意识地看到它们要好。
- 我们使用
setTimeout
。我知道requestAnimationFrame
但似乎我们无法从使用它中获得任何好处:
该研究应该在整个研究期间都处于重点状态,我们获得 +/-500 毫秒的显示比一定数量的 fps 更重要。我的理解正确吗?
显然,Javascript 对此并不理想,但它对我们的目的来说是最不坏的(该研究必须在用户自己的计算机上在线运行,要求他们安装一些东西会吓跑一些人,Java 没有捆绑在 Mac 中OS X 浏览器)。
我们目前只允许当前版本的 Safari、Chrome、Firefox 和可能的 MSIE(performance.now 和全屏 API 的功能检测,我还没有检查 MSIE 是怎么做的)。
最佳答案
因为我还没有得到更多的答案,但是在编辑这个问题时学到了很多东西,所以我将我的进度发布为答案。正如您将看到的那样,它仍然不是最优的,我很乐意将赏金奖励给改进它的任何人。
统计
- 在最左边的面板中,您可以看到让我怀疑我得到的时间估计的分布。
- 中间面板显示了我在缓存选择器、重新排序一些调用、使用更多链接、通过使用
visibility
和绝对定位而不是display
最小化回流之后取得的成果. - 最右边的面板显示了我使用 Joe Lambert 改编的函数后得到的结果使用请求动画框架。我是在 reading a blogpost about rAF now having sub-millisecond precision too 之后做的.我认为它只会帮助我平滑动画,但显然它也有助于获得更好的实际显示持续时间。
结果
在最后一个面板中,“paint-to-paint”时间的平均值约为 500 毫秒,内联执行时间的平均值实际分散(有道理,因为我使用相同的时间戳来终止下面的内部循环)并关联与“油漆到油漆”的时间。
持续时间仍然有很大的差异,我很乐意进一步减少它,但这绝对是进步。我将不得不在一些较慢的和一些 Windows 计算机上测试它,看看我是否真的对它满意,最初我希望所有偏差都低于 10 毫秒。
如果我制作一个不需要用户交互的测试套件,我也可以收集更多的数据,但我想在我们的实际应用程序中这样做以获得现实的估计。
window.requestTimeout
使用 window.requestAnimationFrame
window.requestTimeout = function(fn, delay) {
var start = performance.now(),
handle = new Object();
function loop(){
var current = performance.now(),
delta = current - start;
delta >= delay ? fn.call() : handle.value = window.requestAnimationFrame(loop);
};
handle.value = window.requestAnimationFrame(loop);
return handle;
};
编辑:
关于javascript - 精确控制和测量图像的显示时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14323792/