Но почему браузер DOM все еще так медленно после 10 лет усилий?
Веб-браузер DOM существует с конца 90-х годов, но он остается одним из самых больших ограничений производительности/скорости.
У нас есть одни из самых ярких в мире умов от Google, Mozilla, Microsoft, Opera, W3C и других организаций, работающих над веб-технологиями для всех нас, поэтому, очевидно, это не просто "О, мы не сделали", t оптимизировать его ".
Мой вопрос, если я буду работать над той частью веб-браузера, которая специально занимается этим, почему мне так сложно заставить его работать быстрее?
Мой вопрос не с запросом what заставляет его медленно, он спрашивает why не стало быстрее?
Это похоже на то, что происходит в другом месте, например, JS-двигатели с производительностью, близкой к коду С++.
Пример быстрого script:
for (var i=0;i<=10000;i++){
someString = "foo";
}
Пример медленного из-за DOM:
for (var i=0;i<=10000;i++){
element.innerHTML = "foo";
}
Некоторые детали по запросу:
После заметок на стенде, похоже, что это не неразрешимая медленная проблема, но часто используется неправильный инструмент, и используемый инструмент зависит от того, что вы делаете в кросс-браузере.
Похоже, что эффективность DOM сильно варьируется между браузерами, но моя первоначальная презумпция того, что dom медленная и неразрешимая, кажется, ошибочна.
Я запускал тесты против Chrome, FF4 и IE 5-9, вы можете видеть операции в секунду в этой диаграмме:
![enter image description here]()
Chrome работает быстро, когда вы используете DOM API, но значительно медленнее, используя оператор .innerHTML(на 1000 раз медленнее), однако FF хуже, чем Chrome в некоторых областях (например, тест append гораздо медленнее, чем Chrome), но тест InnerHTML работает намного быстрее, чем хром.
Кажется, что IE действительно ухудшается при использовании DOM append и лучше в InnerHTML, когда вы продвигаетесь через версии начиная с версии 5.5 (т.е. 73OP/сек в IE8 теперь на 51 ops/sec в IE9).
У меня есть тестовая страница здесь:
http://jsperf.com/browser-dom-speed-tests2
Интересно, что кажется, что разные браузеры кажутся разными проблемами при создании DOM. Почему здесь существует такое несоответствие?
Ответы
Ответ 1
Когда вы что-то изменяете в DOM, оно может иметь множество побочных эффектов, связанных с перерасчетами макетов, таблиц стилей и т.д.
Это не единственная причина: когда вы устанавливаете element.innerHTML=x
, вы больше не имеете дело с обычными переменными "хранить значение здесь", а со специальными объектами, которые обновляют загрузку внутреннего состояния в браузере при их установке.
Полные последствия element.innerHTML=x
огромны. Краткий обзор:
- parse
x
как HTML
- запрашивать расширения браузера для разрешения
- уничтожить существующие дочерние узлы
element
- создать дочерние узлы
- recompute styles, которые определяются в терминах отношений родитель-потомок
- пересчитать физические размеры элементов страницы
- уведомить расширения браузера об изменении
- обновить переменные Javascript, которые обрабатывают реальные узлы DOM
Все эти обновления должны проходить через API, который соединяет Javascript и движок HTML. Одной из причин того, что Javascript так быстро в наши дни является то, что мы скомпилируем его на более быстрый язык или даже машинный код, возникают массы оптимизаций, потому что поведение значений хорошо определено. При работе с API DOM возможно none. Ускорение в другом месте оставило DOM позади.
Ответ 2
Во-первых, все, что вы делаете с DOM, может быть видимым пользователем. Если вы измените DOM, браузер должен снова выложить все. Это может быть быстрее, если браузер кэширует изменения, а затем выкладывает только каждые X ms (при условии, что он этого не делает), но, возможно, нет такого огромного спроса на эту функцию.
Во-вторых, innerHTML - не простая операция. Это грязный хак, который MS нажал, и другие браузеры приняты потому, что это так полезно; но он не является частью стандарта (IIRC). Используя innerHTML, браузер должен проанализировать строку и преобразовать ее в DOM. Разбор трудно.
Ответ 3
Оригинальным автором теста является Hixie (http://nontroppo.org/timer/Hixie_DOM.html).
Этот вопрос обсуждался на fooobar.com/info/135617/... и Connect (ошибка-трекер). С IE10 проблема решена. Решив, я имею в виду, что они частично перешли на другой способ обновления DOM.
Команда IE, похоже, обрабатывает обновление DOM, подобное команде Excel-macros в Microsoft, где она считает, что плохая практика обновляет живые ячейки на листе. Вы, разработчик, должны выполнять тяжелую работу в режиме офлайн, а затем обновлять живую команду в пакетном режиме. В IE вы должны делать это с использованием фрагмента документа (в отличие от документа). С новыми новыми стандартами ECMA и W3C документы-фрагменты обесцениваются. Таким образом, команда IE сделала довольно приятную работу, чтобы сдержать проблему.
Ему потребовалось несколько недель, чтобы разделить его на с ~ 42 000 мс в IE10-ConsumerPreview до ~ 600 мс IE10-RTM. Но потребовалось много усилий, чтобы убедить их, что это проблема. Их утверждение состояло в том, что нет реального примера, который содержит 10 000 обновлений для каждого элемента. Поскольку масштабы и характер богатых интернет-приложений (RIA) не могут быть предсказаны, важно иметь производительность, близкую к другим браузерам лиги. Вот еще один пример DOM по OP на MS Connect (в комментариях):
Когда я просматриваю http://nontroppo.org/timer/Hixie_DOM.html, требуется ~ 680 мс, и если я сохраню страницу и запускаю ее локально, она займет ~ 350 мс!
То же самое происходит, если я использую событие button-onclick для запуска script(вместо нагрузки на тело). Сравните эти две версии:
jsfiddle.net/uAySs/< - body onload
против.
jsfiddle.net/8Kagz/< - кнопка onclick
Почти 2x разница..
По-видимому, основное поведение onload и onclick также меняется. В будущих обновлениях он может стать еще лучше.