在WebKit中有效循环大量固定位置图像的最佳方法是什么?

时间:2011-12-15 17:33:55

标签: performance firefox google-chrome webkit gecko

我正在为我的家人在一个小网站上工作。我想做的其中一件事就是制作一个基本的'制作'定格动画视频。我可以组装它并将其上传到Vimeo或其他东西,但我认为这是一个使用HTML,CSS和Javascript的绝佳机会。

我已经完成了所有风格,我的JS正在工作等等,除了它在Chrome和Safari中表现得非常糟糕。有趣的是,它在Firefox中运行良好,我还没有在IE中支持它。我希望每秒812帧,音乐播放,由于这个原因我还没有打扰过。糟糕的表现不是那么的。目前我在Firefox中大致3 fps可接受,但不是我想要的),在Chrome和Safari中我大致.6795 fps

运行Chrome Profiler时,我会得到以下(相关)输出。

99.96%   99.96%     (program)
0.03%    0.03%      (garbage collector)
0.01%    0.01%      script.js:5:nextSlide

我之前从未使用过Profiler,但我相信这让我觉得我的JS不是那么难以达到性能的。

我发布了test page,其中记录了您可以通过Chrome和Firefox访问的性能差异。

我还发现这似乎与循环的图像有关。 Cycling different, simpler images似乎在Chrome和Firefox中运行良好,尽管Chrome仍然比Firefox更耗电。

作为至少这一结论的进一步证明,虽然这是完全不可接受的,但在通过here运行图像后,已经证明convert -compress JPEG -quality 1。它们的循环效率更高,但当然质量很差。

我已经在Chrome(16.0.912.63),Safari(5.1.2 (6534.52.7)),WebKit(Version 5.1.2 (6534.52.7, r102985))和Mobile Safari(latest as of 2011/12/28)中运行了这些测试页Mobile Safari的功能与FireFox相同。桌面浏览器在MacBook Pro上进行了测试。

2.7 GHz Intel Core i7
8 GB 1333 MHz DDR3

有趣的是,在渲染test page时,iPad 2上的Mobile Safari与FireFox的效果相同。虽然Mobile Safari基于WebKit,但在这种情况下它表现完全不同。

setTimeout减少对144的{​​{1}}来电似乎也没有做任何事情。我已经完全随意地到达了244,因为很早就明白,与呼叫相比,显示的时间似乎几乎没有直接对应。这让我相信我正在尽可能快地在每个浏览器上渲染幻灯片。

所以我的问题是,如何在WebKit中创建这个高性能?

8 个答案:

答案 0 :(得分:12)

您可以使用Chrome开发者工具下的时间轴标签调试Chrome中的网页效果。您的脚本的问题是您的重绘周期太昂贵,目前每帧重绘需要1.35秒。

enter image description here

糟糕的性能与jpeg图像的质量无关(尽管图像质量也会影响页面渲染时间)。问题是您正在更新z-index,这会导致Chrome重新绘制所有图像,而不仅仅是下一帧(您有一个O(n)图像滑块网站!)。

浏览器尝试尽可能少地执行操作以响应更改,例如:元素颜色的更改将仅导致重新绘制元素。

更改元素z-index属性与从树中删除节点并向其添加另一个节点基本相同。这将导致元素,其子元素和可能的兄弟元素的布局和重绘。我的猜测是,在Chrome中,兄弟姐妹也被重新粉刷,这解释了可怕的表现。

解决此问题的方法是更新opacity属性而不是z-index。与z-index不同,opacity不会修改DOM树。它只告诉渲染器忽略该元素。该元素仍然在DOM中“物理”存在。这意味着只有一个元素被重新绘制,而不是所有兄弟姐妹和孩子。

CSS中的这个简单更改应该可以解决问题:

.making-of .slide#slide-top {
   opacity: 1;
   /* z-index: 5000; */
}


.making-of .slide {
   position: fixed;
   /* z-index: 4000; */
   opacity: 0;
   ....
}

这就是结果,重复从1.35秒到1毫秒:

enter image description here

编辑:

这是一个使用不透明度解决方案的jsfiddle,我还添加了CSS3过渡(只是为了好玩!)

http://jsfiddle.net/KN7Y5/3/

有关浏览器渲染如何工作的更多信息:

http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/

答案 1 :(得分:5)

我查看了您网站上的代码,发现了两个限制速度的事情。

1)在JavaScript中,您的超时时间约为1/4秒(244毫秒)。这意味着您的最佳帧速率约为4 FPS(每秒帧数)。这可以通过简单地减少延迟来匹配您实际想要的帧速率来解决。 我看到你最近的编辑解决了这一点,但我不想忽略它,因为它最终对于实现你想要的更高帧速率至关重要。

2)您正在使用z-index来控制哪些图像可见。在一般情况下,z-index处理允许对具有不同大小和位置的对象进行排序,以便您可以控制哪个对象在两个或多个对象重叠的位置处可见。在你的情况下,所有的对象都完美地重叠,并且z-index方法工作正常,除了一个主要问题:浏览器没有为这种情况优化z-index处理,因此它们实际上处理每个图像上的每个图像帧即可。我通过创建一个使用两倍图像的演示的修改版本来验证这一点 - FPS减少了近2倍(换句话说,显示整个集合需要4倍)。

我在Chrome和Firefox下共同采用了另一种方法,可以获得更高的FPS(60或更高)。它的要点是我使用display属性而不是操纵z-index:

.making-of .slide#other {
   display: none;
}

.making-of .slide#slide-top {
   display: inline;
}

和JavaScript:

function nextSlide() {
  ...
  topSlide.id='other';
  nextTopSlide.id='slide-top';
  ...
  setTimeout(nextSlide, 1);
  ...
}

我也对HTML进行了一些更改,特别是在每个图片的代码中包含id="other"


那么为什么WebKit这么慢?正如其他评论中指出的那样,你在Webkit上看到的极差性能似乎是Mac特有的。我对此最好的猜测是,Mac版的WebKit实际上并没有使用libjpeg的“turbo”版本(尽管事实上它被列在学分中)。在你的测试中,JPEG解压缩很可能是门控因素,如果它实际上解压缩每一帧上的每个图像(很可能就是这种情况)。 Benchmarking of libjpeg-turbo显示减压速度提高了约5倍。这大致匹配了您在Firefox和Chrome之间看到的差异(3 FPS与0.6795 FPS)。

有关libjpeg-turbo的更多说明以及此假设如何解释您的其他一些结果,请参阅my other answer

答案 2 :(得分:1)

我的经验是,在DOM和javascript数组中保持尽可能少的图像,所以不要一次性加载所有图像,将其保持在最低限度。还要确保销毁已经使用过的DOM元素以及包含图像的javascript对象,手动垃圾回收。这将提高性能。

答案 3 :(得分:1)

随机猜测:GPU加速。它取决于设备,现在浏览器之间有很大的竞争。

您可以尝试使用更新的Chrome,例如金丝雀,http://tools.google.com/dlpage/chromesxs(现在是18.x),只是为了获取更多数据。

about:Chrome中的版本应该为您提供WebKit的版本。

另外,您是否尝试过现有的幻灯片解决方案,例如http://jquery.malsup.com/cycle/?我想知道如果玩z-index是这里的瓶颈......可能只显示1-2个图像(所有其余的使用display:none)会有所帮助。这又是一个猜测。

答案 4 :(得分:0)

最近有一些关于JPEG图像压缩库的工作,它在许多应用程序中使用,包括Firefox和Chrome等浏览器。通过使用现代CPU中可用的特殊媒体处理指令,这个新库可以显着提高速度。 可能只是您的Chrome版本未使用新库。

你的问题要求一种方法来修复你的图像,但这不是必要的 - 毕竟,其他一些浏览器工作正常。因此,修复程序应该在浏览器中(并且浏览器会不断得到改进)。

您说过,您通过大幅降低图片的质量或复杂性来提高Chrome的速度。这可以通过以下事实来解释:对于非常低细节的区域,JPEG解压缩算法可以绕过它通常需要执行的大量工作。如果一个8x8的像素图块可以减少为单一颜色,那么该图块的解压缩就变得非常简单了。

This Wikipedia article提供了一些其他信息和来源。它说Chrome版本11有新库。您可以在位置栏中输入“ chrome:// credits ”,看看它是否引用了“ libjpeg-turbo ”。 “libjpeg”是原始库,“libjpeg-turbo”是优化版本。

另一种可能性是Mac上的Webkit不支持libjpeg-turbo(虽然我没有特别知道)。有一个提示,为什么可能是here发布的情况。

P.S。通过使用不同的算法(例如PNG)进行压缩,您可以获得更好的解压缩速度(尽管您的压缩率可能会受到影响)。另一方面,也许您应该使用HTML5 video,可能使用WebM format

答案 5 :(得分:0)

在图形方面实现更好性能的最佳方法是压缩它们,但是就像你想要的那样,但保持

如果您使用的是Linux,我之前使用过JPEG压缩工具http://linuxpoison.blogspot.com/2011/01/utility-to-optimize-compress-jpeg-files.html。它不会像你给出的ImageMagick示例那样损害质量。

同样http://trimage.org/有JPG支持,这将是我的第一个建议!

如果您使用的是Windows,可能是这样的: http://www.trans4mind.com/personal_development/convertImage/index.html

我没有测试过Windows方法,我甚至不确定它是否支持批处理

希望有所帮助!

P.S。对于我使用的PNG,有时使用http://pmt.sourceforge.net/pngcrush/以及是否有http://trimage.org/

答案 6 :(得分:0)

我在歌剧中测试了它并且它运行得很慢,我注意到歌剧已经排队了150多张图片下载它可能值得尝试下载〜一次20个?

答案 7 :(得分:0)

另一种方法是render this content as a video - 它非常适用于此类事物,并且可以轻松包含音频和字幕。如果你想变得时髦,可以使用JavaScript访问每个帧的每个像素。