Pull to refresh

Comments 23

А почему ни одна современная UI библиотека, в которой задротствуют на тему производительности не использует DocumentFragment?
Для того, чтобы ответить на этот вопрос, мне пришлось бы изучить каждую «современную UI библиотека, в которой задротствуют на тему производительности». Без этого я вообще не уверен, что ваше утверждение истинно.

В React и других фреймворках, основанных на Virtual DOM, фрагменты попросту некуда приткнуть из-за принципиального отличия алгоритмов. В Polymer используется Shadow DOM, который, по сути, является надстройкой над фрагментами, но это никак не связано с производительностью и никак не мешает использовать обычные фрагменты поверх этого. Если вас интересуют ещё какие-то библиотеки, то вам следует обратиться к кому-то, кто в них компетентен.
> В React и других фреймворках, основанных на Virtual DOM, фрагменты попросту некуда приткнуть из-за принципиального отличия алгоритмов

Можно вместо того чтобы рендерить в дом элемент, рендерить виртуальные ноды во фрагмент, а потом вставлять в дом элемент.

А ещё можно открыть исходники хрома и понять что на самом деле происходит при вставке элементов:

chromium.googlesource.com/chromium/blink/+/master/Source/core/dom/DocumentFragment.h#33
chromium.googlesource.com/chromium/blink/+/master/Source/core/dom/ContainerNode.cpp#166
chromium.googlesource.com/chromium/blink/+/master/Source/core/dom/ContainerNode.cpp#66
Да, технически, я могу открыть исходники хрома. Но поскольку в последний раз я брал в руки C++ лет пять назад, когда делал другу какую-то лабу, и до этого ничего сложнее тех же лаб на нём не писал, я примерно с тем же успехом могу открыть тибетскую Книгу Мёртвых на языке оригинала.

Если вы хотите что-то сказать, скажите, пожалуйста, прямым текстом. Я недостаточно умный, чтобы со мной имело смысл вести сократическую беседу.
Использование фрагментов добавляет лишь дополнительный оверхэд от того что приходится создавать этот фрагмент, вставлять в него и потом перебрасывать из него в нужный элемент. Никакого рефлоу не произойдёт от вставки элементов в дом узлы, которые находятся в документе, рефлоу будет отложен до того момента когда кто-нибудь не начнёт читать свойства, которые зависят от вычислений производимых во время рефлоу.
Да, похоже, что касается свежего Хрома, вы правы. Внесу информацию в статью. Но в Firefox (свежая и не очень свежая версии) бенчмарк показывает выгоду от использования DocumentFragment.
Во всех браузерах такое поведение уже очень давно. Единственная ситуация в которой с фрагментом должно быть быстрее — это бэнчмарки с плоскими листами на 10к элементов запущеные в браузере с экстеншенами типа адблока.
Без адблока в FF фрагмент всё равно работает быстрее, хотя преимущество и не такое впечатляющее.

Кстати, а в масштабах веба «очень давно» — это сколько? =)
Даже не знаю точной даты, но точно ещё до того как хром форкнул вебкит.

Кстати, ещё интересный исторический факт — это то что в старых иешках и даже в старых версиях Edge'а, вставка элементов до того как у них отрендерены чилдрены была быстрее чем рендер вне документа и вставка.

Сначало случайно обнаружили это в эпоху когда пытались создать наиболее производительный vdom алгоритм github.com/localvoid/vdom-benchmark/issues/15#issuecomment-71692148, потом реактовцы добавили эту оптимизиацию github.com/sophiebits/innerhtml-vs-createelement-vs-clonenode, а сейчас наверное уже все повыкидывали этот хак :)
Из личной практики — вставка тысяч svg-узлов через фрагмент действительно оказывалась намного быстрее, чем россыпью. Не помню уже точные цифры, но в разы.
Единственное отличие во вставке будет только в случае если где-то сверху висит MutationObserver[1], тогда на каждом вызове `insertBefore()` будет вызываться `dispatchSubtreeModifiedEvent()`[2] и генерировать эвент. Но даже в таком случае разница в производительности будет практически незаметна.

Скорее всего у вас проблемы с производительности были из-за чего-то другого.

1. chromium.googlesource.com/chromium/blink/+/master/Source/core/dom/Node.cpp#1989
2. chromium.googlesource.com/chromium/blink/+/master/Source/core/dom/ContainerNode.cpp#242
Фильтры в SVG пересчитывались. Кроме того, не Хромом единым…
Очень любопытно было бы взглянуть на пример и в каком браузере это проявлялось. Чтоб вставка нодов в свг триггерила репэйнт в любом браузере — как-то не особо верится.
Ключевые слова: «современная» и «UI библиотека» :) jQuery — это обёртка нормализующая работу императивного DOM api на старых браузерах.
Мне кажется, было бы правильнее пометить статью двумя тегами: XML, DOM. Было бы интересно увидеть XML, полученный в результате выполнения кода, приведенного в разделе Зачем нужен.
Ну… Там получится

<div>
    <div></div>
    <div></div>
</div>


Или я неправильно понял вопрос?
Я правильно понял: при формировании XML (сериализации) DocFragment не добавляет собственные теги?
Статья отличная, но пункт 2 касательно производительности весьма сомнителен. Прогнал тест на Chrome предоставленный в статье. Обычная вставка «по очереди» 60мс, Вставка через documentFragment 58мс :-). Сомнительное ускорение.

Надо кнопки не по очереди нажимать, а перезагружать страницу перед каждым нажатием, иначе происходить оптимизация после каждого нажатия. Можно легко проверить, нажать вначале метод documentFragment который покажет около 60мс (у меня) и после вставку «по очереди» не перезагружая страницу, выполнится уже за 45мс (у меня) — сюрприз! — быстрее чем documentFragment.

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

Про template тоже отличный пример, не работал с ним, был бы весьма полезен, если бы не React ;-).

За статью спасибо.
Sign up to leave a comment.

Articles