Raphael.js вызывает узкое место принудительной синхронной компоновки

Я отслеживал время загрузки страницы для своего сайта в Chrome (используя Timeline) и получил сотни предупреждений о том, что «Принудительная синхронная компоновка является возможным узким местом в производительности» для всех вызовов Raphael.js:

введите здесь описание изображения

Я не знаю, как это исправить :/

Есть идеи, где искать?

Вот как я обычно создаю текст на странице:

currentPaper.text(width,height,"text")
            .attr({opacity:.8, fill: "#333", 'font-size':10})
            .id = "someId";

//Or, to be exact:

currentPaper.text(x_pos+(width/2), 
                  y_pos-height/8, 
                  lopaLayoutArray.x[s].y1[r].y2[x])
            .attr({opacity:.8, fill: "#333", 'font-size':(10*size)})
            .id = seatName+"-textLabel";

Спасибо!


person Katie    schedule 19.02.2015    source источник
comment
Можно ли включить больше вашего кода? трудно получить представление о том, что может пойти не так, только из одного утверждения   -  person konkked    schedule 19.02.2015
comment
@konkked Возможно! Я не уверен, где искать :( Я надеялся, что на временной шкале будет какой-то номер строки, но он просто указывает на библиотеку Raphael :/ Номер строки LopaView был строкой, которую я включил в вопрос. Вы знаете, что я должен искать?Есть ли функция Raphael.js, которую мне следует избегать?   -  person Katie    schedule 19.02.2015
comment
Единственное, о чем я могу думать, это то, что вы привязываете свою логику к будущим манипуляциям с результатами предыдущего макета dom, эффективно делая операцию синхронной, возможно, если бы вы указали, откуда вы взяли переменную lopaLayoutArray, это могло бы помочь выяснить, где именно это это происходит   -  person konkked    schedule 20.02.2015
comment
@konkked Хм .. да, я думаю, мне придется немного изменить свой код. Я провел некоторое исследование, и оно называется «Перебор макета», и именно это происходит: blog.idrsolutions.com/2014/08/   -  person Katie    schedule 20.02.2015
comment
Да, это то, что я говорил, за исключением того, что они действительно знают, о чем говорят, могу ли я преобразовать свой комментарий в ответ, даже если он не был на 100% правильным, имел основную идею, и никто другой не опубликовал ответ   -  person konkked    schedule 21.02.2015
comment
@konkked конечно, если хочешь! :)   -  person Katie    schedule 21.02.2015


Ответы (1)


Проблема:

Проблема называется «Переполнение макета» и возникает из-за того, что браузер пытался немедленно обновить/перерисовать после каждого рисунка Рафаэля.

Например, это может привести к сбою макета:

var a = document.getElementById('element-a');
var b = document.getElementById('element-b');

a.clientWidth = 100;
var aWidth = a.clientWidth;

b.clientWidth = 200;
var bWidth = b.clientWidth;

«В этом простом примере браузер дважды обновит весь макет. Это связано с тем, что после установки ширины первого элемента вы просите получить ширину элемента. При получении свойства css браузер знает, что ему нужны обновленные данные, поэтому он затем идет и обновляет все дерево DOM в памяти. Только после этого он переходит к следующей строке, которая вскоре вызовет другое обновление по тем же причинам».

Это можно просто исправить, изменив порядок кода, например:

var a = document.getElementById('element-a');
var b = document.getElementById('element-b');

a.clientWidth = 100;
b.clientWidth = 200;

var aWidth = a.clientWidth;
var bWidth = b.clientWidth;

«Теперь браузер будет обновлять оба свойства одно за другим без обновления дерева».

Источники:

https://blog.idrsolutions.com/2014/08/beware-javascript-layout-thrashing/

http://www.codeproject.com/Articles/758790/Debugging-and-solving-the-Forced-Synchronous-Layou

http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/

https://dev.opera.com/articles/efficient-javascript/?page=3#reflow

Душа:

Один из способов исправить это (действительно быстрый и грязный способ) — скрыть() элемент div, в который вы рисуете, а затем, когда вы закончите, показать() его. . У меня были удачные результаты с этим с Рафаэлем, и это было странно. Однако он работает быстрее...

«Когда стиль отображения элемента не установлен, его не нужно перерисовывать, даже если его содержимое изменено, поскольку он не отображается. Это можно использовать как преимущество. Если необходимо внести несколько изменений в элемент или его содержимое, и невозможно объединить эти изменения в одну перерисовку, для элемента можно установить значение display:none, можно внести изменения, после чего элемент может вернуться к своему обычному отображению».

Вот результаты:

введите здесь описание изображения

Этот способ работал для меня!

person Katie    schedule 20.02.2015
comment
Неважно, это намного лучший ответ, чем я мог бы дать - person konkked; 23.02.2015