Reputation: 48278
I monitored the page load time for my site in chrome (using Timeline), and got hundreds of warnings that said "Forced synchronous layout is a possible performance bottleneck" for all the Raphael.js calls:
I don't know how to fix this :/
Any ideas on where to look?
Here's how I normally create text on the page:
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";
Thanks!
Upvotes: 1
Views: 1016
Reputation: 48278
Problem:
The problem is called "Layout Thrashing" and is happening because the browser was trying to immediately refresh / redraw after every Raphael drawing.
For example, this would cause layout thrashing:
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;
"In this simple example, the browser will update the whole layout twice. This is because after setting the first element's width, you are asking to retrieve an element's width. When retrieving the css property, the browser know's it needs updated data, so it then goes and updates the whole DOM tree in memory. Only then, it will continue to the next line, which will soon after cause another update because of the same reasons."
This can simply be fixed by changing around the order of the code, as so :
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;
"Now, the browser will update both properties one after the other without updating the tree."
Sources:
https://blog.idrsolutions.com/2014/08/beware-javascript-layout-thrashing/
http://www.codeproject.com/Articles/758790/Debugging-and-solving-the-Forced-Synchronous-Layou
https://dev.opera.com/articles/efficient-javascript/?page=3#reflow
Soultion:
One way to fix this (a really quick and dirty way) is to hide() the div you are drawing to, then, when you are finished, show() it. I have had hit and miss results with this with Raphael, and it has been drawing strange this way. However it is faster...
"When an element has its display style set to none, it will not need to repaint, even if its contents are changed, since it is not being displayed. This can be used as an advantage. If several changes need to be made to an element or its contents, and it is not possible to combine these changes into a single repaint, the element can be set to display:none, the changes can be made, then the element can be set back to its normal display."
Here's the results:
This way worked for me!
Upvotes: 6