Комментарии 23
А почему ни одна современная UI библиотека, в которой задротствуют на тему производительности не использует DocumentFragment?
Для того, чтобы ответить на этот вопрос, мне пришлось бы изучить каждую «современную UI библиотека, в которой задротствуют на тему производительности». Без этого я вообще не уверен, что ваше утверждение истинно.
В React и других фреймворках, основанных на Virtual DOM, фрагменты попросту некуда приткнуть из-за принципиального отличия алгоритмов. В Polymer используется Shadow DOM, который, по сути, является надстройкой над фрагментами, но это никак не связано с производительностью и никак не мешает использовать обычные фрагменты поверх этого. Если вас интересуют ещё какие-то библиотеки, то вам следует обратиться к кому-то, кто в них компетентен.
В 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
Можно вместо того чтобы рендерить в дом элемент, рендерить виртуальные ноды во фрагмент, а потом вставлять в дом элемент.
А ещё можно открыть исходники хрома и понять что на самом деле происходит при вставке элементов:
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, а сейчас наверное уже все повыкидывали этот хак :)
Кстати, ещё интересный исторический факт — это то что в старых иешках и даже в старых версиях 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
Скорее всего у вас проблемы с производительности были из-за чего-то другого.
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
Если мне не изменяет память, jQuery где-то использовала.
UPD. Я прав: github.com/jquery/jquery/search?q=createDocumentFragment&unscoped_q=createDocumentFragment
UPD. Я прав: github.com/jquery/jquery/search?q=createDocumentFragment&unscoped_q=createDocumentFragment
Мне кажется, было бы правильнее пометить статью двумя тегами: XML, DOM. Было бы интересно увидеть XML, полученный в результате выполнения кода, приведенного в разделе Зачем нужен.
Спасибо за полезную информацию
Статья отличная, но пункт 2 касательно производительности весьма сомнителен. Прогнал тест на Chrome предоставленный в статье. Обычная вставка «по очереди» 60мс, Вставка через documentFragment 58мс :-). Сомнительное ускорение.
Надо кнопки не по очереди нажимать, а перезагружать страницу перед каждым нажатием, иначе происходить оптимизация после каждого нажатия. Можно легко проверить, нажать вначале метод documentFragment который покажет около 60мс (у меня) и после вставку «по очереди» не перезагружая страницу, выполнится уже за 45мс (у меня) — сюрприз! — быстрее чем documentFragment.
Про удобство использования полностью согласен, одна строка вставляет все элементы вместо работы в цикле.
Про template тоже отличный пример, не работал с ним, был бы весьма полезен, если бы не React ;-).
За статью спасибо.
Надо кнопки не по очереди нажимать, а перезагружать страницу перед каждым нажатием, иначе происходить оптимизация после каждого нажатия. Можно легко проверить, нажать вначале метод documentFragment который покажет около 60мс (у меня) и после вставку «по очереди» не перезагружая страницу, выполнится уже за 45мс (у меня) — сюрприз! — быстрее чем documentFragment.
Про удобство использования полностью согласен, одна строка вставляет все элементы вместо работы в цикле.
Про template тоже отличный пример, не работал с ним, был бы весьма полезен, если бы не React ;-).
За статью спасибо.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
DocumentFragment: что это такое и как с ним (не) бороться