W3C home > Mailing lists > Public > public-script-coord@w3.org > July to September 2014

Re: Object.observe()able properties on the web platform

From: Andreas Rossberg <rossberg@google.com>
Date: Thu, 21 Aug 2014 17:17:06 +0200
Message-ID: <CADjR9Noup6VjYzzappjEnS4kuG7-MUMXLyv-ZS2gO7War8QJtw@mail.gmail.com>
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

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 17:14:22 UTC