Как Object.observe() влияет на производительность?

API JavaScript Object.observe() позволяет любому фрагменту кода получать уведомления об изменениях для всех изменений свойств любого объекта JavaScript.

Разве это не сильно влияет на генерацию кода и оптимизацию производительности, которые могут быть выполнены движком JavaScript (например, V8)? Похоже, что сгенерированный нативный код теперь должен проверять каждую запись в объект. если необходимо создать уведомление об изменении. Невозможно статически определить, настроены ли для данного объекта уведомления или нет. Таким образом, проверки не могут быть оптимизированы.

Похоже, что любой соответствующий движок JavaScript теперь обречен на постоянную и серьезную потерю производительности из-за этого API.


person usr    schedule 27.02.2013    source источник
comment
Невозможно статически определить, настроены ли для данного объекта уведомления. Почему?   -  person Bergi    schedule 27.02.2013
comment
@ Берги, как бы ты это сделал? Статически означает без запуска кода или проверки объекта.   -  person usr    schedule 27.02.2013


Ответы (2)


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

Если мы говорим о V8, то факт, наблюдается объект или нет, закодирован в его скрытом классе. И заглушки встроенного кэша, и оптимизированный код уже проверяют скрытый класс на соответствие некоторому ожидаемому значению, чтобы определить, имеет ли объект ожидаемую форму или нет. Сама же проверка дает информацию о том, наблюдается объект или нет. Так что ничего не меняется в путях кода, которые работают с ненаблюдаемыми объектами. Начало наблюдения за объектом обрабатывается так же, как и изменение его формы: скрытый класс объекта переключается на другой с установленным наблюдаемым битом: вы можете прочитать Runtime_SetIsObserved, чтобы увидеть это.

Аналогичные рассуждения применимы к частям системы, которые пропускают средства защиты в оптимизированном коде и вместо этого деоптимизируют код, зависящий от допущений «формы»: как только объект становится наблюдаемым, весь оптимизированный код, зависящий от предположения, что такой объект не наблюдался, будет деоптимизирован. Таким образом, снова за ненаблюдаемые объекты не платят никакой цены.

Тем не менее, текущая реализация Object.observe в V8 заставляет наблюдаемые объекты платить высокую цену, потому что она их нормализует (превращает в словарное представление) и требует прохождения через систему времени выполнения для записи наблюдения. Но нет присущих технических сложностей в том, чтобы значительно снизить эту стоимость в дальнейшем.

person Vyacheslav Egorov    schedule 27.02.2013
comment
Тем не менее, это требует, чтобы движки всегда придерживались подхода динамического скрытого класса. Прямо сейчас было бы возможно решить больше этих оптимизаций специализации, используя статический анализ или аннотации типов (в будущей версии JavaScript). Теперь это будет невозможно навсегда. JS теперь никогда не сможет быть таким же быстрым, как, скажем, Java или .NET, даже с идеальной информацией о типах. - person usr; 27.02.2013
comment
Во-первых, позвольте мне заметить, что статический анализ типов для полного JavaScript в его нынешнем виде слишком дорог и непрактичен; а аннотации типов — это гипотетическая вещь завтрашнего дня, и даже когда они будут введены, движки должны будут хранить скрытые классы для быстрого запуска неаннотированного кода старой школы для обратной совместимости. Во-вторых, сравнение какого-то абстрактного понятия скорости языка X и языка Y неконструктивно, вы должны указать тест, языковые шаблоны, которые мы обсуждаем, и т. д. И, наконец, я специально изложил подход, при котором исполняемый код не содержит никаких проверок вообще. . - person Vyacheslav Egorov; 28.02.2013
comment
Этот последний подход основан на том, что Object.observe деоптимизирует код, который потенциально может выполнять запись в наблюдаемые объекты. Это очень похоже на деоптимизацию кода, когда, например, подключен отладчик. В зависимости от того, как все реализовано, он может деоптимизировать все или только затронутые функции. - person Vyacheslav Egorov; 28.02.2013
comment
Невозможно деоптимизировать только затронутые функции, потому что любой объект вообще (за исключением случаев, когда с помощью escape-анализа доказано, что он никогда не переходит в код наблюдения, даже с помощью eval) может наблюдаться (и это может измениться на любой итерации цикла событий) .; Не поймите меня неправильно, ваш ответ очень полезен и будет принят через несколько дней. Я просто чувствую, что эта конкретная функция обеспечивает своего рода привязку к производительности, которой у нас никогда не было раньше, и это необратимо. - person usr; 28.02.2013
comment
Конечно, нет никакого способа узнать точно затронутые функции. Простите мою корявую формулировку в последнем предложении. В первом предложении сказано правильно: деоптимизировать код, который потенциально может быть написан. Современные JIT уже имеют для этого средства: они могут деоптимизировать только те функции, которые специализированы для работы с объектами данного скрытого класса. В гипотетическом будущем с аннотациями типов будет достаточно деоптимизировать те функции, которые содержат аннотацию типа, совпадающую с типом наблюдаемого объекта в своих телах (или телах, встроенных в них). - person Vyacheslav Egorov; 28.02.2013
comment
Я пытаюсь показать здесь, что если вы не используете Object.observe, вы абсолютно ничего не платите. Когда вы его используете, то конкретная стоимость будет зависеть от реализации и самого приложения. - person Vyacheslav Egorov; 28.02.2013

Разве это не сильно влияет на генерацию кода и оптимизацию производительности, которую может выполнять механизм JavaScript (например, V8)?

Да. Точно так же, как прокси, геттеры/сеттеры и, может быть, даже объекты-прототипы — все они динамические в JavaScript.

Однако из-за их асинхронности возможны новые (и лучшие) оптимизации; и они могут сделать другой, более неэффективный код устаревшим. Ссылаясь на Цели из проекта гармонии:

  • Не требуются объекты-оболочки или прокси, что обеспечивает эффективность использования памяти и идентификацию объекта.
  • Изменить уведомления о добавлении/удалении свойства объекта
  • Уведомления об изменении дескриптора свойств объекта
  • Возможность для объекта вручную указать, когда свойство доступа изменилось
  • Эффективно реализуется в двигателях
  • Простое, целевое, расширение текущей ES
  • Асинхронное уведомление об изменениях, но разрешить синхронное получение изменений, ожидающих доставки
person Bergi    schedule 27.02.2013