Как различные проекты оптимизации Javascript влияют на производительность DOM?
В Javascript через проекты Tracemonkey, Squirrelfish и V8 идет много капитала C, капитала S компьютерных наук. Рассматривает ли какой-либо из этих проектов (или других) производительность операций DOM или они связаны исключительно с вычислениями Javascript?
2 ответа
На производительность чистых операций DOM (getElementById/Tagname/Selector, nextChild и т. Д.) Это не влияет, так как они уже в чистом C++.
То, как усовершенствования механизма JS будут влиять на производительность, зависит в определенной степени от конкретных методов, используемых для повышения производительности, а также от производительности моста DOM->JS.
Примером первого является зависимость TraceMonkey от всех обращений к функциям JS. Поскольку трассировка эффективно указывает путь выполнения в любой точке, где JS выполняет поиск кода, который не может быть встроен (собственный код, истинная полиморфная рекурсия, обработчики исключений), трассировка прерывается, и выполнение возвращается к интерпретатору. Разработчики TM проделывают довольно большую работу, чтобы улучшить объем кода, который можно отследить (включая обработку полиморфной рекурсии), однако реально отследить вызовы произвольных собственных функций (например, DOM) невозможно. По этой причине я считаю, что они смотрят на реализацию большего количества DOM в JS (или, по крайней мере, в JS дружественной манере). Тем не менее, когда код отслеживается, TM может выполнять исключительно хорошую работу, поскольку он может понизить большинство "объектов" до более эффективных и / или собственных эквивалентов (например, использовать машинные целые числа вместо реализации JS Number).
JavaScriptCore (именно там живет SquirrelFish Extreme) и V8 имеют более схожий подход в том, что оба они JIT-код всего JS немедленно и создают код, который является более умозрительным (например, если вы делаете a*b
они генерируют код, который предполагает a
а также b
являются числами и возвращаются к исключительно медленному коду, если они не). Это имеет ряд преимуществ по сравнению с трассировкой, а именно то, что вы можете выполнять джит весь код независимо от того, вызывает ли он собственный код или генерирует исключения, и т. Д., Что означает, что один вызов DOM не приведет к снижению производительности. Недостатком является то, что весь код является спекулятивным - TM будет выполнять встроенные вызовы Math.floor и т. Д., Но лучшее, что может сделать JSC/V8, будет эквивалентно a=Math.floor(0.5)
-> a=(Math.floor == realFloor) ? inline : Math.floor(0.5)
это связано с затратами как на производительность, так и на использование памяти, а также неосуществимо. Причиной этого является предварительная компиляция, в то время как TM только код JIT после ее выполнения (и поэтому точно знает, какая функция была вызвана), JSC и V8 не имеют реальной основы для такого предположения и, в основном, не должны догадываться (и в настоящее время ни одна из них не пытается). этот). Единственное, что V8 и JSC делают, чтобы попытаться компенсировать эту проблему, это отследить то, что они видели в прошлом, и включить это в путь исполнения, оба используют комбинацию методов для этого кеширования, особенно в горячих случаях. они перезаписывают небольшие части потока инструкций, а в других случаях они хранятся вне кэша каналов. Вообще говоря, если у вас есть код, который идет
a.x * a.y
V8 и JSC будут проверять "неявный тип" / "Структура" дважды - один раз для каждого доступа, а затем проверять, что a.x
а также a.y
оба числа, тогда как TM будет генерировать код, который проверяет тип a
только один раз и может (при прочих равных условиях) просто размножаться a.x
а также a.y
без проверки, что они числа.
Если вы смотрите на чистую скорость выполнения, в настоящее время есть что-то смешанное, поскольку каждый движок, кажется, лучше выполняет определенные задачи, чем другие - TraceMonkey выигрывает во многих тестах по чистой математике, V8 выигрывает в сильно динамичных случаях, JSC выигрывает, если есть смесь. Конечно, хотя сегодня это действительно так, завтра может и не быть, поскольку мы все усердно работаем над повышением производительности.
Другой проблемой, которую я упомянул, была стоимость привязки DOM<->JS - это может сыграть очень важную роль в производительности сети, лучшим примером этого является Safari 3.1/2 против Chrome в тесте Dromaeo. Chrome основан на ветке Safari 3.1/2 WebKit, поэтому можно с уверенностью предположить, что производительность DOM одинакова (разница в компиляторе может вызвать некоторую разницу). В этом тесте Safari 3.1/2 на самом деле превосходит Chrome, несмотря на то, что JS-движок явно намного медленнее, в основном это связано с более эффективными связями между JSC/WebCore (dom/render /etc из WebKit) и V8/WebCore
В настоящее время просмотр привязок DOM к TM кажется несправедливым, поскольку они не выполнили всю работу, которую хотят (увы), поэтому просто прибегают к помощи переводчика:-(
..
Errmmm, это продолжалось несколько дольше, чем предполагалось, поэтому короткий ответ на оригинальный вопрос "это зависит":D
Это чистый JavaScript. Если конкретный вызов метода DOM не реализован в JS, они будут иметь небольшой эффект (не говоря уже о том, что не было сделано работы по сокращению накладных расходов на такие вызовы).
Оптимизация DOM - это всего лишь "первоисточник рыб- пауков обезьян- белок". В игру вступают макеты и даже механизмы рендеринга, и у каждого браузера есть своя собственная стратегия реализации и оптимизации.