
PNG vs SVG for sprites - obilgic
http://codepen.io/adrianosmond/pen/LCogn
======
yason
That'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.)

~~~
overgard
That 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#AccessingBackgroundIma...](http://www.w3.org/TR/SVG/filters.html#AccessingBackgroundImage)

~~~
corresation
>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.

~~~
sambeau
SVG has the added problem of not knowing what size/detail it needs to be
rendered to - while the image has a size it never knows to what scale it's
going to be drawn. If we could provide hints we'd be able to cache a bitmap
and scale it without the need to redraw. Even better would be to do away with
the bitmap altogether and draw them as triangles.

I'd love to see some of the new vector map detail algorithms applied to SVG -
the ones where you throw away any detail smaller than a pixel. Then we'd be
able to zoom smoothly or (if the points need to be calculated and cached)
progressively loading (and possibly streaming) detail.

~~~
seanmcdirmid
I believe Loop and Blin have done a lot of work in this area. See for example,

[http://research.microsoft.com/en-
us/um/people/cloop/LoopBlin...](http://research.microsoft.com/en-
us/um/people/cloop/LoopBlinn05.pdf)

If someone like Ben Constable is lurking in this thread, he'd be able to say
more this; I am extremely ignorant about this problem.

------
vanderZwan
Considering 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=zI...](https://www.youtube.com/watch?feature=player_detailpage&v=zI8cJMjEVBE#t=43s)

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.

~~~
phoboslab
Just 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)

~~~
pbsurf
Have you looked into using Loop-Blinn[1] for drawing Beziers? I'd love to be
able to use the GPU for vector graphics and Loop-Blinn seems to solve the
problem of drawing curves, but I'm still looking for a way to get coverage-
based antialiasing when drawing straight lines with the GPU.

[1]
[http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html)
\- [https://github.com/hansent/lbfont](https://github.com/hansent/lbfont) is a
good example

~~~
seanmcdirmid
Anti-aliasing seem to be why we still prefer pixel art over vector art. I
thought high-res would eliminate this problem (more pixels, less worry about
artifacts), but apparently not yet.

The Loop/Blinn work is really cool, and of course we now have hull shaders to
really exploit it. It is a problem many people are actively working on...e.g.
with Direct2D, but doing everything on the GPU is currently infeasible given
round trip times between the CPU and GPU. Great if you can render everything
in one pass, not so great if you can't.

------
mpyne
This 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.

------
bsimpson
Sprites 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
How 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.

~~~
elithrar
SPDY[1] multiplexes multiple assets over one connection, which will (one day;
many years from now; eventually) resolve some of the performance issues with
HTTP and TCP.

You can already use SPDY now (and fall back to HTTPS), FWIW.

[1]: [http://www.chromium.org/spdy/spdy-
whitepaper](http://www.chromium.org/spdy/spdy-whitepaper)

~~~
ricardobeat
SPDY has been enabled on both Chrome and Firefox for over a year.

[http://caniuse.com/spdy](http://caniuse.com/spdy)

------
anondesign
Updating 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
+100

I can't believe nobody else mentioned this.

~~~
snookca
Animating 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
Eh, 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.

------
kevingadd
The SVGs perform great in Internet Explorer 10, FWIW. Probably because of how
good their hardware acceleration pipeline is.

~~~
sahaskatta
On IE 10, SVG is just as smooth as PNG. I can't tell the difference.

~~~
bliker
off 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
Can 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
[https://en.wikipedia.org/wiki/Usage_share_of_web_browsers](https://en.wikipedia.org/wiki/Usage_share_of_web_browsers)

------
rbirkby
Adding #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
A 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
And fixed:

[http://src.chromium.org/viewvc/blink/trunk/Source/core/svg/g...](http://src.chromium.org/viewvc/blink/trunk/Source/core/svg/graphics/SVGImage.cpp?r1=152895&r2=153069&pathrev=153069)

------
gales
There 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
You 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.

------
NelsonMinar
What'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?

~~~
kllrnohj
Scrolling 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.

------
zopticity
SVG 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
IE 10 is the current version. It has already taken about 20% of IE 9's market
share.

------
ysvg
Did 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/)

------
andy_ppp
Just 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)

------
cbhl
I'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
Those 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.

~~~
overgard
In 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
>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.

------
babuskov
I 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.

------
egypturnash
Huh. 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
Are 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?

------
bitsm
So 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).

------
ernesth
What 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!

------
cies
I'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)

------
tome
Exactly 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
Why are you on an old Firefox?

------
mnot
Or just don't use sprites, once you're on SPDY/HTTP2. It won't be necessary;
win-win.

------
tambourine_man
I'd like to see that in OS X Mavericks, since smooth scrolling is one of its
main features.

~~~
lloeki
Safari 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.

------
voltagex_
Performance is pretty good with both on IE10. I never thought I'd see the
day...

------
dig1
Closed 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.

------
ProfAesop
I've noticed a similar problem while browsing thenounproject.com

------
otikik
Needs a third option with font-based vectors (a la font-awesome)

------
lqdc13
both result in 100% cpu use in ubuntu + chrome/firefox on 3570k processor.
Conclusion: don't use that many sprites.

~~~
Jam0864
Seems like a Ubuntu issue... uses 5% CPU on my 2630QM under Windows, which is
a slower chip.

------
throwmeaway33
This crashes Opera....

