Есть ли какое-то преимущество в производительности для "блокировки" объектов JavaScript? - PullRequest
61 голосов
/ 08 декабря 2011

JavaScript 1.8.5 (ECMAScript 5) добавляет некоторые интересные методы, которые предотвращают будущие модификации переданного объекта с различной степенью тщательности:

Предположительно, основной из нихловить ошибки: если вы знаете, что не хотите модифицировать объект после определенного момента, вы можете заблокировать его, чтобы возникла ошибка, если вы случайно попытаетесь изменить его позже.(Если вы сделали "use strict";, то есть.)

Мой вопрос: в современных движках JS, таких как V8, есть ли какое-либо преимущество в производительности (например, более быстрый поиск свойств,уменьшение объема памяти) при блокировке объектов с помощью описанных выше методов?

(см. также Хорошее объяснение Джона Резига - хотя и не упоминается производительность.)

Ответы [ 7 ]

72 голосов
/ 21 апреля 2014

Не было разницы в производительности , так как по крайней мере 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);

Обновление 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
14 голосов
/ 08 декабря 2011

В 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, которая вызвала эту проблему , была исправлена. См. ответ Яна Молака выше для более

11 голосов
/ 08 декабря 2011

Теоретически замораживание объекта позволяет сделать более строгие гарантии о форме объекта.

Это означает, что виртуальная машина может уменьшить размер памяти.

Это означает, что виртуальная машина может оптимизировать поиск свойств в цепочке прототипов.

Это означает, что любые живые ссылки просто стали неактивными, потому что объект больше не может меняться.

На практике JavaScriptдвигатели пока не проводят эту агрессивную оптимизацию.

5 голосов
/ 29 марта 2015

V8 оптимизировал Object.freeze по состоянию на 20 июня 2013 года. И Object.seal и Object.preventExtensions по состоянию на 10 декабря 2014 года. См. Выпуск https://code.google.com/p/chromium/issues/detail?id=115960

2 голосов
/ 21 сентября 2014

Согласно проблема с кодом Google :

Разница в производительности обусловлена ​​структурой данных резервного хранилища. Для нескольких свойств дескриптор объекта описывает, где свойства хранятся в массиве свойств. Если количество свойства растут, мы в конечном итоге перейти на словарь для поддержки магазин, который менее производительный, но более гибкий. Когда мы замораживаем объект, что делается, что все свойства установлены в не настраиваемый и не подлежащий записи. Хранение этих атрибутов только возможно в хранилище словаря, поэтому мы переключаемся на это.

РЕДАКТИРОВАТЬ: Была проделана большая работа по оптимизации этого и разница между нормальными объектами и замороженных объектов была уменьшена до примерно 20%. Для итерации запечатанных объектов по-прежнему требуется вдвое больше времени, но работа над этим ведется.

1 голос
/ 13 мая 2015

Если вас интересует производительность объекта создание (литерал против замороженного или запечатанного против Immutable.Map), я создал тест на jsPerf чтобы проверить это.

Пока у меня была возможность протестировать его только в Chrome 41 и Firefox 37. В обоих браузерах создание замороженного или запечатанного объекта занимает примерно в три раза дольше , чем создание литерала - тогда как Immutable.Map работает примерно в 50 раз хуже, чем буквальный.

0 голосов
/ 08 декабря 2011

Единственная причина, по которой я вижу эти методы в рабочем коде, заключается в том, что вы можете иметь запечатанные или замороженные объекты в целях целостности.

Например, я пишу небольшую библиотеку, которая прекрасно работает и предлагаетвы набор методов в объекте, но я не хочу, чтобы вы меняли или перезаписывали какие-либо из моих свойств или методов.Я не говорю, что могу помешать вам сделать это, но я могу попытаться помешать вам сделать это случайно, что, возможно, более важно.

Кроме того, эти методы легко «подклинивать» в среде, котораяне знаю о них, просто возвращая исходный объект.Конечно, тогда это никак не повлияет.

Я не вижу никаких причин, связанных с производительностью, чтобы сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...