14 ms·
PNG vs SVG for sprites
- cbhl 13y agoI'm not sure if this is surprising. Even the proprietary Macromedia Flash showed us in the late 90s that vector graphics are more computationally expensive than raster equivalents. SVG is nice because it gives us additional flexibility -- it's resolution independent (so you don't need to redraw your image by hand when higher-DPI displays come out) and allows for animation[0]. But if you don't need those things (and you probably don't for your sprites) then they'll just slow you down. [0] http://en.wikipedia.org/wiki/SVG_animation http://en.wikipedia.org/wiki/SVG_animation
- corresation 13y agoThose things shouldn't slow you down at all if you aren't using them: this is a browser optimization issue. The browser knows that the SVG has not changed in any way, and can with absolute accuracy discern that it can simple blit the pre-rendered raster. Browsers have not optimized SVG at all, painfully clear when the simplest retained dynamic SVG graphic is magnitudes slower than building entirely new framebuffers from scratch for every frame, ala canvas. It is trivial to see that the former should see dramatic optimizations that make it a significant winner, but in actual practice that just hasn't happened. So it's a classic chicken/egg thing. No browser maker does anything to optimize SVG because few use it. Few use it because it's so unoptimized. The findings of this post remain the same in either case, and is completely correct, but it shouldn't be this way. It isn't right that this test favors PNG.
- ChuckMcM 13y agoI think this captures the state of the world more accurately. Every time that someone discovers how cool SVG would be if it did what the documentation said it did in browsers, they follow up with "but this actually sucks in real browsers". If the early reports of IE10 support hold up this might change. It was my hope that retina screens would be the force to finally put real SVG support into browsers (and by real I mean both standards compliant and accelerated) because they benefit so much from line content using SVG.
- twistedpair 13y agoAmen. Discovered this two years ago. FF without Direct2D (i.e. XP) sucks greatly for SMIL SVG animations. It is such a shame as many complex things were trivial with the SMIL/SVG API's, but FF and Chrome have a long list of bugs and missing API implementations which they apparently don't care to correct.
- overgard 13y agoIn some ways though, this reminds me of the arguments about the speed difference between static languages and dynamic languages being an "interpreter optimization issue". Well, yeah, but, the reason these things are slow is because optimizing them is kind of hard. I think the SVG spec was more designed for correctness than it was for speed. I'm saying this from experience because I've actually been working on a library for supporting a subset of SVG in OpenGL because I wanted to use vector graphics for games, and it's not impossible or anything, but I will say I have a great deal of respect for projects that manage to get this fast. The SVG spec is not hardware friendly in the least bit. Almost every filter operation assumes a new clean render target, which is conceptually clean and fine, but it's murderous on fill rate and texture memory, and that's just the tip of the iceberg of things that translate poorly to modern hardware.
- corresation 13y ago>Well, yeah, but, the reason these things are slow is because optimizing them is kind of hard. Optimizing all cases is most certainly hard. Optimizing the most common cases -- the lowest hanging fruit -- is attainable (which is exactly what has happened and continues to happen with dynamic typing languages, since you point that out, and has happened substantially to the DOM, which itself is as complex or more complex than SVG but its layout optimization was obviously prioritized). In this case we're talking about static SVGs that -- with no change in zoom, context, or content (ergo nothing that would change their actual rendering at all) -- are completely rebuilt on every translation. This is true generally in the browser rendering engines of SVG, where compositional elements that could see caching are instead from scratch on each and every render.
- seszett 13y agoThis SVG/Canvas thing reminds me of this visualization[1] I did last month or so which originally made heavy use of SVG, because it was just about good enough on Chromium (and it made sense for d3js and hexbons)... but when I tested it under Firefox, it was just unusable. So I recoded it to use canvas instead (with a switch to allow using one or the other) and there is just comparison, it's much faster everywhere. I've had reports that the SVG version was working fine on IE10 though, but couldn't test it because there's no IE10 for Linux of course. It quickly becomes frustrating to make complex visualizations when SVG makes a lot of things much easier, but you constantly hit the limits of SVG performance on the common browsers. [1] http://ssz.fr/places/?frukie#^saint/^ll/ton$ http://ssz.fr/places/?frukie#^saint/^ll/ton$
- emn13 13y agoNeat! And indeed, it seems to work fine in IE10 under both canvas and SVG modes.
- Chris_Newton 13y agoNo browser maker does anything to optimize SVG because few use it. You said something like that multiple times in your post, but IE seems to handle a lot of SVG work much better than Firefox or Chrome, and has done since at least version 9.
- taeric 13y agoIs it not feasible to load a vector graphic into a raster equivalent on first load? Startup time would, predictably, be slower, but just moving something around the screen would then be equivalent. (Obviously, some actions could trigger a redraw of the vectors, but I would think this would actually be a limited set of interactions.)
- georgemcbay 13y agoYes, this is feasible and Flash did this (optionally). Flash supported this as a trade-off via the cacheAsBitmap attribute on elements. Basically you'd set that to true if you knew the sprite was just going to be translated around in x/y and not scaled or rotated. It wasn't on as the default for new sprites because this mode would actually bite you in the ass if the sprite was going to scale/rotate nearly each frame because the cost of recreating the "cached" version would then be added to the render time without actually ever being useful. So it is a good idea in practical usage to make this an optional feature, though I think Flash could have been smarter about it (like soft-default to caching and only override that once it sees a scale or rotate taking place).
- jarek-foksa 13y agoSVG 1.1 spec defines suspendRedraw() and unsuspendRedraw() methods which seem to have somehow similar purpose, though those can be applied only on <svg> elements, are supported only by Firefox and are going to be deprecated in SVG 2.0.
- egypturnash 13y agoI will note that Flash also had some really terrible redraw logic; if you had a largely static image with something animating in the upper left and lower right corners, the dirty rectangle would cover the whole thing.
- joshtynjala 13y agoAround the Flash Player 10 days, I remember seeing a presentation from someone at Adobe that showed off their debug feature that allows developers to see dirty rectangles. The demo showed that the renderer would use up to two dirty rectangles when redrawing. In your example with two corners, it wouldn't be one giant rectangle that filled the full stage. It would be two smaller rectangles, as one might expect. However, once something was moving in a third corner, one of the two rectangles would need to expand. Again, this was probably 3-5 years ago, and older versions of Flash Player may have been less optimized. This may be one of the many optimizations they made to Flash Player after Apple decided it wasn't fast enough for iPhones.
- egypturnash 13y agoThis was back around... 2003 I think? It would have been back in version 5 or 6 of the editor.
- sambeau 13y agoThis is not true or at least it is more complicated than you suggest. The computationally complex bit is triangulating the image. If you can do that the graphics card will have an easier time drawing the vectors than it will shuffling all those textures around. In fact you could send all your vectors in one draw call. What we need is browsers caching SVGs as geometry not pixels.
- mpyne 13y agoThis is the big reason we had to write a pixmap caching layer for icons/Plasma themes/etc. in KDE. GTK+ goes one better, and they compile an entire icon theme into a single mmap-able file with the data in a static GdkPixbuf format. Sadly I'm not sure how to map that to a QImage in general, otherwise I would have adapted that theme cache (where present) into KDE.
- zopticity 13y agoSVG is scalable, if you have a vector-graphic that is a clear advantage. For pixel-graphics PNG is better. A downside is, that the Internet Explorer supports SVG only with the coming version 9 (before with plugin). Mobile browsers may also have limited support for SVG. I would say PNG simply for the fact it seems to be a more accepted format than SVG.
- sp332 13y agoIE 10 is the current version. It has already taken about 20% of IE 9's market share.
- twistedpair 13y agoOlder Android browsers lacked SVG support too. Bug report said it was to save a few MB off binary. Come on man. Webkit acceleration is getting much better, and for those ancient IE browsers, check out RaphaelJs which translates them into MS approved VML.
- deleted 13y ago[deleted]
- yason 13y agoThat's just a browser problem: for such static graphics it shouldn't matter what the original image format is. The browser will generate an internal bitmap for each decoded PNG image, and uses that for blitting/compositing. Any decent browser ought do the same for SVG icons as well (and just invalidate the bitmap when the SVG image size/rotation or page zooming changes). When compared to blitting, stroking and filling paths is expensive and so is PNG decoding. Of course, SVG can be rotated and scaled and animated nicely, unlike PNG. That will obviously be slower if done every frame. But this isn't the case and shouldn't be the case for such static icons. (Of course, the current state of affairs probably is as described on the demo page. But it doesn't need to be.)
- Nekorosu 13y agoThanks for sharing the thought 'cause at first the demo looked meaningless to me. Now it makes sense.
- overgard 13y agoThat works for the sprite example, but it doesn't generalize to all SVGs. The problem is SVG filters let you do some pretty cool compositing stuff, but you can't necessarily generalize those effects in a static image. For instance, you could blur elements on the page using an SVG blur filter overlayed over your html elements, but if you're just blitting from a static buffer (like with a PNG), it's going to be wrong, so now you're not just paying attention to if the SVG changes, you also have to pay attention to if anything underneath it or around it changed. It's not an impossible problem, but I think you could still call a browser decent if it doesn't bother with that sort of specialized optimization. See: http://www.w3.org/TR/SVG/filters.html#AccessingBackgroundImage http://www.w3.org/TR/SVG/filters.html#AccessingBackgroundIma...
- corresation 13y ago>The problem is SVG filters let you do some pretty cool compositing stuff This is true for every single DOM element, which can layer and obscure and filter and be additive/subtractive and can have levels of translucency. This is not a novel problem with SVG, but it's one where the appropriate solution is a simple if (isComplexCase) { // do uglier, more processor intensive activities } else { // do things the short and simple way } The universe of possibilities on an artifact don't prescribe a baseline performance level unless you're actually using them. And just to be clear, I don't fault the browser makers at all regarding this (any of us can contribute to Chromium/Webkit/Firefox), as they are simply optimizing their efforts towards the things that yield the biggest return, and optimizing SVG just isn't that critical. Yet this leads to a circular situation where we endlessly hear that you shouldn't use SVG because performance suffers.
- kevingadd 13y agoThe SVGs perform great in Internet Explorer 10, FWIW. Probably because of how good their hardware acceleration pipeline is.
- sahaskatta 13y agoOn IE 10, SVG is just as smooth as PNG. I can't tell the difference.
- bliker 13y agooff topic, but IE 10 is really good browser, I just recently discovered how good Devtools are (I dare everyone to go and check). And compared to Chrome the RAM and CPU are less drained.
- monsterix 13y agoCan someone point me to the latest browser distribution on the planet? Last check it was 50-50 tussle between IE and non-IE (If I can call it this way) browsers.
- sahaskatta 13y agohttps://en.wikipedia.org/wiki/Usage_share_of_web_browsers https://en.wikipedia.org/wiki/Usage_share_of_web_browsers
- bzbarsky 13y agoDistribution of browser installs, browser users, or site visits by browsers? The numbers for those three look quite different from each other....
- MichaelGG 13y agoI'd consider using it again, but the UI is just so ugly. Maximized, it has a useless border at the top of the window for no reason (which hurts on low res laptop screens). And in general, the tabs are next to the URL, so you never get to see a remotely full title or URL. And, to top it off, the URL/tab part looks like a dev preview. It doesn't look like anyone took time to make that part look pixel perfect. For general purpose use, I'd expect all modern browsers to deliver a generally decent experience, so the actual chrome is relevant. On top of that, IE10 has no plugin model, so getting basics like privacy and ad blocking - there's just no reason to use IE10 outside of specific demos.
- NelsonMinar 13y agoWhat's strange is that scrolling SVG can be quite smooth in browsers, at least in Chrome. The map library Leaflet, or instance, makes a point of panning the map with -webkit-transform: translate3d() and it animates very smoothly. I wonder why scrolling the whole window like this is worse?
- twistedpair 13y agoAnimation with SMIL and SVG is even more feature packed.
- kllrnohj 13y agoScrolling repaints the content (expensive) Changing a translate3d does not repaint the content, it simply translates a GPU texture (damn near free) Sadly desktop browsers haven't caught up to their mobile equivalents yet and still have brain dead scrolling.
- gales 13y agoThere are icons in the SVG sprite set which consist of numerous clip paths, which could be the root cause of the performance issue. If you load the sprite in Chrome (http://adrianosmond.com/images/sprite.svg http://adrianosmond.com/images/sprite.svg) and inspect the element immediately above the facebook logo you will see an example of this. That aforementioned icon could possibly have been created using a single line path and gradient fill (I've not edited SVG files for a while).
- ygra 13y agoYou cannot have a gradient following a curve. At least not yet. You could probably use some filter trickery and thus create a fill where a gradient follows the path but I bet that's much worse than a few dozen paths.
- anondesign 13y agoUpdating scrollTop is a pretty slow way to scroll on some browsers. Have you tried animating `transform`? That gets you hardware acceleration on webkit at least
- nickporter 13y ago+100 I can't believe nobody else mentioned this.
- snookca 13y agoAnimating transform doesn't affect page scroll, which is a more useful use case (since users need to scroll a page) than being able to use a translate transformation. Of note, a translate transformation still isn't perfect. It seems to chug and then turn into a smooth animation.
- anondesign 13y agoEh, updating page at end/cancel easy enough. I use this approach to animate a page scroll: 1. Animate #transform using jquery's animate (which doesn't work out of the box unfortunately, you have to use a custom #step fn) 2. Install "capture" event handlers on document.body that will cancel the animation, reset scrollTop to the state of the transform, then reset the #translate to 0 on #scroll or #touch (so we don't "fight" the user scrolling) 3. .. animation runs, calls my "complete" callback which uninstalls the event handlers, sets #translate back to 0, and updates scrollTop. Unfortunately there is a noticeable "glitch" here if the user tries to immediately further interact with the page. #2 is optional (OP's implementation didn't handle canceling anyways). I'm sure there's a jquery plugin to do this and degrade to scrollTop on non-webkit browsers. Edit: formatting.
- just2n 13y agoAdditionally, jQuery is not known for its performance, especially regarding animations. For me, on Chrome Canary, the animation "chugs" every 20-30 frames (from 60 fps to a frame that takes 200ms). It's almost entirely in rendering, and it's immediately following a jQuery callback. It only happens when scrolling down. I'd like to see this done with a very simplistic requestAnimationFrame tweener to compare the same type of animation against something that is doing nothing else but computing a new scrollTop and setting it. I have a strong feeling, in Chrome at least, that the problem here is jQuery, not SVG perf. Additionally, for other browsers, I'd like to see this tested with icon fonts.
- vanderZwan 13y agoConsidering the vast majority of our time behind the computer is spent with software that uses 2D graphics, it is kind of ridiculous that we still don't properly exploit our graphics hardware for vector graphics. Luckily the hardware vendors are already working on fixing this. Here's an example of a particularly problematic scene rendered using NVIDIA's GPU-Accelerated Path Rendering, compared to Skia, Cairo, QT and Direct2D: https://www.youtube.com/watch?feature=player_detailpage&v=zI8cJMjEVBE#t=43s https://www.youtube.com/watch?feature=player_detailpage&v=zI... NVidia: ~220 fps Skia: 6 fps Cairo: 29 fps QT: 0.3 fps Direct2D: 48 fps (On a sidenote, I guess this is why IE10 is often faster at rendering SVGs than the other browsers: it uses Direct2D, whereas Firefox and Chrome use Skia). Using graphics hardware should be more energy-efficient, so maybe we will finally see a change because of mobile devices with HD screens.
- zw 13y agoIs Safari/native WebKit hooking straight up to Core Animation on OS X and iOS? I know when the Windows version was still around its WebKit was using Direct2D, even before IE did. I wonder what that would look like in the comparison.
- azakai 13y ago> (On a sidenote, I guess this is why IE10 is often faster at rendering SVGs than the other browsers: it uses Direct2D, whereas Firefox and Chrome use Skia). I think Firefox on Windows uses Direct2D, at least for Canvas, not sure if for img tags.
- phoboslab 13y agoJust to throw this in: my iOS project Ejecta[1] also does all the Vector drawing on the GPU using OpenGL ES2. It's not as advanced as NVidia's implementation (e.g. Ejecta computes all bezier points on the CPU and just draws on the GPU), but it's still much faster than what Apple is doing in CoreGraphics. [1] http://impactjs.com/ejecta http://impactjs.com/ejecta
- vanderZwan 13y agoThat is a really cool project, thanks for sharing! > (e.g. Ejecta computes all bezier points on the CPU and just draws on the GPU) I guess that's where the biggest gain comes from with NVIDIA: it's the only pure-GPU option right now, which probably eliminates quite a few bottlenecks. Freeing up the CPU is also never a bad thing.
- tome 13y agoExactly the same for me. I'm on an old Firefox (10.0.6) so maybe it's poor PNG performance rather than good SVG performance.
- dochtman 13y agoWhy are you on an old Firefox?
- rbirkby 13y agoAdding #container {-webkit-transform: translateZ(0);} puts the whole div as a texture onto the GPU as a composited layer. This improves scrolling massively, but interestingly SVG still has a little bit more jank than the PNG version. See http://jankfree.org http://jankfree.org
- rbirkby 13y agoA Chrome/Blink issue has already been raised for this: https://code.google.com/p/chromium/issues/detail?id=253091 https://code.google.com/p/chromium/issues/detail?id=253091
- rbirkby 13y agoAnd fixed: http://src.chromium.org/viewvc/blink/trunk/Source/core/svg/graphics/SVGImage.cpp?r1=152895&r2=153069&pathrev=153069 http://src.chromium.org/viewvc/blink/trunk/Source/core/svg/g...
- leptons 13y agoIt probably would also help if this were done as pure inline SVG instead of CSS background images. It doesn't surprise me that adding a ton of SVG background images to the page would cause some browsers to behave badly.
- ernesth 13y agoWhat is it? What shoud I see? What does it demonstrate? I followed the link which opens an html/css/js editor in which I cannot do anything. After some search I saw a white page with a list of icon a radio button switching from png to svg and some text about framerate where I do not see any animation or any difference between the two!
- egypturnash 13y agoHuh. Interesting. Activity Monitor gives me some weird numbers for Safari's performance as I watch this on my dual i5 Macbook Air. When scrolling the PNGs up and down, Safari oscillates between 64 to 94% CPU usage. When scrolling the SVGs up and down, it goes between 36-54% CPU. Very very strange. I wonder if it has something to do with the fact that the SVG is dropping about a zillion frames.
- bzbarsky 13y agoAre you looking at just the Safari process or also the Safari Web Content process and the parts of the work Safari offloads to WindowServer and whatnot?
- mnot 13y agoOr just don't use sprites, once you're on SPDY/HTTP2. It won't be necessary; win-win.
- babuskov 13y agoI know EaselJS library has capability to cache the bitmap representation of SVG, so if you do not change stroke settings, paths, etc. it works really fast. When you change, you need to update the cache manually. This works for HTML5 Canvas, but they also have DOMElement class which is still experimental so YMMV. Or maybe there is some other lib. that does specifically for DOM.
- lqdc13 13y agoboth result in 100% cpu use in ubuntu + chrome/firefox on 3570k processor. Conclusion: don't use that many sprites.
- Jam0864 13y agoSeems like a Ubuntu issue... uses 5% CPU on my 2630QM under Windows, which is a slower chip.
- bsimpson 13y agoSprites are a dirty hack that works around the fact that HTTP 1.0 only allows one asset to be returned per request. Using CSS background-images to represent content is semantically gross. If you wanted to the same advantages with SVG, you shouldn't be using CSS sprites; you should take advantage of the fact that SVG is a text-based format and concatenate them all together. Then, you can use some really simple JavaScript to insert each child SVG into the correct place in the DOM. The ideal way to handle this would look like this: <img src = "icons.svg#map" /> where map.svg was the original file on the developer's machine. A grunt task could concatenate all the SVGs in a particular folder together and give them IDs according to their file names. In the client's browser, a JS prollyfill would iterate over all the img tags where src ends in a hash and replaces them with the child SVG of that ID. Just as the prevalence of $$ inspired querySelectorAll, an SVG-optimized spriting system could inspire browser vendors to properly handle hashes in src attributes. and the need for the prollyfill (or the ugliness of CSS spriting) would fade over time.
- dkuntz2 13y agoHow would you make HTTP better? How could you get it to send multiple files per request, because, while a little weird in some ways. HTTP is really quite well designed, there isn't really a good way to send multiple files with one request, unless you want to mage HTTP kinda hacky. Sorry, I've had to write an HTTP compliant server recently, and I don't think there's any good way to send multiple files without completely redesigning the protocol, and even doing that, I don't think there's a good way to do it. Plus, keeping requests atomic makes more sense than bungling then together. I know the main point of your comment wasn't too make HTTP better, just that sprites are, in your opinion, a bad hack, but your implying that HTTP is bad. Also, and this is just nitpicking, everyone uses 1.1, which has persistent connections in the spec, which help negate some if the computing cost for sending multiple files.
- Zarel 13y agoErr, SPDY sends multiple files per request... I suppose it counts as "completely redesigning the protocol" though.
- 13y ago
- throwmeaway33 13y agoThis crashes Opera....
- voltagex_ 13y agoPerformance is pretty good with both on IE10. I never thought I'd see the day...
- tambourine_man 13y agoI'd like to see that in OS X Mavericks, since smooth scrolling is one of its main features.
- lloeki 13y agoSafari 6 and iTunes 11† already use CoreAnimation for scrolling. Mavericks "merely" extends this to other apps. †: Saf' was advertised to do so, and since neither respect defaults write -g NSScrollViewRubberbanding -bool false while being butter smooth, I concur iTunes does so too.
- ProfAesop 13y agoI've noticed a similar problem while browsing thenounproject.com
- bitsm 13y agoSo this is an interesting case for animation, but turn off the javascript and try real-world (manual) scrolling -- both pngs and svg perform about the same for me in Chrome (osx). I'm not sure there's much of a takeaway here unless you're trying to animate the page scrolling of a full page of sprites (i.e., the example proves itself, but not much else).
- cies 13y agoI'd be interested to see you icon-fonts perform in the test. (knowing that it is not really the same thing as you only have monochrome icons in fonts, unless you layer them)
- otikik 13y agoNeeds a third option with font-based vectors (a la font-awesome)
- ysvg 13y agoDid anyone of you try to use the SVG as a stack? It is very easy to maintain (no pixel values in the CSS)... See: http://hofmannsven.com/2013/laboratory/svg-stacking/ http://hofmannsven.com/2013/laboratory/svg-stacking/
- dig1 13y agoClosed after noticed the page will scroll up/down automatically. Quickly tried SVG version and my browser (latest Firefox) skyrocketed CPU. Guys, please make your pages usable since (we), users, are not interested in you-think-it-is-cool effect. I'm going to avoid this page like plague until author fixes it.
- andy_ppp 13y agoJust as an aside Firefox has a bug which means it blurs SVGs that are being displayed at a different background-size than 100% 100% (or equivalent in other units), if the width and height set in the SVG is smaller than the size at which it is displayed as a background image. This happens because Firefox apparently (only for background images) renders the SVG at it's size settings and then scales it for use in the page. This is the same type of issue as discussed in the example - it's a bug in the browser not a problem with SVGs in general. See the related bug here: https://bugzilla.mozilla.org/show_bug.cgi?id=600207 https://bugzilla.mozilla.org/show_bug.cgi?id=600207