Closed Thread Icon

Topic awaiting preservation: Animation vs. efficiency trade-offs/tricks (Page 1 of 1) Pages that link to <a href="http://ozoneasylum.com/backlink?for=25730" title="Pages that link to Topic awaiting preservation: Animation vs. efficiency trade-offs/tricks (Page 1 of 1)" rel="nofollow" >Topic awaiting preservation: Animation vs. efficiency trade-offs/tricks <span class="small">(Page 1 of 1)</span>\

 
Scott
Paranoid (IV) Inmate

From: schillmania.com
Insane since: Jul 2002

posted posted 05-11-2005 04:21

Alright, time for the question I'm sure there's been a lot of previous discussion/debate on before (which heck, I'm sure I probably participated in at some point):

"What are some tips/tricks for making animation code efficient, particularly when dealing with moving a good number of items simultaneously?"

A summary of what I believe to be true thus far:

  • Canvas animation (background on a DIV) > separate images regarding efficiency

  • Lots of images == bad (slow, inefficient)?

  • One main animation loop == good, preferable to use setInterval() rather than recursive setTimeout()

  • Win98 animation framerate is better with two "staggered" setInverval() calls (A weird find I made! )

I've messed around with animation experiments a fair bit in various older projects (eg. "flash-like" portfolio, or dhtml arkanoid etc.) and I think I've been fairly successful in terms of maintaining a good frame rate across various browsers/platforms, but I realised it was probably because in these cases (Arkanoid sometimes not) I wasn't moving a lot of images simultaneously.

.. Which brings me to the newer stuff I was tinkering with.

Working on a personal side-project, a fireworks experiment, I've found the performance really degrades quickly with lots of image elements flying around (well, duh,) but markedly moreso than I've seen previously. (Pardon my lack of math skills, also.)

Fireworks approach/notes:

  • OO-based, firework object creates multiple element objects which animate and fade out

  • One image per firework "type" which contains 10 states (100% to 10% opacity, for simple non-filter-based fade - another possible slow-point)

  • IE flickers the "wait" cursor when moving elements with background images, so I tried <img> in a cropped DIV instead

  • Element objects grab associated HTML structure from an existing "template" node, using cloneNode() rather than creating structure etc. in script (thanks to some old buddies at my previous employer for the idea) - cleaner, benefit of preloaded images, possibly faster?

  • Resorted to using GIFs rather than PNG for the time being due to IE and assumed speed benefits (no filtering)

I tried a few different techniques along the way (PNGs, playing with image size during animation, using a background tile, filters and .style.opacity for fading etc.), and I haven't compared side-to-side yet but feel the cropped div/img technique seems to work well. Am I going the wrong way here?

Also related, this photo thing I was playing with earlier uses a cropped div/img combo which is quite smooth in IE, but noticeably slower in Firefox and even worse on the Mac. (Again, sorry about the math in the code being a bit off.)

By contrast, Safari and Firefox on the Mac render the fireworks animation considerably smoother than the photos experiment. Is it related to the image size perhaps (and the cropping), not necessarily the number of images in this case that's the bottleneck?

In summary, I thought I'd post some findings I've made and collective knowledge from tinkering with code in addition to reading others' posts and thoughts on the subject.. but knowing the Asylum's collective knowedge far exceeds that of any individual, I thought I'd put the question out there and see what else comes up. I'm thinking of a few (cough cough.. Poi..) people in particular who I know have done some nifty things in this area.

(Edit)

It would appear those Norwegians are onto something - Opera 8 runs that firework animation faster than anything else I've got (vs. IE/FF on Win32 as well as Safari/FF on Mac.) They have definitely improved their browser lately. Impressive!

(Edited by Scott on 05-11-2005 05:39)

Iron Wallaby
Paranoid (IV) Inmate

From: USA
Insane since: May 2004

posted posted 05-11-2005 07:25

Opera is wicked fast. Safari is catching up... in 2.0, it's better than MSIE now, unless I'm mistaken. FF is still the chugging workhorse, but since it's compatibility is sooo much better than MSIE, you better believe I'm not complaining.

BTW - very impressed with the flash-like intro/stuff on your page. Very sexy, fast, etc. Flash coders should look at this stuff -- it's amazing what can be done in modern browsers, neh?

A few things I've found myself:

  • Working on a DIV is faster than on the body.
  • Using DOM elements is faster than innerHTML/text-manipulation methods. Pretty obvious.
  • Images are very slow, compared to blank DIVs. However, images are far more versatile (for example, p01's line technique; in fact, images are faster here since it's 1 image compared to, perhaps, 100 divs). (Also -- make sure you cache the images so the don't need to reload a million times in MSIE.)
  • OOP code tends to be slow. Not just in Javascript, but in everything. Speed often is the price to pay for clean code. Functional code is better, procedural code is best. However, Javascript is a functional language at heart, and thus lends itself well to those techniques. I find my maddeningly recursive functions run faster than many interacting objects, though the comparisons are probably unfair.
  • Opacity is only slow in Mozilla (and Opera?). In MSIE/Win and Safari, it's done in hardware.
  • Lots of elements, even ones that don't move, will slow everything down. HTML was never designed for efficient rendering. So even if you just want to keep adding non-moving elements, it's just gonna get slower and slower, as the renderer has to deal with more and more data...
  • Precompute EVERYTHING.
  • Also, save links to nodes when possible (for example, load document.getElementById etc. early). Save's hunting through nodes = less pointer manipulation = speedier code.


That said, I love little JS renders, since the limitations and presentation possibilities make for lots of creativity and lots of power, not to mention a huge audience.

---
Website

(Edited by Iron Wallaby on 05-11-2005 07:31)

poi
Paranoid (IV) Inmate

From: France
Insane since: Jun 2002

posted posted 05-11-2005 23:30

you already covered a lot of points. However :

  • manipulating images is not slow if you don't go crazy on their size and number ( changing 2-3 style attributes of 50 clipped images is not/shouldn't be slow at all )
  • having a hell lot of elements is ok as long you update only few of them per frame and they don't overlap or have an impact on the others.
  • innerHTML is ok to append of big load of nodes, that you retrieve then with getElementsByTagName() or through the childNode array/collection
  • canvas animation works better ( and is more flexible ) when you nest an IMG in a DIV rather than using a DIV and its background property
  • If you have some if statements order the conditions from high probability to low probability

Obviously the less work in the inner loops, the faster the result.

Last but not least, since ~ the version 0.7 of FireFox/Bird I noticed it is ~4 times slower than Mozilla for the intensive scripts I'm fond of .

Scott: In the photo thing, I noticed you set the clip property of the DIVs in the CSS. Is it for compatibility reasons ? Because there's no need for it since you already set the width and height and the overflow is hidden. Though I doubt it has a significant impact on speed if any.



(Edited by poi on 05-11-2005 23:35)

Scott
Paranoid (IV) Inmate

From: schillmania.com
Insane since: Jul 2002

posted posted 05-12-2005 08:35

Iron Wallaby: Thanks for the kind words.

The portfolio site was the result of what was originally two separate ones (making a JS-based animation library, and then a need to build a new portfolio.) It's been almost a year since I launched it and it's pretty much been left alone, but I haven't really needed to demonstrate my work stuff as I've been busy and am currently quite happily employed. (I got a lot of great comments from people who saw the site, thinking it was Flash and surprised to realise otherwise - one of my long-time goals!)

Further to your notes:

.. Using DOM elements is faster than innerHTML/text-manipulation methods. Pretty obvious.

I had heard a few mixed opinions on this one, the jury seems to be out from what I recall reading; PPK (quirksmode.org) had done some tests if I recall correctly and found it depends on the browser, the efficiency seems to vary.

Opacity is only slow in Mozilla (and Opera?). In MSIE/Win and Safari, it's done in hardware.

Hadn't really thought about this one, but it makes sense that the "OS browsers" would take advantage of their respective core graphics libraries for some rendering stuff.

Lots of elements, even ones that don't move, will slow everything down. ... Precompute EVERYTHING.

Amen to that. The more elements the browser has to iterate through etc., the slower it'll run. I have objects removing themselves from the DOM as they die out (as well as references to other DOM elements thus helping to ensure garbage collection works in IE, etc.) to try to keep the element count down. I make a call to the body to remove the parent firework div (which contains <128 element nodes), obviously being logically smarter than looping through that collection and removing each node individually.

I am also precomputing the core animation points "on-the-fly" (ie. as each object is generated and queued in the animation sequence), which seems to work nicely. This happens in batches as each firework is created. (I haven't done this for the fade bit, which affects the offsetLeft of the image within the div - using a fixed array may work better there.)

One other thing, is there any evidence to suggest .style.marginLeft may be any more/less efficient than assigning .style.left? It sounds pretty odd to me, but I figured I'd throw it out there.. you never know what others may have found in their JS experimentation adventures.

Also, save links to nodes when possible

I am doing this also. I created two globally-scoped references to the base DOM nodes which are the structures cloned for the firework and element objects, so a reference is just passed each time (saving calls to getElementById(), .innerHTML and createElement() - using cloneNode() instead. Haven't done any timing comparisons, but you'd expect this to be faster.)

From poi:

canvas animation works better ( and is more flexible ) when you nest an IMG in a DIV rather than using a DIV and its background property

Ah-ha, this is what I thought. For whatever reason IE seems to flicker the "wait" cursor whenever a background on a DIV is shifted around, and that's highly annoying. I would imagine that for people whose caching is screwed up, this would result in the image being requested/reloaded again as well etc. Using the img + cropped div trick seems better still despite having two elements for each item now.

In the photo thing, I noticed you set the clip property of the DIVs in the CSS. Is it for compatibility reasons ? Because there's no need for it since you already set the width and height and the overflow is hidden.

I was fiddling around with clip vs. overflow:hidden, trying to see if there was any noticeable difference in performance etc. Didn't seem to notice any between IE, Safari and Firefox. Then I must have forgotten to take it out of the code.

Thanks for the replies; of course, any interesting findings from others will be appreciated.

(Edited by Scott on 05-12-2005 08:49)

poi
Paranoid (IV) Inmate

From: France
Insane since: Jun 2002

posted posted 05-12-2005 10:43

Regarding the canvas animation. Sure it's less elegant ( semantically wise ) to have a DIV and an IMG, but that way you avoid the dumb-cache problem and you can also zoom the IMG ( or should I say the DIV ) which is impossible using the background property, and annoying using the clip property.

As for the impact of the static elements it certainly depends on the browsers.
For instance in 3D TOMB II ( which I should move my a** to release at last ), there is more than ~2,600 DIVs and 60+ IMG. All the IMGs are canvas animated. The size of 52 IMG varies between 256x64 and 256x256 and are clipped to 8x256, the others vary between ~576x64 and 2,304x256 and are clipped to ~64x64 to ~256x256. Only the backgroundColor of DIVs needing to be updated is altered, that is between 600 and 1,100 DIV. On my XP1800+ the whole thing goes at ~15fps in IE6 and crawls in FF and MZ.

When updating a style property it's often faster to store the current value in a variable and update the style property only if the current value differs from the one you just computed.

Scott: For your fireworks I think you should create a load of DIV+IMG tags once for all and simply hide whenever you don't need them instead of deleting them ( or their parent node ) and re-creating them later. Btw you could well mixed all you images in a single image having all the colors and opacities you need. Once you instaciante some sparkles you just have to set the top property of the IMGs to select the color.

Scott
Paranoid (IV) Inmate

From: schillmania.com
Insane since: Jul 2002

posted posted 05-12-2005 18:51

Poi:

I agree on the cache and image sizing benefits to the div/img combo, my question was more along performance (since logically, more elements should mean slower?)

Thanks for the single-image tip, for some reason that didn't occour to me despite having done half the work already, having put the opacity states into one image for each colour.

It makes sense to create a number of objects early and then recycle them, but I was trying to make something flexible that'd only create the elements actually needed for the animation. (The fireworks vary from say 16 to 64 elements each.)

Granted I could just create a big number of elements and globally reference them, but again I wanted to only create and use on an "as-needed" basis. I may try a fixed experiment with pre-generated elements and see if it's any faster.

poi
Paranoid (IV) Inmate

From: France
Insane since: Jun 2002

posted posted 05-12-2005 19:08

From what I've seen/done the number of elements has a tiny impact on speed compared to the number of elements updated.

Flexibility vs. Speed = what Iron Wallaby said about OOP vs. Procedural code.

Why couldn't you create and reference a big number of elements ?



(Edited by poi on 05-12-2005 19:11)

« BackwardsOnwards »

Show Forum Drop Down Menu