控制并精确测量图像的显示时间

Rub*_*ben 26 javascript time jquery repaint reflow

对于反应时间研究(如果您感兴趣,请参阅此问题)我们希望控制和测量图像的显示时间.我们想说明在不同用户的机器上重绘所需的时间.

编辑:最初,我只使用内联执行进行计时,并认为我不能相信它可以准确地测量图片在用户屏幕上可见的时间,因为绘画需要一些时间.

后来,我发现了事件" MozAfterPaint ".它需要在用户的计算机上运行配置更改,并且相应的WebkitAfterPaint没有成功.这意味着我无法在用户的计算机上使用它,但我将它用于我自己的测试.我粘贴了相关的代码片段和我下面的测试结果.
我还在Chrome中使用SpeedTracer手动检查了结果.

// 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...
Run Code Online (Sandbox Code Playgroud)

比较使用MozAfterPaint和内联执行测量的持续时间的结果.

这不会让我太开心.首先,中位显示持续时间比我想要的短约30毫秒.其次,使用MozAfterPaint的方差非常大(并且比内联执行大),所以我不能简单地通过将setTimeout增加30ms来调整它.第三,这是在我相当快的计算机上,其他计算机的结果可能更糟.

Boxplot的持续时间

使用两种方法测量的持续时间的关系

SpeedTracer的结果

这些更好.图像可见的时间通常在预期持续时间的4(有时)10毫秒内.它看起来像Chrome占用了重新setTimeout调用呼叫所需的时间(因此,如果图像需要重新绘制,则呼叫之间有504ms的差异).不幸的是,我无法分析和绘制SpeedTracer中许多试验的结果,因为它只记录到控制台.我不确定SpeedTracer和MozAfterPaint之间的差异是否反映了两个浏览器的差异或我使用MozAfterPaint时缺少的东西(我很确定我正确地解释了SpeedTracer输出).

问题

我想知道

  1. 如何衡量用户机器上实际可见的时间,或至少获得不同测试计算机(Chrome,Firefox,Safari)上一组不同浏览器的可比数字?
  2. 我可以抵消渲染和绘画时间以达到500毫秒的实际可见度吗?如果我不得不依赖于通用偏移,那将会更糟,但仍然比显示图像的持续时间短,用户在有些慢的计算机上没有有意识地看到它们.
  3. 我们用setTimeout.我知道,requestAnimationFrame但似乎我们不能从使用它中获得任何好处:
    该研究应该是整个研究期间的焦点,更重要的是我们得到+/- 500ms显示而不是某些fps的数量.我的理解是否正确?

显然,Javascript对此并不理想,但它对我们的目的来说是最不利的(该研究必须在用户自己的计算机上在线运行,要求他们安装一些会吓跑一些,Java没有捆绑在Mac OS X浏览器中了).
我们目前只允许使用当前版本的Safari,Chrome,Firefox和MSIE(性能检测功能.现在和全屏API,我还没有检查过MSIE的功能).

Rub*_*ben 5

因为我还没有得到任何答案,但在编辑这个问题的过程中学到了很多东西,所以我发布了我的进展答案.正如你所看到的那样,它仍然不是最优的,我很乐意将赏金奖励给任何改进它的人.

统计

新结果

  • 在最左边的面板中,您可以看到分布,这让我怀疑我得到的时间估计.
  • 中间面板显示了我在缓存选择器之后取得的成就,重新排序一些调用,使用更多链接,通过使用visibility和绝对定位而不是最小化回流display.
  • 最右边的面板显示了Joe Lambert使用requestAnimationFrame 后使用改编函数后得到的结果.我在阅读了一篇关于现在具有亚毫秒级精度的rAF博客后也做到了这一点.我认为它只能帮助我平滑动画,但显然它也有助于获得更好的实际显示持续时间.

结果

在最后一个面板中,"paint-to-paint"时间的平均值约为500ms,内联执行时序的平均值实际上分散(有意义,因为我使用相同的时间戳来终止下面的内部循环)并与"paint"相关联 - 画画"时机.

持续时间仍有很多差异,我希望进一步减少它,但这肯定是进步.我将不得不在一些较慢的和一些Windows计算机上测试它,看看我是否真的很满意它,最初我希望得到的所有偏差都低于10ms.

如果我制作了一个不需要用户交互的测试套件,我也可以收集更多的数据,但我想在我们的实际应用程序中进行实际估算.

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;
};
Run Code Online (Sandbox Code Playgroud)

编辑:

我的另一个问题答案链接到一篇好的新文章.