admin管理员组文章数量:1135655
JavaScript 1.8.5 (ECMAScript 5) adds some interesting methods that prevent future modifications of a passed object, with varying degrees of thoroughness:
Object.preventExtensions(obj)
Object.seal(obj)
Object.freeze(obj)
Presumably the main point of these is to catch mistakes: if you know that you don't want to modify an object after a certain point, you can lock it down so that an error will be thrown if you inadvertently try to modify it later. (Providing you've done "use strict";
that is.)
My question: in modern JS engines such as V8, is there any performance benefit (eg, faster property look-ups, reduced memory footprint) in locking down objects using the above methods?
(See also John Resig's nice explanation – doesn't mention performance, though.)
JavaScript 1.8.5 (ECMAScript 5) adds some interesting methods that prevent future modifications of a passed object, with varying degrees of thoroughness:
Object.preventExtensions(obj)
Object.seal(obj)
Object.freeze(obj)
Presumably the main point of these is to catch mistakes: if you know that you don't want to modify an object after a certain point, you can lock it down so that an error will be thrown if you inadvertently try to modify it later. (Providing you've done "use strict";
that is.)
My question: in modern JS engines such as V8, is there any performance benefit (eg, faster property look-ups, reduced memory footprint) in locking down objects using the above methods?
(See also John Resig's nice explanation – doesn't mention performance, though.)
Share Improve this question edited May 8, 2012 at 14:37 callum asked Dec 8, 2011 at 17:29 callumcallum 37.6k38 gold badges112 silver badges175 bronze badges 2- Possible duplicate of Difference between freeze and seal in Javascript – maja Commented May 7, 2017 at 13:12
- I posted a new answer with working perf links. I attempted to prevent any dead code elimination, and it seems as though frozen objects are slightly slower for iteration using for-in. stackoverflow.com/a/70490675/454780 – trusktr Commented Dec 27, 2021 at 0:15
7 Answers
Reset to default 110There's been no difference in performance since at least Chrome 47.0.2526.80 (64-bit).
Testing in Chrome 6.0.3359 on Mac OS 10.13.4
-----------------------------------------------
Test Ops/sec
non-frozen object 106,825,468 ±1.08% fastest
frozen object 106,176,323 ±1.04% fastest
Performance test (available at http://jsperf.com/performance-frozen-object):
const o1 = {a: 1};
const o2 = {a: 1};
Object.freeze(o2);
// Non-frozen object:
for(var key in o1);
// Frozen object:
for(var key in o2);
Update 30.10.2019: There's no difference in performance on Chrome 78.0.3904 (64-bit)
Update 17.09.2019: There's no difference in performance on Chrome 76.0.3809 (64-bit)
Update 03.05.2018: There's no difference in performance on Chrome 66.0.3359 (64-bit)
Update 06.03.2017: There's no difference in performance on Chrome 56.0.2924 (64-bit)
Update 13.12.2015: There's no difference in performance on Chrome 47.0.2526.80 (64-bit)
With Chrome 34, a frozen object performs slightly better than a non-frozen one in @pimvdb's test case (results below). The difference, however doesn't seem to be large enough to justify using this technique for performance benefits.
http://jsperf.com/performance-frozen-object
Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test Ops/sec
non-frozen object 105,250,353 ±0.41% 3% slower
frozen object 108,188,527 ±0.55% fastest
Running @kangax's test cases shows that both versions of the object perform pretty much the same:
http://jsperf.com/performance-frozen-object-prop-access
Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test Ops/sec
non-frozen object 832,133,923 ±0.26% fastest
frozen object 832,501,726 ±0.28% fastest
http://jsperf.com/http-jsperf-com-performance-frozen-object-instanceof
Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test Ops/sec
non-frozen object 378,464,917 ±0.42% fastest
frozen object 378,705,082 ±0.24% fastest
In theory freezing an object allows you to make stronger guarantees about the shape of an object.
This means the VM can compact the memory size.
It means the VM can optimize property lookups in the prototype chain.
It means any live references just became not live because the object cannot change anymore.
In practice JavaScript engines do not make these aggressive optimization yet.
Update: Since this answer was originally written, the bug in V8 that caused this issue has been fixed. See the answer by Jan Molak for more info.
In Google Chrome (so V8, that is), a frozen object iterates 98% slower than a regular object.
http://jsperf.com/performance-frozen-object
Test name* ops/sec
non-frozen object 32,193,471
frozen object 592,726
Probably this is because those functions are relatively new and probably not optimized yet (but that's just my guess, I honestly don't know the reason).
Anyhow, I really do not recommed using it for performance benefits, as that apparently does not make sense.
* The code for the test is:
var o1 = {a: 1};
var o2 = {a: 1};
Object.freeze(o2);
Test 1 (non-frozen object):
for(var key in o1);
Test 2 (frozen object):
for(var key in o2);
V8 has optimized Object.freeze as of Jun 20, 2013. And Object.seal and Object.preventExtensions as of Dec 10, 2014. See issue https://code.google.com/p/chromium/issues/detail?id=115960
jsperf links in the answers are broken, plus an empty for-loop might cause dead code elimination in some engines, so I wrote a new test to ensure code elimination doesn't happen. Most of the time the frozen object wins:
perf.link benchmark
For reference, the code looks like:
const o1 = {a: 1};
const o2 = {a: 1};
Object.freeze(o2);
// store stuff to prevent any sort of theoretical dead code elimination
const buffer = [];
// test 1, unfrozen
for(const key in o1) buffer.push(key);
// test 2, frozen
for(const key in o2) buffer.push(key);
EDIT: I tried to further eliminate the possibility of dead code elimination. Maybe (?) an engine can detect and eliminate the unused buffer
array that is never read from, so in the following benchmark I placed the object onto the globalThis object, and the frozen object tends to win more often (edited, it more recently wins more often, but at some point it was slower):
perf.link benchmark
For reference, the code looks like:
const o1 = {a: 1};
const o2 = {a: 1};
Object.freeze(o2);
// store stuff to prevent any sort of theoretical dead code elimination
globalThis._buffer = [];
// test 1, unfrozen
for(const key in o1) globalThis._buffer.push(key);
// test 2, frozen
for(const key in o2) globalThis._buffer.push(key);
If you’re interested in the performance of object creation (literal vs frozen vs sealed vs Immutable.Map
), I’ve created a test on jsPerf to check that out.
So far I’ve only had the opportunity to test it in Chrome 41 and Firefox 37. In both browsers the creation of a frozen or sealed object takes about three times longer than the creation of a literal – whereas the Immutable.Map
performs about 50 times worse than the literal.
The only reason I see for those methods in production code is, that you can have sealed or frozen objects, for integrity purposes.
For instance, I write a little library, which works just great and offers you a set of methods in an object, but I don't want to you to change or overwrite any of my properties or methods. I'm not saying I can prevent you from doing that, but I can try to prevent you do it by accident which maybe is more important.
Also, those methods are easy to 'shim' in environment which doen't know about them, by just returning the original object. Of course it would have no effect then.
I don't see any performance related reasons to do this.
本文标签: ecmascript 5Any performance benefit to quotlocking downquot JavaScript objectsStack Overflow
版权声明:本文标题:ecmascript 5 - Any performance benefit to "locking down" JavaScript objects? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736922543a1956510.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论