- From: Andreas Rossberg <rossberg@google.com>
- Date: Thu, 21 Aug 2014 17:17:06 +0200
- To: Boris Zbarsky <bzbarsky@mit.edu>
- Cc: Domenic Denicola <domenic@domenicdenicola.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>
Let me offer a few clarifications regarding performance (in V8, but probably extrapolates to other VMs): - Checking whether an object is observed is relatively cheap (about half a dozen of machine instructions: 2 memory loads, mask, compare, branch). That seems like a bearable cost once per mutation. - Calling from C++ into JavaScript is not so cheap, tens of instructions of overhead, but currently required to create notification events. That's probably still okay for every _observed_ mutation. - Invoking eval is damn expensive, easily in the order of thousands of instructions -- it has to run the whole compilation pipeline. You don't want to do that in performance sensitive code, ever. - Creating notifications has some cost by itself: several allocations, initialisation, same origin checks, various hash table lookups, and runtime calls. There are also secondary effects to consider: - To spill out mutation notifications you need to get, and hold on to, the previous value. That can cost. - The logic for notification affects every mutator in rather intrusive ways. Depending on the concrete operation, this can increase code size and complexity measurably. (Getting the corner cases right can be hairy.) - Observation is incompatible with lazy computation or other optimisations and short cuts that are probably common in bindings. Finally, just to clear up some myths, observation is nothing close to free inside V8 either: - Observing an object slows down all its mutations severely, easily by 10x-100x, depending on the case. - It invalidates a range of routine optimisations, especially for bulk mutations like on arrays. Essentially, observing an object forces every potentially impure operation on it onto the slowest path. - Observation introduces additional type polymorphism, which can cause even unrelated optimisations to fall off the cliff. Most of these costs are inherent to the mechanism, and there probably isn't much of a chance that they can be optimised by more than constant factors. /Andreas On 20 August 2014 22:14, Boris Zbarsky <bzbarsky@mit.edu> wrote: > On 8/20/14, 4:02 PM, Domenic Denicola wrote: >> >> I can't really speak to this personally. I've been told, or at least >> marketed-to, that it is not an overhead for normal JS objects. > > > I think that depends on your definition of "overhead", no? I seriously > doubt it's a single instruction, for example. > > I do think it should be possible to keep this down to the cost of a > hashtable lookup or something. Not tiny, but OK if you don't have to do too > many of them. > > >> To Olli's point, I would hope that since DOM objects are eventually >> exposed as JS objects, that can prove true for them, if nothing else by >> eval'ing the relevant JS code. > > > eval (or in general entering JS code) is itself somewhat non-negligible. > Order of low hundreds of nanoseconds on modern desktop hardware in most > browsers last I measured. Browsers are trying to improve it, of course. > > >>> Especially so for cases where the property value is computed lazily, >>> because then you need some sort of extra something to notice when the value >>> might have changed, which you don't need without Object.observe. >> >> >> That's fair, but I would assume we would not make such properties >> observable. > > > The thing is, lazy computation is a implementation detail. There are things > that are lazily computed in some UAs but not others. > > >> Yes. Is it not a fair assumption that the code setting a new value for, >> say, wake-lock, can consult the current value of the wake-lock? > > > Sure. But it's not necessarily a fair assumption that the code adding a > node to the DOM tree should consult the current values of all the various > properties whose value might now be that node. > > I do agree we should make things observable judiciously, in case that wasn't > clear. I just think we should consider performance and complexity > implications during said judgments. > > >>> You also constructed an object. And defined properties on it. I can >>> assure you that doing that is non-negligible in performance terms. >> >> >> I would hope that the overhead of using ES's built-in "event" mechanism is >> lower than that of using EventTarget. > > > This is _probably_ true, yes. Event dispatch, due to capture/bubbling and > various other legacy bits has a ton of machinery that I'd hope > Object.observe wouldn't involve. > > >> Again, for all of this, I want to emphasize that what I'm interested in is >> supplanting { prop, propchanged } EventTarget subclasses in favor of { prop >> } classes. > > > Agreed on that. For that use case, I think Object.observe should be just > fine. > > -Boris >
Received on Thursday, 21 August 2014 15:18:04 UTC