Open Bug 1088453 Opened 10 years ago Updated 2 years 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
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.