在 WebKit 中高效循环浏览大量固定位置图像的最佳方法是什么?
我目前正在为我的家人开发一个小网站。我想做的一件事是制作一个基本的定格动画视频。我可以组装它并将其上传到 Vimeo 或其他东西,但我认为这是一个只使用 HTML、CSS 和 Javascript 的绝佳机会。
我已经设置了所有样式,并且我的 JS 正在运行,等等,但它在 Chrome 和 Safari 中的表现很糟糕。有趣的是,它在 Firefox 中运行得很好,但我在 IE 中还不支持它。我希望每秒 8
到 12
帧播放音乐,因此我还没有费心去尝试。糟糕的表现远不止于此。目前,我在 Firefox 中获得了大约 3 fps
(可以接受,但不是我想要的),在 Chrome 和 Safari 中,我获得了大约 .6795帧率。
运行 Chrome Profiler 时,我得到以下(相关)输出。
99.96% 99.96% (program)
0.03% 0.03% (garbage collector)
0.01% 0.01% script.js:5:nextSlide
我以前从未使用过 Profiler,但我相信这向我表明,我的 JS 并不是对性能造成如此严重影响的原因。
我发布了 测试页面,记录了您可以使用 Chrome 和 Firefox 访问的性能差异。
我还发现这似乎与循环的图像有关。 骑自行车不同,更简单的图像似乎在 Chrome 和 Firefox 中都运行得很好,尽管 Chrome 仍然比 Firefox 更耗电。
作为至少这一结论的进一步证明,尽管这是完全不可接受的,但已证明 此处,通过 转换-压缩 JPEG-质量 1
。它们的循环效率要高得多,但质量当然很糟糕。
我已在 Chrome (16.0.912.63
)、Safari (5.1.2 (6534.52.7)
)、WebKit nightly (Version 5.1.2) 中运行这些测试页面(6534.52.7, r102985)
) 和 Mobile Safari(最新版本2011/12/28
),只有 Mobile Safari 的性能与 FireFox 一样好。桌面浏览器在 MacBook Pro 上进行了测试。
2.7 GHz Intel Core i7
8 GB 1333 MHz DDR3
有趣的是,在渲染 测试页面。尽管 Mobile Safari 基于 WebKit,但在本例中它的表现完全不同。
将 setTimeout
调用从 244
减少到 144
似乎也没有做任何事情。在这一点上,我完全任意地达到了244
,因为很早就很清楚,与调用相比,显示的时间似乎几乎不直接对应。这让我相信我正在每个浏览器上尽可能快地渲染幻灯片。
所以我的问题是,如何在 WebKit 中实现此功能?
I'm currently working on a little site for my family. One of the things I wanted to do was to make a basic 'making of' stop-motion video. I could assemble it and upload it to Vimeo or something but I thought it was a perfect opportunity to use nothing but HTML, CSS, and Javascript.
I've got everything styled and my JS is working, etc. except that it performs atrociously in Chrome and Safari. Interestingly, it works great in Firefox and I'm not supporting it yet in IE. I'm hoping for 8
to 12
frames per second, with music playing, which I haven't bothered trying yet due to this. Bad performance is anything less than that. Currently I'm getting roughly 3 fps
in Firefox (acceptable, but not what I was looking for) and in Chrome and Safari I'm getting roughly .6795 fps
.
When running the Chrome Profiler, I get the following (relevant) output.
99.96% 99.96% (program)
0.03% 0.03% (garbage collector)
0.01% 0.01% script.js:5:nextSlide
I've never used the Profiler before but I believe this is showing me that my JS is not what's hitting the performance so hard.
I've published a test page that documents the performance differences that you can visit with Chrome and Firefox.
I've also discovered that this seems to be related to the images cycled. Cycling different, simpler images seems to work just fine in both Chrome and Firefox, despite the fact that Chrome is still a little more power hungry than Firefox.
As further proof of at least this conclusion, though it's entirely unacceptable, is demonstrated here, after running the images through convert -compress JPEG -quality 1
. They cycle much more efficiently, but of course the quality is terrible.
I have run these test pages in Chrome (16.0.912.63
), Safari (5.1.2 (6534.52.7)
), WebKit nightly (Version 5.1.2 (6534.52.7, r102985)
), and Mobile Safari (latest as of 2011/12/28
) and only Mobile Safari performs as well as FireFox. The desktop browsers were tested on a MacBook Pro.
2.7 GHz Intel Core i7
8 GB 1333 MHz DDR3
Interestingly, Mobile Safari on an iPad 2 performs as well as FireFox when rendering the test page. Though Mobile Safari is based on WebKit, in this instance it performs entirely different.
Decreasing the setTimeout
call to 144
from 244
also seems to not do anything. I've arrived at 244
entirely arbitrarily at this point as it became clear early on that the timing of the display compared to the call didn't seem to correspond nearly directly. This leads me to believe that I'm rendering the slide show as quickly as I can on each browser.
So my question is, how can I make this performant in WebKit?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您可以使用 Chrome 开发者工具下的“时间轴”选项卡调试 Chrome 中的页面性能。您的脚本的问题在于您的重绘周期太昂贵,目前每帧重绘需要 1.35 秒。
性能不佳与 jpeg 图像的质量无关(尽管图像质量也会影响页面渲染时间)。问题是您正在更新 z-index,这会导致 Chrome 重新绘制所有图像,而不仅仅是下一帧(您有一个 O(n) 图像滑块网站!)。
浏览器尝试执行尽可能少的操作来响应更改,例如:元素颜色的更改只会导致元素的重新绘制。
更改元素 z-index 属性基本上与从树中删除一个节点并向其添加另一个节点相同。这将导致元素、其子元素以及可能的同级元素的布局和重新绘制。我的猜测是,在 Chrome 中,兄弟姐妹也被重新绘制,这解释了糟糕的性能。
解决此问题的一种方法是更新
opacity
属性而不是z-index
。与z-index
不同,opacity
不会修改 DOM 树。它只告诉渲染器忽略该元素。该元素仍然“物理”存在于 DOM 中。这意味着只有一个元素会被重新绘制,而不是所有的兄弟元素和子元素。CSS 中的这个简单更改应该可以解决问题:
这就是结果,重绘从 1.35 秒变为 1 毫秒:
编辑:
这是一个使用不透明解决方案的jsfiddle,我还添加了CSS3过渡(只是为了好玩!)
http://jsfiddle.net/KN7Y5/3/
有关浏览器渲染工作原理的更多信息:
http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/
You can debug the page performance in Chrome using the Timeline tab under the Chrome developer tools. The problem with your script is that your repaint cycle is simply too expensive, it currently takes 1.35s to repaint every frame.
The bad performance has nothing to do with the quality of the jpeg images (although the image quality also affects the page render time). The problem is that you are updating the z-index which causes the Chrome to repaint all images instead of just the next frame (You have a O(n) image slider website!).
The browsers try to do the minimal possible actions in response to a change e.g.: changes to an elements color will cause only repaint of the element.
Changing the element z-index property is basically the same as removing a node from the tree and adding another node to it. This will cause layout and repaint of the element, its children and possibly siblings. My guess is that in Chrome, the siblings are being repainted too, this explains the horrible performance.
A way to fix this problem is to update the
opacity
property instead of thez-index
. Unlike thez-index
, theopacity
does not modifies the DOM tree. It only tells the render to ignore that element. The element is still 'physically' present in the DOM. That means that only one element gets repainted and not all siblings and children.This simple changes in your CSS should do the trick:
And this is the result, the repaint went from 1.35s to 1ms:
EDIT:
Here is a jsfiddle using the opacity solution, I also added CSS3 transitions (just for fun!)
http://jsfiddle.net/KN7Y5/3/
More info on how the browser rendering works:
http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/
我查看了您网站上的代码,发现有两件事限制了速度。
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:和 JavaScript:
我也在 HTML 中做了一些更改,特别是包括
id="other" 在每个图像的标签中。
那么为什么 WebKit 这么慢? 正如其他评论中所指出的,您在 Webkit 上看到的极差性能似乎是 Mac 特有的。我对此的最佳猜测是,Mac 版本的 WebKit 实际上并未使用 libjpeg 的“turbo”版本(尽管它列在制作人员名单中)。在您的测试中,如果 JPEG 解压缩实际上解压缩每一帧上的每个图像(很可能就是这种情况),那么 JPEG 解压缩很可能是选通因素。 libjpeg- 的基准测试Turbo 的减压速度提高了约 5 倍。这大致符合您在 Firefox 和 Chrome 之间看到的差异(3 FPS 与 0.6795 FPS)。
有关 libjpeg-turbo 的更多说明以及该假设如何解释其他一些结果,请参阅 我的其他答案。
I took a look at the code on your site and found two things that are limiting the speed.
1) In the JavaScript, you have a timeout of approximately 1/4 second (244 milliseconds). This means that your best-cast frame-rate is about 4 FPS (frames-per-second). This can be fixed by simply reducing the delay to match the frame rate that you actually want. I see that your most recent edit addresses this point, but I didn't want to ignore it since it is ultimately critical to achieving the higher frame-rates that you want.
2) You are using
z-index
to control which image is visible. In the general case, z-index handling allows for objects that have different sizes and positions to be ordered so that you can control which object is visible at locations where two or more objects overlap. In your case, all of the objects overlap perfectly, and the z-index approach works fine except for one major problem: browsers don't optimize z-index processing for this case and therefore they are actually processing every image on every frame. I verified this by creating a modified version of your demo which used twice as many images -- the FPS was reduced by nearly a factor of 2 (in other words, it took 4 times as long to display the entire set).I hacked together an alternative approach that achieved a much higher FPS (60 or more) under both Chrome and Firefox. The gist of it was that I used the
display
property instead of manipulating z-index:and the JavaScript:
I made some changes in the HTML too, notably including
id="other"
in the tag for each image.So why is WebKit so slow? As has been pointed out in other comments, the extra-poor performance that you are seeing on Webkit seems to be Mac specific. My best guess about this is that the Mac version of WebKit is not actually using the "turbo" version of libjpeg (despite the fact that it is listed in the credits). In your test, JPEG decompression could very well be the gating factor if it is actually decompressing every image on every frame (as is likely the case). Benchmarking of libjpeg-turbo has shown about a 5x improvement in decompression speed. This roughly matches the difference that you are seeing between Firefox and Chrome (3 FPS vs. 0.6795 FPS).
For more notes on libjpeg-turbo and how this hypothesis explains some of your other results, see my other answer.
根据我的经验,关键是在 DOM 和 javascript 数组中保留尽可能少的图像,因此不要一次加载所有图像,请将其保持在最低限度。还要确保你销毁了已经使用的 DOM 元素以及保存图像的 javascript 对象,手动垃圾收集。这将提高性能。
Key in my experience is to keep as less as possible images in the DOM and in javascript arrays, so don't load all of the at once, keep it to a minimum. Also make sure you destroyed already used DOM elements as well as javascript objects holding images, manual garbage collection. This will improve performance.
随机猜测:GPU加速。它依赖于设备,并且现在浏览器之间存在着一场激烈的竞争。
您可以尝试使用更新版本的 Chrome,例如 Canary,http://tools.google.com/dlpage/chromesxs (现在是18.x),只是为了获取更多数据。
Chrome 中的 about:version 应该为您提供 WebKit 的版本。
另外,您是否尝试过现有的幻灯片解决方案,例如 http://jquery.malsup.com/cycle/ ?我想知道使用 z-index 是否是这里的瓶颈...也许只显示 1-2 个图像(其余所有图像都使用 display:none)会有所帮助。这又是一个猜测。
Random guess: GPU acceleration. It is device-dependent, and there is a big race among browsers now.
You could try with a more recent Chrome like the canaries, http://tools.google.com/dlpage/chromesxs (it's 18.x now), just to get more data.
about:version in Chrome should give you version of WebKit.
Also, have you tried existing slideshow solutions like http://jquery.malsup.com/cycle/ ? I wonder if playing with the z-index is the bottleneck here... maybe having only 1-2 images displayed (all the rest using display:none) would help. This is again a guess.
在图形方面获得更好性能的最佳方法是压缩它们,但是像你想要的那样,但是保留
如果你使用的是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方法,我什至不确定它是否支持批处理
希望有帮助!
PS 对于我使用的 PNG,有时会使用 http://pmt.sourceforge.net/pngcrush/ 以及 或没有 http://trimage.org/
The best way to achieve better performance when it comes to graphics is to compress them, but like you want, but keep
If you are using Linux, I have used JPEG compression tool http://linuxpoison.blogspot.com/2011/01/utility-to-optimize-compress-jpeg-files.html before. It doesn't hurt quality as much as the ImageMagick example you gave.
Also http://trimage.org/ has JPG support, and would be my first recommendation!
If you are on Windows, maybe something like this:
http://www.trans4mind.com/personal_development/convertImage/index.html
I have not tested the Windows method, and I'm not even sure it supports batch
Hope that helps!
P.S. For PNGs I use sometimes use http://pmt.sourceforge.net/pngcrush/ along with or without http://trimage.org/
最近有一些关于 JPEG 图像压缩库的工作,该库在许多应用程序中使用,包括 Firefox 和 Chrome 等浏览器。这个新库通过使用现代 CPU 中可用的特殊媒体处理指令,显着提高了速度。 可能只是因为您的 Chrome 版本不使用新库。
您的问题要求提供一种修复图像的方法,但这不是必需的 - 毕竟其他一些浏览器也可以使用美好的。因此,修复应该在浏览器中进行(并且浏览器正在不断改进)。
您说您通过大幅降低图像的质量或复杂性来提高 Chrome 的速度。这可以通过以下事实来解释:对于细节非常低的区域,JPEG 解压缩算法可以绕过通常需要执行的许多工作。如果 8x8 的像素图块可以减少为单一颜色,那么该图块的解压缩就变得非常简单。
这篇维基百科文章提供了一些附加信息和来源。它说 Chrome 版本 11 有新的库。您可以在地址栏中输入“chrome://credits”,看看它是否引用“libjpeg-turbo”。 “libjpeg”是原始库,“libjpeg-turbo”是优化版本。
另一种可能性是 Mac 上的 Webkit 不支持 libjpeg-turbo(尽管我具体不知道)。 此处发布了关于为什么会出现这种情况的提示< /a>.
PS 您可以通过使用不同的算法(例如 PNG)进行压缩来获得更好的解压缩速度(尽管您的压缩率可能会受到影响)。另一方面,也许您应该使用 HTML5 视频,可能使用 WebM 格式。
There has been some relatively recent work on the JPEG image compression library that is used in many applications including browsers such as Firefox and Chrome. This new library achieves a significant speed increase by using special media-processing instructions available in modern CPUs. It may simply be that your version of Chrome doesn't use the new library.
Your question requests a way to fix your images, but that shouldn't be necessary -- after all, some other browsers work fine. Therefore, the fix should be in the browser (and browsers are constantly being improved).
You said that you improved Chrome's speed by dramatically reducing the quality or complexity of your images. This could be explained by the fact that for areas of very low detail, the JPEG decompression algorithm can bypass a lot of the work that it would normally need to perform. If an 8x8 tile of pixels can be reduced to a single color, then decompression of that tile becomes a very simple matter.
This Wikipedia article provides some additional info and sources. It says that Chrome version 11 has the new library. You can enter "chrome://credits" in your location bar and see if it references "libjpeg-turbo". "libjpeg" is the original library and "libjpeg-turbo" is the optimized version.
One other possibility is that libjpeg-turbo isn't supported in Webkit on the Mac (although I don't specifically know that). There is a hint as to why that might be the case posted here.
P.S. You may get better decompression speed by compressing with a different algorithm, such as PNG (although your compression ratios will likely suffer). On the other hand, maybe you should use HTML5 video, probably with the WebM format.
我在 Opera 中测试了它,它运行得非常慢,我注意到 Opera 已经排队下载了 150 多张图像,一次下载大约 20 张是否值得尝试?
I tested it in opera and it ran slow as hell, i noticed that opera had queued 150+ images to download it could be worth a try to download ~20 at a time?
另一种方法是将此内容呈现为视频 - 它是此类内容的理想选择并且可以轻松包含音频和字幕。如果您想变得时髦,您可以使用 JavaScript 访问每个帧中的每个像素。
An alternative approach would be to render this content as a video - it is ideal for this kind of thing and can easily contain audio and subtitles. You can access each pixel from each frame using JavaScript if you want to get funky.