TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Faster DOM

133 pointsby plurbyalmost 9 years ago

13 comments

CharlesWalmost 9 years ago
&gt; <i>That way, you only do the IDL-dance once and the browser then manipulates the tree in C++ with the many operations you fed it.</i><p>As a beginning web developer, I remember being surprised that there was no way for me to group DOM manipulations into SQL-like transactions, or even an equivalent to HyperCard&#x27;s lockScreen.<p>I&#x27;m finding it a little tough to tell whether the author is talking about putting the browser or the web developer in control of grouping DOM updates.
评论 #11779671 未加载
评论 #11779622 未加载
评论 #11779633 未加载
评论 #11780619 未加载
评论 #11779634 未加载
c-smilealmost 9 years ago
We all know that Element.innerHtml = &quot;...&quot; can be significantly faster than set of individual DOM mutating calls. Element.innerHtml = ... gets executed as single transaction - relayout happens only once, at the end of it. Yet there is no overhead on JS-native bridging and function calls in JS in general.<p>But the need of &quot;transactioned&quot; DOM updates is not just about the speed. There are other cases when you need this. In particular:<p>1. Massive DOM updates (that&#x27;s your case), can be done with something like: Element.update( function mutator(ctx) ). While executing the mutator callback Element.update() locks&#x2F;delays any screen&#x2F;layout updates.<p>2. That Element.update( function mutator(ctx) ) can be used with enhanced transitions. Consider something like transition: blend linear 400ms; in CSS. While executing the update browser makes snapshots of initial and final DOM states and does blending of these two states captured into bitmaps.<p>3. transactioned update of contenteditable. In this case Element.update() groups all changes made by the mutator into single undoable operation. This is a big deal actually in WYSIWYG online editors.<p>There are other cases of course, but these three functionalities are what I&#x27;ve implemented in my Sciter Engine ( <a href="http:&#x2F;&#x2F;sciter.com" rel="nofollow">http:&#x2F;&#x2F;sciter.com</a> ) already - proven to be useful.
评论 #11780324 未加载
tixzdkalmost 9 years ago
I&#x27;ll leave this module here for those of you how haven&#x27;t heard of it. <a href="https:&#x2F;&#x2F;github.com&#x2F;patrick-steele-idem&#x2F;morphdom" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;patrick-steele-idem&#x2F;morphdom</a><p>It diff&#x27;s the DOM instead of a VDOM
评论 #11780862 未加载
评论 #11780582 未加载
m1elalmost 9 years ago
I was playing with the idea of using JS objects as a template engine: <a href="http:&#x2F;&#x2F;m1el.github.io&#x2F;jsonht.htm" rel="nofollow">http:&#x2F;&#x2F;m1el.github.io&#x2F;jsonht.htm</a>, and I&#x27;m pretty happy with it.<p>I think DOM is pretty damn fast in modern browsers. `innerHTML` can be slower than creating elements from a JS object!<p>Here&#x27;s the script I&#x27;m using for timing: <a href="https:&#x2F;&#x2F;gist.github.com&#x2F;m1el&#x2F;b28625b3b9261f0fab819e866133e49a" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;m1el&#x2F;b28625b3b9261f0fab819e866133e49...</a><p>My results in Chrome are: dom: 2663.580ms, innerHTML: 10999.449ms
评论 #11782277 未加载
评论 #11781261 未加载
bzbarskyalmost 9 years ago
I wrote up a response to this but haven&#x27;t found a good place to put it; might as well post it here.<p>1) I think the idea about such an API encouraging good practice is very much correct, in the sense that it makes it harder to interleave DOM modification and layout flushes. That might make it worth doing on its own.<p>2) DOM APIs are not necessarily _that_ cheap in and of themselves (though they are compared to layout flushes). Setting the various dirty flags can actually take a while, because in practice just marking everything dirty on DOM mutation is too expensive, so in practice UAs limit the dirty marking to varying degrees. This trades off time inside the DOM API call (figuring out what needs to be dirtied) for a faster relayout later. There is some unpredictability across browser engines in terms of which APIs mark what dirty and how long it takes them to figure that out.<p>3) The IDL cost is pretty small in modern browsers, if we mean the fixed overhead of going from JS to C++ and verifying things like the &quot;this&quot; value being of the right type. When I say &quot;pretty small&quot;, I mean order of 10-40 machine instructions at the most. On a desktop machine, that means the overhead of a thousand DOM API calls is no more than 13 microseconds. On mobile, it&#x27;s going to be somewhat slower (lower clocks, if nothing else, smaller caches, etc). Measurement would obviously be useful.<p>There is the non-fixed overhead of dealing with the arguments (e.g. going from whatever string representation your JS impl uses to whatever representation your layout engine uses, interning strings, copying strings, ensuring that provided objects, if any, are the right type, etc). This may not change much between the two approaches, obviously, since all the strings that cross the boundary still need to cross it in the end. There will be a bit less work in terms of object arguments, sort of. But....<p>4) The cost of dealing with a JS object and getting properties off it is _huge_. Last I checked in Gecko a JS_GetProperty equivalent will take 3x as long as a call from JS into C++. And it&#x27;s much worse than that in Chrome. Most of the tricks JITs use to optimize stuff go out the window with this sort of access and you end up taking the slowest slow paths in the JS engine. What this means in practice is that foo.bar(&quot;x&quot;, &quot;y&quot;, &quot;z&quot;) will generally be much faster than foo.bar({arg1: &quot;x&quot;, arg2: &quot;y&quot;, arg3: &quot;z&quot;}). This means that the obvious encoding of the new DOM as some sort of JS object graph that then gets reified is actually likely to be much slower than a bunch of DOM calls right now. Now it&#x27;s possible that we could have a translation layer, written in JS such that JITs can do their magic, that desugars such an object graph into DOM API calls. But then that can be done as a library just as well as it can be done in browsers. Of course if we come up with some other way of communicating the information then we can possibly make this more efficient at the expense of it being super-ugly and totally unnatural to JS developers. Or UAs could do some sort of heroics to make calling from C++ to JS faster or something....<p>5) If we do provide a single big blob of instructions to the engine, it would be ideal if processing of that blob were side-effect free. Or at least if it were guaranteed that processing it cannot mutate the blob. That would simplify both specification and implementation (in the sense of not having to spell out a specific processing algorithm, allowing parallelized implementation, etc). Instructions as object graph obviously fail hard here.<p>Summary: I think this API could help with the silly cases by preventing layout interleaving. I don&#x27;t think this API would make the non-silly cases any faster and might well make them slower or uglier or both. I think that libraries can already experiment with offering this sort of API, desugaring it to existing DOM manipulation, and see what the performance looks like and whether there is uptake.
maxbrunsfeldalmost 9 years ago
I&#x27;m curious about the source of the slowness of the IDL operations. Is it specific to the DOM, or is he referring to overhead that exists for <i>any</i> bindings between JS and C++?
评论 #11779969 未加载
评论 #11780186 未加载
EGregalmost 9 years ago
Yeah, that&#x27;s why in our framework, we go the FastDOM &#x2F;greensock route and encourage writing mutation code explicitly for when the state changes.<p>However to be fair the point of React, vdom, mithril etc. is to allow the developers to write a mapping from state to view and let the mutations be calculated automatically. They claim it&#x27;s easier to just write the logic of the mapping instead of all possible transitions. I don&#x27;t buy it, but it has grown to a huge community.
mmastracalmost 9 years ago
I think this is a natural evolution of where DOM has been headed. Batching requests is entirely within the spirit of the original DOM.
lucioalmost 9 years ago
Something like suspendLayout(), resumeLayout() I guess this GUI technique is like... 50 years old?
lj3almost 9 years ago
At what point does fiddling with the DOM get complicated and unpredictable enough that WebGL and&#x2F;or Canvas starts to look like the saner alternative?<p>On that note, I just stumbled on an old framework that&#x27;s been out of development since 2012 called Blossom. It looks like it uses Canvas instead of the DOM. Does anybody have any history with it?
评论 #11783686 未加载
ameliusalmost 9 years ago
Is there anything in a browser that ensures that simple updates with local effect have O(1) layout cost?<p>Or do developers have to live with the uncertainty that simple updates may have a higher computational complexity?
评论 #11782543 未加载
bedersalmost 9 years ago
Build faster browsers. Don&#x27;t be afraid of dogma.<p>There were times before there was a DOM (you might not have been born yet) and there can be times after DOM :)
kralljaalmost 9 years ago
&gt; backed by C++ (née Rust)<p>&quot;née&quot; means &quot;originally called&quot; (usually someone&#x27;s maiden name). I don&#x27;t think C++ used to be called Rust.
评论 #11781096 未加载
评论 #11780575 未加载