What is a good resource for understanding the DOM/query selectors and their performance (JS and CSS selectors)? All that I know about it is just through word of mouth and it would be great to look at a resource that covers these things.
Also, is document.createElement('div') really much faster than $("<div></div>")? Just checked and a lot of well-respected JS libs use (including Backbone) use the jQuery version.
The normalisation is purely to support older browsers though. Backbone doesn't really use that much of jQuery, have a search for 'Backbone.$' through the annotated source [1]. There are only 10 uses of it in the whole file, and not for anything too crazy. In modern browsers you could probably do away with jQuery and still avoid "if safari then...".
There are good talks by the Chrome dev team from various GoogleIO's. CSS selectors used to have a lot of voodoo about them but no longer matter that much in terms of performance.
Try the blog of one Paul Irish and spread out from there.
> but no longer matter that much in terms of performance
That's not quite true. They matter enough that WebKit is implementing them incorrectly because they can't figure out how to make a correct implementation performant enough...
I went to a meet up a few weeks ago on Sencha Touch and how they did the Fastbook (http://www.sencha.com/blog/the-making-of-fastbook-an-html5-l...) project to prove that HTML5 is, indeed, ready to provide host an application as complex as Facebook a few weeks ago and it opened my eyes in a few ways.
This article is correct, and provides an example, in saying that the DOM can easily create thousands of elements in milliseconds. However, the problem is that events and interactions with it all happen on a single process. Things load and block the thread, an event happens and blocks the thread, etc.
The Sencha guys did something really smart. They used an object pool with one object: requestAnimationFrame, as the core of their mobile platform and sent EVERYTHING to it. That way events, loading, or whatever, didn't block, but happened in a FIFO manor. They also kept the number of dom elements static and just reused them when needed, so an object pool of dom nodes -- no creating or destroying nodes.
The things that make working with the dom slow isn't only creating nodes, but applying styles, listeners, and destroying them -- basically creating an application.
I do agree with the overall premise that a lot of developers do not know the best methods/practices/patterns to utilize when creating complex applications. I learn new things daily and I hope that our community continues to teach itself and provide tools to make getting things done easier.
Honestly, that doesn't sound like a best practice and more like a convoluted performance hack. It's one thing to use a pre-allocated memory pool for speeding up the creation of objects in native language like C++. Having to the equivalent while working several software layers above that is an example of extremely leaky abstraction.
DOM and Javascript engines still need few more man-centuries of iteration to bring their performance closer to e.g. JVM which doesn't really require hacks like that anymore.
> e.g. JVM which doesn't really require hacks like that anymore.
Is this the case?
I used to be pretty in-touch with Java, but haven't been keeping up from the release of 7 onwards. I've picked it up again for game development, and 100% of the performance advice I've found is to use object pooling... but nearly all of that advice is years old, and I have no idea if it still holds true for JRE7 or even JRE6.
It did strike me as something the JVM should be doing for me, so if that has been fixed, that news will be greatly welcomed by the Java game dev community.
For Java 6 and 7 I would say don't do object pooling, this is probably true for 4 and 5 as well. Creating a new object in Java is very inexpensive and it keeps getting improved. The only argument you might be able to make against creating lots of objects is garbage collection, and for that I'd say profile when you have problems and change only then.
Especially the newer generational GCs are very good at letting you create and destroy lots of short-lived objects. Object pools may only be useful for long-lived objects, maybe.
"Public service announcement: Object pooling is now a serious performance loss for all but the most heavyweight of objects, and even then it is tricky to get right without introducing concurrency bottlenecks."
This article was also written when Java 6 was starting to get escape analysis, which can result in stack allocations in some cases.
I recall taking a course in 2008 or so (Java 6). We were doing a genetic simulation of sorts, and the professor recommended using an object pool to speed things up. I implemented one and observed no measurable difference in my code's performance (these were very small objects used over and over again evolving new organisms). I hooked up a profiler and used that to guide me to some areas that could be improved, and a valuable lesson was learned.
Does everything that happens in the JVM happen on a single tread? I think that is the biggest bottleneck when you see slow performing web apps. I think that moving things off to web workers is the natural progression, but browser support...
Not everything, just UI work for AWT/Swing. Pretty much every UI framework that I've worked with over my 20 years of experience is single-threaded, uses an event-based queueing architecture. I'm sure others have a different experience though ;)
well i would argue not everybody has a top of the line handset , and trust me html5 vs native makes a huge difference on cheap devices.
You dont have to use all these tricks when you use IOS or Android widgets.
And usually developping with Xcode or Eclipse IDEs makes the work far more easier than using any JS ide.
Instead of using Javascript for the UI i usually use it to implement bits of business logic , algorithms i can easily port from plateform to plateform , so i get native UI and portable JS libraries.
> You dont have to use all these tricks when you use IOS or Android widgets.
I havent gotten too deep in native development on either platform, but don't they prioritize tasks automatically? JS doesn't, using requestAnimationFrame and web workers is doing exactly that. Wasn't the main knock against Android's UI lag because everything happens once allowing blocking and it was addressed with project Butter?
Have you successfully developed any iOS apps using the approach you describe (native UI, JS back-end)? If so, how did you embed a JS engine in your app and bridge between that and ObjC?
Prediction: Since jQuery2 is dropping support for IE < 9, it will never be as popular as its predecessor. We all owe John Resig a debt of gratitude for getting querySelectorAll into modern browsers.
The next missing piece is the ShadowDOM/Templates stuff coming down the pipeline, but sadly that will probably take just as long for mass adoption.
It would be more accurate to say something along the lines of: "it's often possible to get the DOM to perform a lot faster than it currently is for you", or even: "speed probably isn't the biggest problem you'll face with the DOM; inconsistency and weird browser quirks are".
That said, the following things irked me:
> Abstraction is more likely to increase speed, because someone smarter than you has written the bit that needs to be fast.
That's a very sweeping statement that doesn't really describe the situation. It obviously depends on what you're doing, who wrote the abstraction and how much is being abstracted.
> First: ignore pretty much anything Facebook has to say about DOM performance. They really have no idea what they are talking about. Sencha was able to make a version of the Facebook mobile app with their framework, and it was FASTER than the official, native app, and Sencha isn’t even particularly fast.
If you create an app that has half the feature set of another app it will likely be easier to make it go fast.
> Second: Stop using DOM libraries out of habit! If your target browser is IE8 or above, jQuery hardly provides any features that aren’t shipped on the host object anyway. document.querySelectorAll will pretty much do everything you need. jQuery is a tool, not a framework. Use it as such.
jQuery provides a clean sensible API. Something that is currently still lacking from the DOM (despite all the improvements). document.querySelectorAll will definitely not do "pretty much everything" you need out of the box.
I assumed he was talking about document.querySelectorAll in the context of selecting elements, not for additional functionality such as jQuery's fadeIn()
It's the extra functionality that makes it useful though.
document.querySelectorAll doesn't even support event listeners or forEach loops. I wouldn't call that extra functionality, I'd call that a basic requirement.
It lets you select elements using CSS selectors. That's good and all but if you want to actually do anything with that you're better off using some sort of library that abstracts the awkwardness away (i.e. jQuery).
But apparently a nodelist isn't array enough to get the map function. sigh....
you could use Array.prototype.map.call(). But this really underlines the value of jQuery: in jQuery you can predict what will happen, in the DOM you can't.
Yes, except as that article shows the traditional for loop somehow ends up more palatable than the awkward `forEach.call()` voodoo you have to do to use it on a NodeList, which is a pretty sad state of affairs :/
(Note: I am aware you can alleviate this with toArray type utils [1] but that does seem to be slightly besides the point).
> Abstraction is more likely to increase speed, because someone smarter than you has written the bit that needs to be fast.
Am I the only one that hates this meme? The idea that "someone smarter than me therefore blah blah" seems ultimately to be counter-productive. Placing arbitrary limits on yourself does nothing except prevents you from attempting certain types of "hard" problems because "someone smarter than me will/couldn't figure it out so I shouldn't bother". Perhaps its just hubris on my part but I am completely confident in my ability to fully comprehend any problem or solution that someone has come up with. There are certainly people much smarter than myself, but I will never let that limit me. Whether or not there is actually a limit to what I am capable of understanding is irrelevant, I will never assume before-hand that something is beyond my comprehension or capability.
"Someone smarter than you" perhaps is a bit too bold of a statement, but generally, it is true that using available code should usually be preferred over writing one's own code. It allows you to focus on your main task and spend less time implementing helper functions that someone with more time (I guess that's a better expression than "someone smarter") has already optimized.
Don't get me wrong, I totally agree that using pre-existing code in most situations is far preferable than re-inventing things, especially when it comes to incredibly uninteresting "plumbing" code like DOM manipulation. But instead of referencing intelligence, the justification should be something like "someone already spent the time and effort optimizing something I have no interest in doing myself". Just like it has been shown that praising kids for their intelligence leads to worse outcomes, we should not be artificially limiting ourselves based on intelligence.
I'd generally interpret "smarter than me" in this context as "has put more brain-cycles into this problem than I will", so with regards the that specific problem, they are "smarter".
I like what you're saying, but in some cases (ie. the good cases) "someone smarter than me" is a euphemism for more meticulous.
Save me from unrolling loops and implementing hash maps. I can do these things, I just do not want to.
Of course, I've seen programmers use the term "someone smarter than me" quiet literally. I'd agree with them, because what usually happens is a horrible anti-pattern.
The idea of wilful self-blinding and going, "I'm dumb and so are you! Only those 1337 guys know how to do it" pretty much fills me with rage when I hear it.
I'm not that stupid, and I'm not that smart - I can figure out pretty much anything out there given time and effort.
"Someone smarter than you" is perhaps a bad term. Better would be "Someone who had more time and resources dedicated to this than you do". API developers tweak for performance all the time, specifically for the sake of performance. You often can't do this in your code that uses the APIs: you've got other things to worry about. In that case, it's better to leverage the work of a dev who didn't have other things to worry about.
There's also a few other things wrong with it in this context.
Firstly, the assumption is that the "smarter" person has been focused on performance, rather than for example stability or flexibility. And more specifically, on performance for my particular use case.
Secondly, when I'm writing a native app, regardless of platform, I'm also using a set of OS libraries that have been written those "smarter" people.
And thirdly, if I'm looking to do something where speed is likely to be an issue (e.g. game development) I've got OS- (and use case-) tuned libraries, such as Cocos, that will have also been written by smarter people.
> People often throw around the statement “The DOM is slow”. This is a completely false statement. Utterly stupid. Look: http://jsfiddle.net/YNxEK/. Ten THOUSAND divs in about 200 milliseconds.
How is that even an argument? Just because you can insert a fragment containing 10k <div>s in 200 milliseconds doesn’t mean that the DOM is not slow compared to other operations in JavaScript.
DOM operations are still the slowest operations you can perform using JavaScript in a web browser.
The reason people say “the DOM is slow” is because it’s slower than anything else in JavaScript, not because of an absolute measurement.
If you’re calling JavaScript features slow or fast based on absolute measurements, you’re doing it wrong. Read up on JavaScript benchmarking. Create and run some jsPerf tests on various devices and browsers, and compare the results. You’ll quickly find that absolute numbers are meaningless in this case.
FYI, browser profilers can't evaluate the efficiency of your jQuery selectors, which can be a bottleneck aswell depending on what you do. I personally use this: https://github.com/osteele/jquery-profile
I have had similar experience. Skipping jquery and calling native DOM methods directly can be surprisingly fast.
Still I am curious in what the benchmarks actually say. The native DOM methods appear to return before rendering is done (at least in webkit). So when we get a 200ms benchmark for 10,000 divs I suspect there it is taking a longer than that to fully render.
Yeah, they do return before rendering is done. For example, this fiddle[1] inserts 100k svg circles; it takes 1000 milliseconds on my machine, but scrolling around takes several seconds.
I was caught off-guard by the results - it appears that (even after multiple runs) the raw JS implementation is ~100 times (times, not %) faster. Definitely surprised at the drastic difference, although someone please correct me if I missed something in these simple test cases.
I got different results on Windows XP (don't ask). Using both Firefox 19 and Chrome 25, Direct append came in the fastest with modestly slower performance (around 5-10%) from the other methods.
Version 10 of your test is really surprising. The raw JS append function just came out 250 times faster than the jquery direct append example, and 750 times faster than jquery append variable. This is on chrome for iOS.
Wow, yeah. Document fragments seem to be even faster than my original createElement. I'm really going to have to re-evaluate how I'm creating new DOM elements.
This is the kind of thing I was hoping to inspire. Sure, use jQuery, but use it wisely. That said, literally never make DOM in it, for so many reasons...
Why would you append on every loop. Rather than build the string and then append the whole lot on one block?
If you compare the DOM of the original fiddle and the DOM of following the fiddle I posted. You will see they are the same.
I'm not saying what I referenced is the 'best' way of doing things. But that the debate in the original article (based on the provided examples) is pretty null.
You're right, my example was different. But upon fixing it to match the original article's example, but with jQuery creating the dom nodes, it is still slower
Interesting. On a whim, I tried changing your fiddle to use Array.join construction rather than string appends, but string appends remain 5-10% faster:
> Second: Stop using DOM libraries out of habit! If your target browser is IE8 or above, jQuery hardly provides any features that aren’t shipped on the host object anyway.
Nope, sorry, 9 times out of 10 the provision is theoretical and the interface is garbage. querySelector is pretty much the only one which does not suck — hence it being used as an example every single time.
* Querying or altering elements? Verbose shit.
* Binding events? Verbose shit.
* Delegating events? You've got 2 different specs, the most recent one is unimplemented and the older one is prefix-implemented everywhere (and useless as far as I know).
* Inserting elements in a DOM tree? Oh boy you're going to have a fun time manually traversing crap until you can reliably use insertBefore.
* Creating a node with text in it? You're in for 3 different statements, and that's if you're not trying to add attributes as well
* Manipulating classes? Hello broken regex search&replace. Oh you're targeting IE9 anyway? Well fuck you still, because Element#classList is IE10+.
* Playing with data-* elements? I hope you like getAttribute, because Element#dataset is MIA in MSIE.
* And bulk operations? What, you think querySelectorAll or getElementsByClass is going to return an array? Dream on, you may get something array-like in DOM4 if you're lucky. That means IE15, maybe.
Every single time I tried to get by with raw DOM, I fell back on zepto or jquery, life's too short for shit APIs and the DOM is exactly that. I don't code in raw DOM for the same reason I've stopped coding in assembly: I value my life more.
Now there are issues with jQuery, but these issues are generally that jQuery makes it easy to do the wrong thing (it's important to note that it also makes it easy to do the right thing, and improves that all the time, the "ease of doing the wrong thing" is just a side-effect of making things easier in general, the library does not specifically drive the user to the wrong thing) (except for animation maybe) e.g. keep doing noop work on empty selections, repeatedly select the same elements over and over again instead of caching the selection or not realizing you're doing a batch operation of adding a class or event on hundreds of DOM nodes in a single line.
The DOM itself does not fix this, it just makes these things so incredibly and obviously painful you look for other ways to do it to try and slightly alleviate the pain.
You get the same result out of thinking, and not blindly using jQuery.each and the like.
Maybe I'm neurotic but if I know I can speed up my application 100x by typing .addEventListener('click', fn) instead of .click(fn) I'm going to do that every time and not lose any sleep over it.
> Maybe I'm neurotic but if I know I can speed up my application 100x by typing .addEventListener('click', fn) instead of .click(fn)
You can't though, not even close. You can speed up your application significantly by using event delegation on a parent instead of binding an event to each element, but the raw DOM makes this a giant pain in the ass in the general case.
In case anyone reading doesn't realise* - that's not the kind of thing you'd be doing to get a speed up. I can't think of how addEventListener could lead to a 1.001x speedup of an app, let alone a 100x. You don't ever need to create listeners in loops, so a single operation like that just isn't a optimisation target. If you need to listen for an event that could come from lots of nodes, listen for the event bubbling up to the parent of those nodes.
* I'm sure Matthew realises but just gave the first example that came to him.
I didn't mean event listeners specifically, I meant trading all of the normal DOM APIs for less verbose and more consistent jQuery alternatives is a trade of performance. On a fast desktop computer that tradeoff is an easy one to make, but in mobile it still arguably isn't.
No way - even if it was the sole performance bottleneck in your application (which as I've commented above is absurd, and a sign you're doing it so very, very wrong). Even if your application was:
var i = 100;
while(i--) els[i].addEventListener("click",fn);
it'd be untrue jQuery is nowhere _near_ 100x slower. Profiling this is totally ridiculous because there's no use case that requires adding event listeners at a scale that could _ever_ be a performance concern, but anyway - http://jsperf.com/jquery-on-vs-native/3. So just 10x slower on even this - completely not performance critical and therefore nobody would bother optimising it - method.
I totally agree that jQuery is a significant improvement over the native DOM as an API, and that thinking about/profiling what your jQuery code is doing is a better approach than deciding to try to avoid jQuery whenever possible.
However, throwing away jQuery for whatever reason (as we have on the iOS-only project I've been on for the last 3 months) doesn't necessarily mean you're stuck in verbosity hell. We just tried to look for the points where it seemed most verbose/painful and wrote thin jQuery-ish wrappers around native stuff... so, for example, there's a short alias for querySelector All which gloms `Array.prototype.forEach` onto the return value, and class manipulation functions, and a handful of other things. Last time I checked, the library fits on one screen and none of the functions are longer than 4 lines.
Not necessarily the right approach for every project, but neither has it been a descent into hell.
Interestingly, I've never found event binding to be a particular pain point; the thing I'm really getting tired of is writing `e.preventDefault()`, but jQuery isn't going to save me from that anyway.
That's what Zepto was made for... the core of jQuery for modern browsers, without a bunch of the compatibility aspects of jQuery. (it's not 100% complete, but the core is compatible with jQuery) ex: jQuery 2.0 for newer desktop browsers, jQuery 1.9 for desktop and legacy, and Zepto for supported browsers... Do your testing in a webkit browser with Zepto, and it should be outward compatible with jQuery.
"Sencha was able to make a version of the Facebook mobile app with their framework, and it was FASTER than the official, native app, and Sencha isn’t even particularly fast."
No, the DOM is slow. I've worked on mobile projects that didn't use a single 3rd party library, no jQuery no underscore, the most I've used is polyfills for stuff like Function.prototype.bind etc.
It doesn't matter. When you have a non-trivial thing to render in a list, not just a div with text content, and you start to scroll the browser stutters. Even if the list isn't particularly long (< 50 items).
CSS animations are also rather slow in mobile browsers although this is getting better with every release.
I actually find it a little bothersome that so much browser development these days is focused on JavaScript performance and JavaScript alternatives whether it is Dart or asm.js or whatever... when the DOM is the primary reason lag exists.
Yeah, the problem is if anything changes or even if you ask for the width of an element, it has to for some reason reflow everything or at least a big portion of it. So you have to keep interactions with element positions and dimensions to a minimum.
The reason native is better for mobile apps is not that the browser's rendering engine isn't fast. It's that the browser is yet another turtle on top of an already bloated stack.
He argues that the developers working on these browsers are optimizing them, and that we are not intelligent enough to trump their obviously superior coding skills. Well, I'm going to disagree outright on that point. Many of us are very talented.
Add Webkit on top of the Dalvik VM and android SDK, and fragmented device ecosystem, and we're talking major disparities between the way your HTML5 app is going to run on different android devices. I have seen HTML5 apps that work great on phone a and b, but not on c, because well, c has a different webkit version!
It's bad enough to have to write code for different browsers. It's really bad to have to write code for different browsers that will run on hundreds of different android devices.
Back to the point you made about optimization: don't you think the developers of the native SDKs are making optimizations, too? And the lower level means we're way closer to the metal, lower on the stack, and ergo: less complex.
I'd use HTML5 for a trivial app, like, a business's mobile website. But for anything serious, GO NATIVE!
Note, my answer is for mobile browsers, specifically android. Even iOS should be marginally better on this, but really I've only seen HTML5 kicking ass on desktop browsers. I've yet to be impressed by it in mobile.
"Used in moderation, jQuery is an exceptionally useful tool for assisting in DOM manipulation and compatibility, and simplifying APIs such as for XHR requests"
The point the author is trying to make is perhaps a reasonable one, but what an inappropriate communication style. I don't know if the author realizes the tone is so off-putting, but I've found that supportive feedback and constructive criticism goes a lot further in professional environments than name calling and insults. Put another way, if someone on my team at work communicated like that I'd have a conversation with them about more effective approaches less likely to alienate or offend colleagues.
There appears to be an uptick of hyper-agressive technical posts over the past several years. I'm not sure where it started, but I'm hoping it burns itself out soon.
(If you're the author, I apologize for calling you out on this. Nothing personal at all, I just wanted to make the general point about tone.)
I didn't find his tone offensive at all, esp as a piece of writing. It's likely that he hears "DOM is slow" all the time, and is venting. And he's a far cry from Zed Shaw's kind of writing.
Consider that the OP itself is already disagreeing with something (the assertion "DOM is slow"). If we apply the rules of your link to the OP, it doesn't even get pass DH1 (the title is already a name call, and later on it uses others).
“I’m too stupid to know that what I’m doing is stupid”
I agree that the OP's smartass writing style is more annoying than anything else, but I really didn't like the quoted phrase above. Calling someone stupid because they don't know the ins and outs of what is, let's face it, a particularly byzantine system, is just, well...mean.
He's saying it's more difficult to convince people of your point if you're being a dick about it. You aren't arguing the central point of his thesis, so I'm unsure what exactly your point is in regards to OP.
As far as I know, PG's post doesn't apply to the original article, as the article starts the discussion, rather than responds to one.
This discussion has being going on for a very long time, even on HN. The article is very much a response to what has come before it. Sure it's a starting point for a thread of discussion we're having here, but it's by no means the _start_ of the debate.
I think that he probably doesn't care if he hurts the fragile feelings of the types of people who think of JavaScript as a "low level" language and probably doesn't want to work at a place that would hire such people.
>If all you are doing is making HTML elements, DO NOT USE JQUERY.
That's pure premature optimization. I don't understand how people can still be making blanket statements about performance costs like this. Using jQuery to create HTML elements is fine. It's convenient and succinct, and it keeps your code consistent. Otherwise, you'll have two ways of creating HTML elements: one for when you are just creating an element, and another for when you need to use jQuery on it afterward.
But if you do hit a point where creating HTML elements with jQuery is slow, you optimize that point and leave a comment explaining why you're doing it that way.
People get these ideas in their heads that somehow they're going to be able to code everything super fast from the very start, and it's nonsense. All you're going to do is make it harder to maintain your project.
The types of optimizations you are suggesting are extremely hard to track down. If you have a laggy list you only know that you have a laggy list.. changing a single $('<div></div>') to document.createElement('div') probably isn't the thing that will speed up your application. It's probably not a single function or even a set of functions that is causing the problem. It's probably that in order to gain the 'sticky' affect you want that jquery plugin you're using is listening to a window.onscroll or something, and unless you want to dig into the code of every library you're using you probably won't know why.
When you're working in the mobile web and performance is important you want to know what every line of code is doing. Your application is probably going to be a little laggy anyways, but at least you'll know why that is and know where to target to try and fix it.
>The types of optimizations you are suggesting are extremely hard to track down
Except that it's not, because you can use profiling in modern browsers to figure out where the time is being spent.
>It's probably that in order to gain the 'sticky' affect you want that jquery plugin you're using is listening to a window.onscroll or something, and unless you want to dig into the code of every library you're using you probably won't know why.
But that's not what the author is arguing, and it has nothing to do with adding elements to the DOM via jQuery vs via lower level methods.
There are some points that I'd agree with in this post, but the framing is all wrong. The author begins the article saying that abstractions are fast (the DOM) and ends the article saying that abstractions are slow (jQuery).
The native vs web argument has been beaten to death. It comes down to this: there is no perfect solution and everything has trade-offs (speed, quality, and cost). Use your brain and pick the solution that works best for the problem you are trying to solve. As much as web apps have replaced many things that may have previously been implemented as native apps on the desktop, there is still native development being done.
I stopped reading when he said that he thought 10000 divs in 200 milliseconds was impressive.
That was impressive on a 486 SX. The things that make people go "woa!" in a browser are, barring WebGL demos entirely made in shaders, completely not-impressive when compared to doing the same outside a browser. This is fine. The browser is expected to handle so many wildly varying use cases at once, it can't be top speed at all of them. But don't go around telling us that something that Firefox does on a 2Ghz quad core PC is amazing when the same has been done on an Amiga 500.
The DOM is slow. It can be used to be fast enough for most purposes.
Agreed. The DOM is incredibly slow, and his example is so asinine.
What is the use case for generating 2000 unstyled divs with one line of text? Try making that into a nice slick CSS list, maybe throw an image in each list item, with some title copy and supporting text. Perhaps you throw a bit of text shadow on it to create a nice beveled effect. Oh yeah, that 2000 divs per 200 milliseconds probably just turned into 10. Maybe even less, maybe 1 or 2 on a mobile browser.
This is really taking things out of context. The DOM might be slow compared to your Amiga, but the statement TFA is talking about is within the context of web browsers.
That bothered me too, but if you had read further I think you would have found the introduction misleading. The rest of the rant isn't really about DOM vs native, it's about good DOM code vs bad DOM code.
Yes, from the viewpoint of a game developer, the DOM is extremely, painfully, awfully, ridiculously slow and completely useless other than static HUDs. With the DOM, we can move only hundreds of sprites at 60 fps (on the latest Core i7!). HTML5 Canvas can achieve thousands but it's also far from native (and the function of Canvas is very poor).
WebGL can gain acceptable performance in many situations, but there is still much overhead.
I suspect today's most web developers don't know the true performance of computers they are actually using.
Maybe the DOM isn't, but browsers still are for more complex & animated UIs. And worse of all it rally depends on the browser. I was surprised that safari is still a lot better than chrome with smooth css animations, Chrome just chokes when there are larger images: http://stackoverflow.com/questions/15323228/css-transition-i...
I was a little surprised to hear "use document.createElement, it's faster than innerHTML" since the conventional wisdom was exactly the opposite a few years ago.
Based on the Browserscope results (and my own testing), it seems that document.createElement is faster in Webkit but slower in everything else (Gecko, Trident). So, a bit of a wash there unless you're targeting mobile.
That said, in my experience HTML (template) parsing isn't the main bottleneck to getting an app to that smooth 60fps feeling. Usually the big targets you want to focus on there are avoiding cascading reflows/repaints, using smoother animation technologies such as requestAnimationFrame or CSS transitions/animations, understanding how to trigger hardware acceleration and what its limits are, and keeping careful control of your CSS special effects (border radius, box-shadow, gradients, etc). I recommend checking out http://jankfree.com/ (especially the I/O talk) if you're interested.
(edit: I don't really like the original article's vitriol, but he's right about a couple things. Manipulating your nodes outside of the DOM is much faster, although you don't need to be inside a DocumentFragment to do this (don't get me wrong; DocFrags are pretty useful). Also, yes, please don't keep running those jQuery selectors over and over again. Store the jQ object that the selector returns to you and just reuse that)
125 comments
[ 3.0 ms ] story [ 202 ms ] threadEDIT: typo
[1] http://backbonejs.org/docs/backbone.html
Try the blog of one Paul Irish and spread out from there.
That's not quite true. They matter enough that WebKit is implementing them incorrectly because they can't figure out how to make a correct implementation performant enough...
Also, here are some articles I found in my links list:
CSS Stress Tester Bookmarklet (Copy into a bookmarklet. Then it will tell you the rules that are causing the most lag.)
javascript:(function(d){var s=d.createElement('script');s.src='http://andy.edinborough.org/Demos/css-stress/stressTest.js?_... es=d.getElementsByTagName('script')[0];es.parentNode.insertBefore(s,es);var doit=function(){if(window.stressTest){stressTest.bookmarklet();}else{setTimeout(doit,100);}};doit();})(document);
Old but still relevant I think: http://www.stevesouders.com/blog/2009/06/18/simplifying-css-... Text makes CSS slow (don't render too much): https://news.ycombinator.com/item?id=2232212 In general, following good guidelines might help: https://github.com/csswizardry/CSS-Guidelines
This article is correct, and provides an example, in saying that the DOM can easily create thousands of elements in milliseconds. However, the problem is that events and interactions with it all happen on a single process. Things load and block the thread, an event happens and blocks the thread, etc.
The Sencha guys did something really smart. They used an object pool with one object: requestAnimationFrame, as the core of their mobile platform and sent EVERYTHING to it. That way events, loading, or whatever, didn't block, but happened in a FIFO manor. They also kept the number of dom elements static and just reused them when needed, so an object pool of dom nodes -- no creating or destroying nodes.
The things that make working with the dom slow isn't only creating nodes, but applying styles, listeners, and destroying them -- basically creating an application.
I do agree with the overall premise that a lot of developers do not know the best methods/practices/patterns to utilize when creating complex applications. I learn new things daily and I hope that our community continues to teach itself and provide tools to make getting things done easier.
DOM and Javascript engines still need few more man-centuries of iteration to bring their performance closer to e.g. JVM which doesn't really require hacks like that anymore.
Is this the case?
I used to be pretty in-touch with Java, but haven't been keeping up from the release of 7 onwards. I've picked it up again for game development, and 100% of the performance advice I've found is to use object pooling... but nearly all of that advice is years old, and I have no idea if it still holds true for JRE7 or even JRE6.
It did strike me as something the JVM should be doing for me, so if that has been fixed, that news will be greatly welcomed by the Java game dev community.
This article was also written when Java 6 was starting to get escape analysis, which can result in stack allocations in some cases.
I recall taking a course in 2008 or so (Java 6). We were doing a genetic simulation of sorts, and the professor recommended using an object pool to speed things up. I implemented one and observed no measurable difference in my code's performance (these were very small objects used over and over again evolving new organisms). I hooked up a profiler and used that to guide me to some areas that could be improved, and a valuable lesson was learned.
You dont have to use all these tricks when you use IOS or Android widgets.
And usually developping with Xcode or Eclipse IDEs makes the work far more easier than using any JS ide.
Instead of using Javascript for the UI i usually use it to implement bits of business logic , algorithms i can easily port from plateform to plateform , so i get native UI and portable JS libraries.
I havent gotten too deep in native development on either platform, but don't they prioritize tasks automatically? JS doesn't, using requestAnimationFrame and web workers is doing exactly that. Wasn't the main knock against Android's UI lag because everything happens once allowing blocking and it was addressed with project Butter?
The next missing piece is the ShadowDOM/Templates stuff coming down the pipeline, but sadly that will probably take just as long for mass adoption.
That said, the following things irked me:
> Abstraction is more likely to increase speed, because someone smarter than you has written the bit that needs to be fast.
That's a very sweeping statement that doesn't really describe the situation. It obviously depends on what you're doing, who wrote the abstraction and how much is being abstracted.
> First: ignore pretty much anything Facebook has to say about DOM performance. They really have no idea what they are talking about. Sencha was able to make a version of the Facebook mobile app with their framework, and it was FASTER than the official, native app, and Sencha isn’t even particularly fast.
If you create an app that has half the feature set of another app it will likely be easier to make it go fast.
> Second: Stop using DOM libraries out of habit! If your target browser is IE8 or above, jQuery hardly provides any features that aren’t shipped on the host object anyway. document.querySelectorAll will pretty much do everything you need. jQuery is a tool, not a framework. Use it as such.
jQuery provides a clean sensible API. Something that is currently still lacking from the DOM (despite all the improvements). document.querySelectorAll will definitely not do "pretty much everything" you need out of the box.
document.querySelectorAll doesn't even support event listeners or forEach loops. I wouldn't call that extra functionality, I'd call that a basic requirement.
It lets you select elements using CSS selectors. That's good and all but if you want to actually do anything with that you're better off using some sort of library that abstracts the awkwardness away (i.e. jQuery).
you could use Array.prototype.map.call(). But this really underlines the value of jQuery: in jQuery you can predict what will happen, in the DOM you can't.
(Note: I am aware you can alleviate this with toArray type utils [1] but that does seem to be slightly besides the point).
[1] http://jsfiddle.net/AhQPU/
Am I the only one that hates this meme? The idea that "someone smarter than me therefore blah blah" seems ultimately to be counter-productive. Placing arbitrary limits on yourself does nothing except prevents you from attempting certain types of "hard" problems because "someone smarter than me will/couldn't figure it out so I shouldn't bother". Perhaps its just hubris on my part but I am completely confident in my ability to fully comprehend any problem or solution that someone has come up with. There are certainly people much smarter than myself, but I will never let that limit me. Whether or not there is actually a limit to what I am capable of understanding is irrelevant, I will never assume before-hand that something is beyond my comprehension or capability.
Save me from unrolling loops and implementing hash maps. I can do these things, I just do not want to.
Of course, I've seen programmers use the term "someone smarter than me" quiet literally. I'd agree with them, because what usually happens is a horrible anti-pattern.
I'm not that stupid, and I'm not that smart - I can figure out pretty much anything out there given time and effort.
Firstly, the assumption is that the "smarter" person has been focused on performance, rather than for example stability or flexibility. And more specifically, on performance for my particular use case.
Secondly, when I'm writing a native app, regardless of platform, I'm also using a set of OS libraries that have been written those "smarter" people.
And thirdly, if I'm looking to do something where speed is likely to be an issue (e.g. game development) I've got OS- (and use case-) tuned libraries, such as Cocos, that will have also been written by smarter people.
> People often throw around the statement “The DOM is slow”. This is a completely false statement. Utterly stupid. Look: http://jsfiddle.net/YNxEK/. Ten THOUSAND divs in about 200 milliseconds.
How is that even an argument? Just because you can insert a fragment containing 10k <div>s in 200 milliseconds doesn’t mean that the DOM is not slow compared to other operations in JavaScript.
DOM operations are still the slowest operations you can perform using JavaScript in a web browser.
You aren't refuting the author's point. "The DOM is slow" is based on an absolute timing. No one is making a relative comparison.
In general its possible to argue that operation X is fast, even if X is the slowest of a set of operations, if you take an absolute perspective.
If you’re calling JavaScript features slow or fast based on absolute measurements, you’re doing it wrong. Read up on JavaScript benchmarking. Create and run some jsPerf tests on various devices and browsers, and compare the results. You’ll quickly find that absolute numbers are meaningless in this case.
Still I am curious in what the benchmarks actually say. The native DOM methods appear to return before rendering is done (at least in webkit). So when we get a 200ms benchmark for 10,000 divs I suspect there it is taking a longer than that to fully render.
[1] http://jsfiddle.net/vHvZD/
For some concrete numbers, I updated a JSPerf that I found to include a raw JS implemention.
http://jsperf.com/creating-dom-elements/8
I was caught off-guard by the results - it appears that (even after multiple runs) the raw JS implementation is ~100 times (times, not %) faster. Definitely surprised at the drastic difference, although someone please correct me if I missed something in these simple test cases.
This was with Chrome on Windows, by the way.
Writing this utilising jQuery for DOM manipulation ( http://jsfiddle.net/YNxEK/7/ ) is getting me consistently faster results than the original fiddle ( http://jsfiddle.net/YNxEK/ ) on Firefox and Chrome.
http://jsfiddle.net/d5geB/
Here is the equivalent:
http://jsfiddle.net/EmEhRKay/YNxEK/10/
If you compare the DOM of the original fiddle and the DOM of following the fiddle I posted. You will see they are the same.
I'm not saying what I referenced is the 'best' way of doing things. But that the debate in the original article (based on the provided examples) is pretty null.
http://jsfiddle.net/EmEhRKay/YNxEK/13/
http://jsfiddle.net/2kWdC/
That way uses an indexed for-loop, but the while loop with Array.push was just as bad.
But checking at: https://blogs.oracle.com/greimer/resource/loop-test.html
Still seemed to demonstrate a decreasing while loop as the fastest in my test.
Nope, sorry, 9 times out of 10 the provision is theoretical and the interface is garbage. querySelector is pretty much the only one which does not suck — hence it being used as an example every single time.
* Querying or altering elements? Verbose shit.
* Binding events? Verbose shit.
* Delegating events? You've got 2 different specs, the most recent one is unimplemented and the older one is prefix-implemented everywhere (and useless as far as I know).
* Inserting elements in a DOM tree? Oh boy you're going to have a fun time manually traversing crap until you can reliably use insertBefore.
* Creating a node with text in it? You're in for 3 different statements, and that's if you're not trying to add attributes as well
* Manipulating classes? Hello broken regex search&replace. Oh you're targeting IE9 anyway? Well fuck you still, because Element#classList is IE10+.
* Playing with data-* elements? I hope you like getAttribute, because Element#dataset is MIA in MSIE.
* And bulk operations? What, you think querySelectorAll or getElementsByClass is going to return an array? Dream on, you may get something array-like in DOM4 if you're lucky. That means IE15, maybe.
Every single time I tried to get by with raw DOM, I fell back on zepto or jquery, life's too short for shit APIs and the DOM is exactly that. I don't code in raw DOM for the same reason I've stopped coding in assembly: I value my life more.
Now there are issues with jQuery, but these issues are generally that jQuery makes it easy to do the wrong thing (it's important to note that it also makes it easy to do the right thing, and improves that all the time, the "ease of doing the wrong thing" is just a side-effect of making things easier in general, the library does not specifically drive the user to the wrong thing) (except for animation maybe) e.g. keep doing noop work on empty selections, repeatedly select the same elements over and over again instead of caching the selection or not realizing you're doing a batch operation of adding a class or event on hundreds of DOM nodes in a single line.
The DOM itself does not fix this, it just makes these things so incredibly and obviously painful you look for other ways to do it to try and slightly alleviate the pain.
You get the same result out of thinking, and not blindly using jQuery.each and the like.
edits: formatting, classes manipulations, data-* attributes, matches/matchesSelector.
You can't though, not even close. You can speed up your application significantly by using event delegation on a parent instead of binding an event to each element, but the raw DOM makes this a giant pain in the ass in the general case.
* I'm sure Matthew realises but just gave the first example that came to him.
var i = 100; while(i--) els[i].addEventListener("click",fn);
it'd be untrue jQuery is nowhere _near_ 100x slower. Profiling this is totally ridiculous because there's no use case that requires adding event listeners at a scale that could _ever_ be a performance concern, but anyway - http://jsperf.com/jquery-on-vs-native/3. So just 10x slower on even this - completely not performance critical and therefore nobody would bother optimising it - method.
However, throwing away jQuery for whatever reason (as we have on the iOS-only project I've been on for the last 3 months) doesn't necessarily mean you're stuck in verbosity hell. We just tried to look for the points where it seemed most verbose/painful and wrote thin jQuery-ish wrappers around native stuff... so, for example, there's a short alias for querySelector All which gloms `Array.prototype.forEach` onto the return value, and class manipulation functions, and a handful of other things. Last time I checked, the library fits on one screen and none of the functions are longer than 4 lines.
Not necessarily the right approach for every project, but neither has it been a descent into hell.
Interestingly, I've never found event binding to be a particular pain point; the thing I'm really getting tired of is writing `e.preventDefault()`, but jQuery isn't going to save me from that anyway.
Yes, jQuery is a time saving tool, and a really good one at that. The problem isn't jQuery, it's the developers that abuse it.
Oh.. Déjà vu...
It was really laggy on Android, so no.
It doesn't matter. When you have a non-trivial thing to render in a list, not just a div with text content, and you start to scroll the browser stutters. Even if the list isn't particularly long (< 50 items).
CSS animations are also rather slow in mobile browsers although this is getting better with every release.
I actually find it a little bothersome that so much browser development these days is focused on JavaScript performance and JavaScript alternatives whether it is Dart or asm.js or whatever... when the DOM is the primary reason lag exists.
He argues that the developers working on these browsers are optimizing them, and that we are not intelligent enough to trump their obviously superior coding skills. Well, I'm going to disagree outright on that point. Many of us are very talented.
Add Webkit on top of the Dalvik VM and android SDK, and fragmented device ecosystem, and we're talking major disparities between the way your HTML5 app is going to run on different android devices. I have seen HTML5 apps that work great on phone a and b, but not on c, because well, c has a different webkit version!
It's bad enough to have to write code for different browsers. It's really bad to have to write code for different browsers that will run on hundreds of different android devices.
Back to the point you made about optimization: don't you think the developers of the native SDKs are making optimizations, too? And the lower level means we're way closer to the metal, lower on the stack, and ergo: less complex.
I'd use HTML5 for a trivial app, like, a business's mobile website. But for anything serious, GO NATIVE!
Note, my answer is for mobile browsers, specifically android. Even iOS should be marginally better on this, but really I've only seen HTML5 kicking ass on desktop browsers. I've yet to be impressed by it in mobile.
There appears to be an uptick of hyper-agressive technical posts over the past several years. I'm not sure where it started, but I'm hoping it burns itself out soon.
(If you're the author, I apologize for calling you out on this. Nothing personal at all, I just wanted to make the general point about tone.)
Look under DH2.
I didn't find his tone offensive at all, esp as a piece of writing. It's likely that he hears "DOM is slow" all the time, and is venting. And he's a far cry from Zed Shaw's kind of writing.
However, if you'd prefer a critique on the substance of the actual article, I have one of those, too: https://news.ycombinator.com/item?id=5401340
He's saying it's more difficult to convince people of your point if you're being a dick about it. You aren't arguing the central point of his thesis, so I'm unsure what exactly your point is in regards to OP.
As far as I know, PG's post doesn't apply to the original article, as the article starts the discussion, rather than responds to one.
That's pure premature optimization. I don't understand how people can still be making blanket statements about performance costs like this. Using jQuery to create HTML elements is fine. It's convenient and succinct, and it keeps your code consistent. Otherwise, you'll have two ways of creating HTML elements: one for when you are just creating an element, and another for when you need to use jQuery on it afterward.
But if you do hit a point where creating HTML elements with jQuery is slow, you optimize that point and leave a comment explaining why you're doing it that way.
People get these ideas in their heads that somehow they're going to be able to code everything super fast from the very start, and it's nonsense. All you're going to do is make it harder to maintain your project.
When you're working in the mobile web and performance is important you want to know what every line of code is doing. Your application is probably going to be a little laggy anyways, but at least you'll know why that is and know where to target to try and fix it.
Except that it's not, because you can use profiling in modern browsers to figure out where the time is being spent.
>It's probably that in order to gain the 'sticky' affect you want that jquery plugin you're using is listening to a window.onscroll or something, and unless you want to dig into the code of every library you're using you probably won't know why.
But that's not what the author is arguing, and it has nothing to do with adding elements to the DOM via jQuery vs via lower level methods.
The native vs web argument has been beaten to death. It comes down to this: there is no perfect solution and everything has trade-offs (speed, quality, and cost). Use your brain and pick the solution that works best for the problem you are trying to solve. As much as web apps have replaced many things that may have previously been implemented as native apps on the desktop, there is still native development being done.
That was impressive on a 486 SX. The things that make people go "woa!" in a browser are, barring WebGL demos entirely made in shaders, completely not-impressive when compared to doing the same outside a browser. This is fine. The browser is expected to handle so many wildly varying use cases at once, it can't be top speed at all of them. But don't go around telling us that something that Firefox does on a 2Ghz quad core PC is amazing when the same has been done on an Amiga 500.
The DOM is slow. It can be used to be fast enough for most purposes.
What is the use case for generating 2000 unstyled divs with one line of text? Try making that into a nice slick CSS list, maybe throw an image in each list item, with some title copy and supporting text. Perhaps you throw a bit of text shadow on it to create a nice beveled effect. Oh yeah, that 2000 divs per 200 milliseconds probably just turned into 10. Maybe even less, maybe 1 or 2 on a mobile browser.
WebGL can gain acceptable performance in many situations, but there is still much overhead.
I suspect today's most web developers don't know the true performance of computers they are actually using.
You call that impressive on 2013? My laptop can sort a million numbers in the times you can create a mere 10k objects.
>using JavaScript, render the whole thing in about 100 milliseconds.
That's not fast enough. 100ms is perceptible. Websites should render instantly, and 100ms is on top of everything else.
For 99% of the projects out there, jQuery is fast enough and it's productivity boosts outweigh any performance costs.
Someone has already written a decent JSPerf to test this out: http://jsperf.com/innerhtml-vs-createelement-test/16 (see also http://jsperf.com/innerhtml-vs-createelement-test/4 for a slightly deeper dive)
Based on the Browserscope results (and my own testing), it seems that document.createElement is faster in Webkit but slower in everything else (Gecko, Trident). So, a bit of a wash there unless you're targeting mobile.
That said, in my experience HTML (template) parsing isn't the main bottleneck to getting an app to that smooth 60fps feeling. Usually the big targets you want to focus on there are avoiding cascading reflows/repaints, using smoother animation technologies such as requestAnimationFrame or CSS transitions/animations, understanding how to trigger hardware acceleration and what its limits are, and keeping careful control of your CSS special effects (border radius, box-shadow, gradients, etc). I recommend checking out http://jankfree.com/ (especially the I/O talk) if you're interested.
(edit: I don't really like the original article's vitriol, but he's right about a couple things. Manipulating your nodes outside of the DOM is much faster, although you don't need to be inside a DocumentFragment to do this (don't get me wrong; DocFrags are pretty useful). Also, yes, please don't keep running those jQuery selectors over and over again. Store the jQ object that the selector returns to you and just reuse that)