Open Bug 1088453 Opened 8 years ago Updated 24 days ago

No way to quickly make non-enumerable instance properties

Categories

(Core :: JavaScript Engine: JIT, defect, P5)

36 Branch
x86
macOS
defect

Tracking

()

People

(Reporter: stefan.penner, Unassigned)

References

(Blocks 1 open bug)

Details

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2198.0 Safari/537.36

Steps to reproduce:

Currently the cost of creating objects who have instance level non-enumerable properties is prohibitive.

Why is this important?

Often users will JSON.stringify/extend/merge/copy or use some sort of enumerating function (like deepEqual when comparing) on objects. 

Unfortunately some data, should not be made available to such methods. Examples could be, internal framework meta-data, state, objects known to contain cycles.

As far as I can tell there are 4 ways to accomplish this non enumerable state:

Marking string properties as non-enumerable
Using symbols
Using a WeakMap to store the state off-object


Actual results:

Unfortunately all of these appear to have downsides.

Non-enumerable string properties: calling defineProperty is prohibitively slow
Symbols: faster to create than defProp, but slower for setting and slower for accessing than regular properties
WeakMaps: under heavy use crash V8 (other issue already opened) and lookups/sets are slower than regular properties

Some related evil micro-benchmarks:

cost of marking an instance property as non-enumerable

new Obj + enumerable property: baseline
new Obj + non-enumerable property (via def prop): 7x slower
new Obj + non-enumerable property (via Symbol): 4x slower
new Obj + weakmap (via Symbol): 7x slower

http://jsperf.com/symbol-vs-prop-vs-def-prop/1

cost of accessing such a property (symbol is unfortunately slower)

Enumerable string:     obj['foo'] === 1: baseline
Non-enumerable string: obj['defined'] === 1: same as basline
Symbol:                obj[FOO]   === 1: 80x slower

http://jsperf.com/symbol-vs-property/2



Expected results:

We have considered moving to symbols. This gave  improved initial render cost vs. non-enumerable (string) properties. The downside is that symbols results in much slower access framework wide. The trade-off is still a win, but it is an unfortunate trade-off to make.

Ideally we would like something with "encapsulation" at least as strong as non-enumerable string properties, but with the performance of enumerable properties. So, this bug is asking to improve one of symbols, non-enumerable string properties, or weak maps to be as fast as enumerable properties.
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
Making symbol-named sets faster seems like the simplest path to victory here.
Component: JavaScript Engine → JavaScript Engine: JIT
Status: UNCONFIRMED → NEW
Ever confirmed: true
Speeding up Object.defineProperty may be good too. Is this bug a tracking bug? Seems like it ought to be.

/be
Agreed that Symbols seem like the right answer here.  They would also avoid glorious perf hacks like this:
  https://github.com/emberjs/ember.js/blob/a6fdd051df9cfff14642f556c892c909fd8e5189/packages/ember-metal/lib/utils.js#L59
for trying to pre-atomize strings.

jorendorff/jandem: could this just be a matter of adding Symbol paths to baseline/ion ICs?
Depends on: 1038859
Although symbols are the right path forward (for new code). Copious amounts of code exists in the wild today, that would really benefit from defProp for non-enumerable cases being fast.
Blocks: jsperf
Priority: -- → P5
You need to log in before you can comment on or make changes to this bug.