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

时间:2013-01-14 17:49:44

标签: javascript jquery time repaint reflow

对于反应时间研究(see also this question,如果您感兴趣),我们希望控制和测量图像的显示时间。我们想说明在不同用户的机器上重绘所需的时间。

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

后来,我发现了事件“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...

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

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

Boxplot of durations

Relationship of durations measured using two methods

SpeedTracer的结果

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

问题

我想知道

  1. 如何衡量用户机器上实际可见的时间,或至少获得不同测试计算机(Chrome,Firefox,Safari)上一组不同浏览器的可比数字?
  2. 我可以抵消渲染&amp;绘画时间达到500ms的实际能见度?如果我不得不依赖普遍的偏移,那将会更糟,但仍然比显示图像的持续时间短,用户在有些慢的计算机上没有有意识地看到它们。
  3. 我们使用setTimeout。我知道requestAnimationFrame,但似乎我们不能从使用它中获得任何好处:
    该研究应该是整个研究期间的焦点,更重要的是我们得到+/- 500ms显示而不是一定数量的fps。我的理解是否正确?
  4. 显然,Javascript对此并不理想,但它对我们的目的来说是最不利的(研究必须在用户自己的计算机上在线运行,要求他们安装一些会吓跑一些,Java不捆绑在Mac上OS X浏览器了。) 我们目前只允许使用当前版本的Safari,Chrome,Firefox和MSIE(性能检测功能。现在和全屏API,我还没有检查过MSIE的功能)。

2 个答案:

答案 0 :(得分:5)

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

统计

New results

  • 在最左边的面板中,你可以看到导致我怀疑我得到的时间估计的分布。
  • 中间面板显示我在缓存选择器之后取得的成就,重新排序一些调用,使用更多链接,使用visibility和绝对定位而不是display来最小化回流。
  • 最右边的面板显示了Joe Lambert使用requestAnimationFrame使用改编函数后得到的结果。我在reading a blogpost about rAF now having sub-millisecond precision too之后做到了。我认为它只能帮助我平滑动画,但显然它有助于获得更好的实际显示持续时间。

结果

在最后一个面板中,“paint-to-paint”时间的平均值是~500ms,内联执行时序的平均值实际上分散(有意义,因为我使用相同的时间戳来终止下面的内部循环)并且相关联与“油漆到油漆”的时间。

持续时间仍有很多变化,我希望进一步减少它,但这肯定是进步。我将不得不在一些较慢的和一些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;
};

编辑:

answer to another question of minegood new article链接。

答案 1 :(得分:4)

您是否尝试获取初始毫秒数,并在事件触发后计算差异?而不是setTimeout。类似的东西:

var startDate = new Date();
var startMilliseconds = startDate.getTime();

// when the event is fired :
(...), function() {
    console.log(new Date().getTime() - startMilliseconds);
});

尝试尽可能避免使用jQuery。普通JS将为您提供更好的响应时间和更好的整体性能