Подтвердить что ты не робот

Любое преимущество в производительности для "блокировки" объектов JavaScript?

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

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

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

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

4b9b3361

Ответ 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

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

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

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

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