Браузеры анализируют JavaScript при каждой загрузке страницы?
Браузеры (IE и Firefox) анализируют связанные файлы javascript при каждом обновлении страницы?
Они могут кэшировать файлы, поэтому я предполагаю, что они не будут пытаться загружать их каждый раз, но, поскольку каждая страница по сути отдельна, я ожидаю, что они разрушат любой старый код и проведут его повторный анализ.
Это неэффективно, хотя и вполне понятно, но мне интересно, достаточно ли умны современные браузеры, чтобы избежать шага парсинга внутри сайтов. Я имею в виду случаи, когда сайт использует библиотеку javascript, например ExtJS или jQuery и т. Д.
6 ответов
Это детали, которые мне удалось откопать. Прежде всего, стоит отметить, что, хотя обычно считается, что JavaScript интерпретируется и выполняется на виртуальной машине, в действительности это не так с современными интерпретаторами, которые стремятся скомпилировать исходный код непосредственно в машинный код (за исключением IE).
Хром: двигатель V8
V8 имеет кеш компиляции. Это хранит скомпилированный JavaScript с использованием хэша источника для до 5 сборок мусора. Это означает, что два идентичных фрагмента исходного кода будут совместно использовать запись кэша в памяти независимо от того, как они были включены. Этот кэш не очищается при перезагрузке страниц.
Обновление - 19/03/2015
Команда Chrome выпустила подробности о своих новых методах потоковой передачи и кэширования JavaScript.
- Скрипт Потоковое
Скрипт потоковой передачи оптимизирует синтаксический анализ файлов JavaScript. [...]
Начиная с версии 41, Chrome анализирует асинхронные и отложенные сценарии в отдельном потоке, как только начинается загрузка. Это означает, что синтаксический анализ может завершиться всего за миллисекунды после завершения загрузки, что приводит к загрузке страниц на 10% быстрее.
- Кэширование кода
Обычно движок V8 компилирует JavaScript-код страницы при каждом посещении, превращая его в инструкции, понятные процессору. Этот скомпилированный код затем отбрасывается, как только пользователь уходит со страницы, так как скомпилированный код сильно зависит от состояния и контекста компьютера во время компиляции.
В Chrome 42 реализован продвинутый метод хранения локальной копии скомпилированного кода, так что когда пользователь возвращается на страницу, все этапы загрузки, анализа и компиляции могут быть пропущены. При любой загрузке страницы это позволяет Chrome избегать около 40% времени компиляции и экономит драгоценную батарею на мобильных устройствах.
Опера: Каракан Двигатель
На практике это означает, что всякий раз, когда программа сценария собирается скомпилироваться, исходный код которой идентичен исходному коду какой-либо другой программы, которая была недавно скомпилирована, мы повторно используем предыдущий вывод компилятора и полностью пропускаем этап компиляции. Этот кэш весьма эффективен в типичных сценариях просмотра, когда страница загружается страница за страницей с одного и того же сайта, например, в разные новостные статьи из службы новостей, поскольку каждая страница часто загружает одну и ту же, иногда очень большую, библиотеку сценариев.
Поэтому JavaScript перезагружается при перезагрузке страницы, два запроса к одному и тому же сценарию не приведут к повторной компиляции.
Firefox: SpiderMonkey Engine
SpiderMonkey использует Nanojit
как его родной сервер, JIT-компилятор. Процесс компиляции машинного кода можно увидеть здесь. Короче говоря, похоже, что он перекомпилирует скрипты по мере их загрузки. Тем не менее, если мы поближе познакомимся с внутренними Nanojit
мы видим, что монитор более высокого уровня jstracer
, который используется для отслеживания компиляции может переходить через три этапа во время компиляции, обеспечивая преимущество для Nanojit
:
Начальное состояние монитора трассировки - мониторинг. Это означает, что spidermonkey интерпретирует байт-код. Каждый раз, когда spidermonkey интерпретирует байт-код обратного перехода, монитор записывает, сколько раз было выполнено переключение значения счетчика целевой программы перехода (ПК). Этот номер называется счетчиком обращений для ПК. Если число попаданий определенного ПК достигает порогового значения, цель считается горячей.
Когда монитор решает, что целевой ПК горячий, он просматривает хеш-таблицу фрагментов, чтобы увидеть, есть ли фрагмент, содержащий нативный код для этого целевого ПК. Если он находит такой фрагмент, он переходит в режим выполнения. В противном случае он переходит в режим записи.
Это означает, что для hot
фрагменты кода нативный код кешируется. Это означает, что не нужно будет перекомпилировать. Не ясно, что эти хэшированные собственные разделы сохраняются между обновлениями страниц. Но я бы предположил, что они есть. Если кто-то может найти подтверждающие доказательства для этого, то отлично.
РЕДАКТИРОВАТЬ: Было отмечено, что разработчик Mozilla Борис Збарский заявил, что Gecko еще не кеширует скомпилированные скрипты. Взято из этого ТАКОГО ответа.
Safari: JavaScriptCore / SquirelFish Engine
Я думаю, что лучший ответ для этой реализации уже был дан кем-то еще.
В настоящее время мы не кэшируем байт-код (или собственный код). Это
вариант, который мы рассмотрели, однако, в настоящее время генерация кода является
тривиальная часть времени выполнения JS (< 2%), поэтому мы не преследуем
это на данный момент.
Это написал Мачей Стаховяк, ведущий разработчик Safari. Поэтому я думаю, что мы можем принять это за правду.
Я не смог найти другую информацию, но вы можете прочитать больше об улучшениях скорости последней SquirrelFish Extreme
Двигатель здесь, или просмотреть исходный код здесь, если вы чувствуете себя авантюрным.
IE: Chakra Engine
В этом поле нет текущей информации о JavaScript Engine (Chakra) в IE9. Если кто-нибудь что-то знает, пожалуйста, прокомментируйте.
Это довольно неофициально, но для более старых реализаций движка IE Эрик Липперт ( разработчик JScript для MS) заявляет в своем блоге, что:
JScript Classic действует как скомпилированный язык в том смысле, что перед запуском любой программы JScript Classic мы полностью проверяем синтаксис кода, генерируем полное дерево разбора и генерируем байт-код. Затем мы запускаем байт-код через интерпретатор байт-кода. В этом смысле JScript столь же "скомпилирован", как и Java. Разница в том, что JScript не позволяет вам сохранять или проверять наш проприетарный байт-код. Кроме того, байт-код гораздо более высокого уровня, чем байт-код JVM - язык байт-кода JScript Classic - это не что иное, как линеаризация дерева разбора, тогда как байт-код JVM явно предназначен для работы на низкоуровневой машине стека.
Это говорит о том, что байт-код не сохраняется никоим образом, и, следовательно, байт-код не кэшируется.
Опера делает это, как упоминалось в другом ответе. ( источник)
Firefox (движок SpiderMonkey) не кэширует байт-код. ( источник)
WebKit (Safari, Konqueror) не кэширует байт-код. ( источник)
Я не уверен насчет IE[6/7/8] или V8 (Chrome), я думаю, что IE может выполнять какое-то кэширование, а V8 - нет. IE является закрытым исходным кодом, поэтому я не уверен, но в V8 может не иметь смысла кэшировать "скомпилированный" код, так как они компилируются прямо в машинный код.
Насколько я знаю, только Opera кэширует разобранный JavaScript. Смотрите раздел "Кэшированные скомпилированные программы" здесь.
Ничего не стоит, что Google Dart явно решает эту проблему с помощью "Снимков" - цель состоит в том, чтобы ускорить инициализацию и время загрузки путем загрузки предварительно отредактированной версии кода.
InfoQ имеет хорошую рецензию @ http://www.infoq.com/articles/google-dart
Браузер определенно использует кэширование, но да, браузеры анализируют JavaScript каждый раз, когда страница обновляется. Потому что всякий раз, когда страница загружается браузером, она создает 2 дерева: 1. Дерево контента и 2. Дерево рендеринга.
Это дерево рендеринга состоит из информации о визуальном расположении элементов dom. Таким образом, всякий раз, когда страница загружается, javascript анализируется, и любые динамические изменения javascript будут такими, как позиционирование элемента dom, элемент show/hide, элемент add/remove заставит браузер воссоздать дерево рендеринга. Но современные броузеры, такие как FF и chrome, обрабатывают это немного по-разному, они имеют концепцию инкрементального рендеринга, поэтому всякий раз, когда js выполняет динамические изменения, как упомянуто выше, только эти элементы будут визуализироваться и перерисовываться заново.
Я думаю, что правильный ответ будет "не всегда". Из того, что я понимаю, и браузер, и сервер играют роль в определении того, что кэшируется. Если вам действительно нужно каждый раз перезагружать файлы, я думаю, вы сможете настроить это из Apache (например). Конечно, я предполагаю, что браузер пользователя может быть настроен на игнорирование этого параметра, но это, вероятно, маловероятно.
Так что я бы предположил, что в большинстве практических случаев сами файлы javascript кэшируются, но динамически интерпретируются при каждой загрузке страницы.