Любое преимущество в производительности для "блокировки" объектов JavaScript?
JavaScript 1.8.5 (ECMAScript 5) добавляет некоторые интересные методы, которые предотвращают будущие изменения пройденного объекта с различной степенью тщательности:
Предположительно главный смысл этого заключается в том, чтобы поймать ошибки: если вы знаете, что не хотите изменять объект после определенного момента, вы можете заблокировать его, чтобы ошибка была выброшена, если вы непреднамеренно попытаетесь изменить это позже. (Обеспечение выполнения "use strict";
).
Мой вопрос: в современных JS-машинах, таких как V8, есть ли какое-либо преимущество в производительности (например, более быстрый поиск свойств, сокращение занимаемой памяти) при блокировке объектов с использованием вышеуказанных методов?
(См. также Хорошее объяснение Джона Ресига - не упоминает о производительности.)
Ответы
Ответ 1
В разнице в производительности не было, поскольку по крайней мере Chrome 47.0.2526.80 (64-разрядная версия).
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
Тест производительности (доступен на 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);
Обновление 17.09.2019. В Chrome нет различий в производительности 76.0.3809 (64-разрядная версия)
Обновление 03.05.2018: в Chrome нет различий в производительности 66.0.3359 (64-разрядная версия)
Обновление 06.03.2017: в Chrome нет различий в производительности 56.0.2924 (64-разрядная версия)
Обновление 13.12.2015: в Chrome нет различий в производительности 47.0.2526.80 (64-разрядная версия)
В Chrome 34 замороженный объект работает немного лучше, чем не замороженный в тестовом примере @pimvdb (результаты приведены ниже). Однако разница, по-видимому, недостаточно велика, чтобы оправдать использование этого метода для повышения производительности.
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
Выполнение тестовых примеров @kangax показывает, что обе версии объекта работают примерно одинаково:
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
Ответ 2
В Google Chrome (например, V8) замороженный объект выполняет итерацию на 98% медленнее, чем обычный объект.
http://jsperf.com/performance-frozen-object
Test name* ops/sec
non-frozen object 32,193,471
frozen object 592,726
Вероятно, это потому, что эти функции относительно новые и, вероятно, еще не оптимизированы (но это только моя догадка, я честно не знаю причины).
Во всяком случае, я действительно не рекомендую использовать его для повышения производительности, поскольку это, по-видимому, не имеет смысла.
* Код для теста:
var o1 = {a: 1};
var o2 = {a: 1};
Object.freeze(o2);
Тест 1 (незамерзший объект):
for(var key in o1);
Тест 2 (замороженный объект):
for(var key in o2);
EDIT:
Поскольку этот ответ был изначально написан, исправлена ошибка в V8, вызвавшая эту проблему. См. ответ Яна Молака выше для mor
Ответ 3
В теории замораживание объекта позволяет сделать более надежные гарантии относительно формы объекта.
Это означает, что виртуальная машина может сжать размер памяти.
Это означает, что виртуальная машина может оптимизировать поиск свойств в цепочке прототипов.
Это означает, что любые живые ссылки только что стали неживыми, потому что объект больше не может меняться.
На практике механизмы JavaScript еще не делают эту агрессивную оптимизацию.
Ответ 4
V8 оптимизировал Object.freeze по состоянию на 20 июня 2013 года. А Object.seal и Object.preventExtensions по состоянию на 10 декабря 2014 года. См. проблему https://code.google.com/p/chromium/issues/detail?id=115960
Ответ 5
Как проблема с кодом Google:
Разница в производительности связана с структурой данных хранилища резервных копий. Для нескольких свойств дескриптор объекта описывает, где свойства сохраняются в массиве свойств. Если количество свойства растут, мы в конечном итоге переключаемся на словарь для поддержки магазин, который менее эффективен, но более гибкий. Когда мы замораживаем объект, то, что делается, заключается в том, что для всех свойств задано значение неконфигурируемым и ненаписанным. Хранение этих атрибутов возможно в хранилище поддержки словаря, поэтому мы переключаемся на это.
РЕДАКТИРОВАТЬ: Проделана большая работа по оптимизации этого, а разница между нормальными объектами и замороженными объектами уменьшена примерно до 20%. Запечатанные объекты по-прежнему занимают в два раза больше времени, чтобы выполнять итерацию, но на это не работает.
Ответ 6
Если вы заинтересованы в производительности создания объекта (буквально против замороженного и закрытого vs Immutable.Map
), Ive создал a тест на jsPerf, чтобы проверить это.
До сих пор у Ive была возможность протестировать его в Chrome 41 и Firefox 37. В обоих браузерах создание замороженного или запечатанного объекта занимает примерно в три раза больше, чем создание литерала - тогда как Immutable.Map
выполняет примерно в 50 раз хуже, чем буквальный.
Ответ 7
Единственная причина, по которой я вижу эти методы в производственном коде, заключается в том, что вы можете иметь запечатанные или замороженные объекты для целей целостности.
Например, я пишу небольшую библиотеку, которая отлично работает и предлагает вам набор методов в объекте, но я не хочу, чтобы вы меняли или перезаписывали любые мои свойства или методы. Я не говорю, что я могу помешать вам это сделать, но я могу попытаться помешать вам сделать это случайно, что, возможно, более важно.
Кроме того, эти методы легко "закрепить" в среде, о которой они не знают, просто вернув исходный объект. Конечно, это не будет иметь никакого эффекта.
Я не вижу причин, связанных с производительностью.