Браузеры анализируют JavaScript при каждой загрузке страницы?

190

Браузеры (IE и Firefox) анализируют связанные файлы javascript при каждом обновлении страницы?

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

Это неэффективно, хотя и вполне понятно, но мне интересно, достаточно ли умны современные браузеры, чтобы избежать шага парсинга внутри сайтов. Я имею в виду случаи, когда сайт использует библиотеку javascript, например ExtJS или jQuery и т. Д.

ajreal
источник
4
Мой 2c: я чувствую, что преимущества производительности при кэшировании анализируемых файлов Javascript слишком малы, чтобы это было значимой оптимизацией.
Итай Маман
2
Судя по моим оценкам, это может иметь значение. Например, время загрузки jQuery составляет около 30 мсек (на быстром настольном компьютере), из которых 20% только анализируют код в исполняемом представлении, а остальное выполняет его, то есть инициализирует объект jQuery в этом случае. Если вы работаете на мобильном телефоне и используете две или три библиотеки, эта задержка может иметь значение, поскольку выполнение JavaScript блокируется, а страница практически пуста до тех пор, пока каждый сценарий JS не будет загружен в память.
djjeck

Ответы:

338

Это детали, которые мне удалось откопать. Прежде всего, стоит отметить, что, хотя обычно считается, что JavaScript интерпретируется и запускается на виртуальной машине, в действительности это не так с современными интерпретаторами, которые склонны компилировать исходный код непосредственно в машинный код (за исключением IE).


Хром: двигатель V8

V8 имеет кеш компиляции. Это хранит скомпилированный JavaScript с использованием хэша источника для до 5 сборок мусора. Это означает, что два идентичных фрагмента исходного кода будут совместно использовать запись кэша в памяти независимо от того, как они были включены. Этот кэш не очищается при перезагрузке страниц.

Источник


Обновление - 19/03/2015

Команда Chrome выпустила подробности о своих новых методах потоковой передачи и кэширования JavaScript .

  1. Скрипт Потоковое

Скрипт потоковой передачи оптимизирует синтаксический анализ файлов JavaScript. [...]

Начиная с версии 41, Chrome анализирует асинхронные и отложенные сценарии в отдельном потоке, как только начинается загрузка. Это означает, что синтаксический анализ может завершиться всего за миллисекунды после завершения загрузки, что приводит к загрузке страниц на 10% быстрее.

  1. Кэширование кода

Обычно движок V8 компилирует JavaScript-код страницы при каждом посещении, превращая его в инструкции, понятные процессору. Этот скомпилированный код затем отбрасывается, как только пользователь уходит со страницы, так как скомпилированный код сильно зависит от состояния и контекста компьютера во время компиляции.

В Chrome 42 реализован продвинутый метод хранения локальной копии скомпилированного кода, так что, когда пользователь возвращается на страницу, все этапы загрузки, анализа и компиляции могут быть пропущены. При любой загрузке страницы это позволяет Chrome избегать около 40% времени компиляции и экономит драгоценную батарею на мобильных устройствах.


Опера: Каракан Двигатель

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

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

Источник


Firefox: движок SpiderMonkey

SpiderMonkey использует в Nanojitкачестве своего собственного back-end JIT-компилятор. Процесс компиляции машинного кода можно увидеть здесь . Короче говоря, похоже , что он перекомпилирует скрипты по мере их загрузки. Однако, если мы поближе рассмотрим внутреннее устройство, Nanojitмы увидим, что монитор более высокого уровня jstracer, который используется для отслеживания компиляции, может проходить три этапа во время компиляции, обеспечивая преимущество Nanojit:

Начальное состояние монитора трассировки - мониторинг. Это означает, что spidermonkey интерпретирует байт-код. Каждый раз, когда spidermonkey интерпретирует байт-код обратного перехода, монитор записывает, сколько раз было выполнено переключение значения счетчика целевой программы перехода (ПК). Этот номер называется счетчиком обращений для ПК. Если число попаданий определенного ПК достигает порогового значения, цель считается горячей.

Когда монитор решает, что целевой ПК горячий, он просматривает хеш-таблицу фрагментов, чтобы увидеть, есть ли фрагмент, содержащий нативный код для этого целевого ПК. Если он находит такой фрагмент, он переходит в режим выполнения. В противном случае он переходит в режим записи.

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

EDIT : Это было отмечено, что Mozilla разработчик Борис Збарский заявил , что Gecko не кэш скомпилирована сценарии еще . Взято из этого так ответ .


Safari: JavaScriptCore / SquirelFish Engine

Я думаю, что лучший ответ для этой реализации уже был дан кем-то еще .

В настоящее время мы не кэшируем байт-код (или собственный код). Это
вариант, который мы рассмотрели, однако в настоящее время генерация кода - это
тривиальная часть времени выполнения JS (<2%), поэтому
в данный момент мы не занимаемся этим.

Это написал Мацей Стаховяк , ведущий разработчик Safari. Поэтому я думаю, что мы можем принять это за правду.

Мне не удалось найти какую-либо другую информацию, но вы можете прочитать больше об улучшениях скорости последнего SquirrelFish Extremeдвижка здесь или просмотреть исходный код здесь, если вы чувствуете себя в авантюре.


IE: Chakra Engine

В этой области нет текущей информации о JavaScript Engine (Чакра) IE9. Если кто-нибудь что-то знает, пожалуйста, прокомментируйте.

Это вполне неофициальное, но для более старых реализаций двигателя в IE, Эрик Липперто ( разработчик МС JScript ) утверждает в блоге ответа здесь , что:

JScript Classic действует как скомпилированный язык в том смысле, что перед запуском любой программы JScript Classic мы полностью проверяем синтаксис кода, генерируем полное дерево разбора и генерируем байт-код. Затем мы запускаем байт-код через интерпретатор байт-кода. В этом смысле JScript ничуть не менее «скомпилирован», чем Java. Разница в том, что JScript не позволяет вам сохранять или проверять наш проприетарный байт-код . Кроме того, байт-код намного более высокого уровня, чем байт-код JVM - язык байт-кода JScript Classic - это не что иное, как линеаризация дерева разбора, тогда как байт-код JVM явно предназначен для работы на низкоуровневой машине стека.

Это говорит о том, что байт-код не сохраняется никоим образом, и, следовательно, байт-код не кэшируется.

Jivings
источник
10
+1, отличная рецензия. Тем не менее, что касается Firefox, смотрите этот вопрос StackOverflow, где Mozilla Developer Борис Збарский объясняет, что Gecko в настоящее время не делает этого.
cha0site
Спасибо, я видел это в своих путешествиях, но не смог найти никаких других подтверждающих доказательств. Я отредактирую ответ с этим.
Jivings
1
Обратите внимание, что то, что было сказано об IE, было сказано в 2003 году: первый выпуск механизма JS IE9 был в IE9 в 2011 году.
gsnedders
Кроме того, Opera кэширует байт-код JS больше, чем просто перезагружает. (Однако сгенерированный машинный код не кэшируется).
Гснеддерс
2
@Jivings Возьмите вышесказанное в качестве источника. (Я один из членов команды Carakan.)
gsnedders
12

Опера делает это, как упоминалось в другом ответе. ( источник )

Firefox (движок SpiderMonkey) не кэширует байт-код. ( источник )

WebKit (Safari, Konqueror) не кэширует байт-код. ( источник )

Я не уверен насчет IE [6/7/8] или V8 (Chrome), я думаю, что IE может выполнять какое-то кэширование, а V8 - нет. IE является закрытым исходным кодом, поэтому я не уверен, но в V8 может не иметь смысла кэшировать «скомпилированный» код, так как они компилируются прямо в машинный код.

cha0site
источник
1
IE6–8 почти наверняка не будет. IE9 может, но у меня нет никаких доказательств в любом случае. Скомпилированный JS, вероятно, нигде не кэшируется, потому что он довольно часто довольно большой.
gsnedders
@gsnedders: Я не уверен, что IE8 технически не может сделать это, кажется, что он слишком компилируется для байт-кода (не официальный, но закрытый), поэтому нет технической причины не кэшировать это. IE9, кажется, добавляет JIT для компиляции в нативный код.
cha0site
2
Байт-код был использован IE для ... навсегда. В IE8 нет ничего нового. Просто для интерпретатора просто так, что работа интерпретатора намного медленнее, чем время анализа, это совершенно не имеет значения. IE9 имеет совершенно новый (с нуля) движок JS, поэтому между ними ничего не следует.
gsnedders
3

Насколько я знаю, только Opera кеширует разобранный JavaScript. Смотрите раздел «Кэшированные скомпилированные программы» здесь .

gsnedders
источник
спасибо, у вас есть более подробная информация о других семействах браузеров?
ajreal
2

Ничего не стоит, что Google Dart явно решает эту проблему с помощью «моментальных снимков» - цель состоит в том, чтобы ускорить инициализацию и время загрузки путем загрузки предварительно отредактированной версии кода.

InfoQ имеет хорошую рецензию @ http://www.infoq.com/articles/google-dart

igrigorik
источник
0

Я думаю, что правильный ответ будет «не всегда». Из того, что я понимаю, и браузер, и сервер играют роль в определении того, что кэшируется. Если вам действительно нужно каждый раз перезагружать файлы, то, я думаю, вы сможете настроить это из Apache (например). Конечно, я предполагаю, что браузер пользователя может быть настроен на игнорирование этого параметра, но это, вероятно, маловероятно.

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

Захари Мюррей
источник
0

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

Это дерево рендеринга состоит из информации о визуальном расположении элементов dom. Таким образом, всякий раз, когда страница загружается, javascript анализируется, и любые динамические изменения в javascript будут такими, как позиционирование элемента dom, элемента show / hide, элемента add / remove, что заставит браузер воссоздать дерево рендеринга. Но современные броузеры, такие как FF и chrome, обрабатывают это немного по-разному, они имеют концепцию инкрементального рендеринга, поэтому всякий раз, когда js динамически изменяет, как упомянуто выше, это только заставит эти элементы рендерить и перерисовывать заново.

Abhidev
источник