Today i was refactoring some js code that rendered a graph to svg. It was taking several seconds in some cases, and the developer had done a bunch of micro-optimizations, inlining functions, building caches to avoid nested loops, and so on.
I ran a profile. The code ran for 2.5 seconds, 4 ms of which in the micro-optimized js code, the rest updating the dom, five times all over again. Needless to say that i threw out all the micro-optimizations, halving the number of lines, and fixed it so the dom was updated once.
Anyway, the point i'm making is this: you should micro-optimize for readability and robustness, not performance, unless profiling shows it's worth it. I haven't known a case where pure (non-dom, non-xhr) js code needed micro-optimization for performance in half a decade.
Having written a major HTML5 game engine, I've ended up micro-optimizing JS code after small functions really did show up high in profiling measurements. One example: calculating a bounding box from a quad involved code along the lines of Math.min(a, b, c, d) followed by Math.max(a, b, c, d). Replacing that with a tree of ifs to determine both the minimum and maximum at once was faster and moved the bottleneck elsewhere.
I have done some optimizations using the Safari Debugger alongside with Chrome's, because I needed to access an iPad.
Safari counts and profiles ALL function invocation, so if you go looking for hotspots with it's profiler, you always get the parts where many functions are called. I consider this harmful.
I stumbled over this. Maybe other developers did too.
Depends on what you're doing. On mobile, those can end up providing much faster user interactions than doing everything via canvas (which it seems is your proposed alternative).
For example, with IE on Win8, your DOM UI is actually composed of DirectComposition layers, and touch manipulations (pan, zoom, swipe, etc) are performed entirely on a separate thread from your UI+JS using DirectManipulation and a kernel feature called delegate input threads, controlling animations of the composition layers on yet another (composition) thread. You'll have a heck of a time matching that with canvas and mouse/touch/pointer events on your lone JS UI thread and the dozens of responsibilities it's signed up for.
Again, it depends a great deal on what you're doing. And it's a trade-off for sure... DOM is expensive, and if you're doing something too complicated then having panning and hit-testing on another thread doesn't help if the user ends up seeing large unpainted regions for a while, or if you make your startup time painful by trying to build a complex scene upfront. But you asked, so I answered :-)
There are also other important considerations:
1) It's easier (at least until we get some awesome UI frameworks on top of canvas, if that works out well).
2) It's compatible with older browser versions.
3) DOM layouts and controls support various accessibility features, input modalities, etc.
4) There's a huge library of tools/utilities/reusable components all designed specifically for it.
(I used IE/Win8 as an example because I'm familiar with how that works in great detail. Last I knew no other platforms were that aggressively optimized in those respects but presumably some are part way there)
I can't speak for others, but if you write browser apps/websites for a generic audience you basically have no choice. The reason consist of two letters: IE
I ran a profile. The code ran for 2.5 seconds, 4 ms of which in the micro-optimized js code, the rest updating the dom, five times all over again. Needless to say that i threw out all the micro-optimizations, halving the number of lines, and fixed it so the dom was updated once.
Anyway, the point i'm making is this: you should micro-optimize for readability and robustness, not performance, unless profiling shows it's worth it. I haven't known a case where pure (non-dom, non-xhr) js code needed micro-optimization for performance in half a decade.