大型应用的回流/布局性能 [英] Reflow/Layout performance for large application

查看:102
本文介绍了大型应用的回流/布局性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



有时候,它可以加载DOM中的很多对象,应用程序变慢。我使用Chrome开发人员工具分析器来查看这个时间花费在哪里(Chrome一旦编译了应用程序,即没有GWT开销),很明显方法 getAbsoluteLeft()/ getBoundingClientRect()消耗主要



以下是Chrome(com.google.gwt.dom.client.DOMImplStandardBase)下使用的实现:

  private static native ClientRect getBoundingClientRect(Element element)/ *  -  {
return element.getBoundingClientRect&& element.getBoundingClientRect();
} - * /;

@Override
public int getAbsoluteLeft(Element elem){
ClientRect rect = getBoundingClientRect(elem);
return rect!= null? rect.getLeft()
+ elem.getOwnerDocument()。getBody()。getScrollLeft()
:getAbsoluteLeftUsingOffsets(elem);
}

这对我来说很有意义,因为DOM中的元素越多越多可能需要计算绝对位置的时间。但是令人沮丧的是,因为有时您只知道应用程序的一个子部分已经改变,而这些方法仍然需要时间来计算绝对定位,这可能是因为它不必要地重新检查了一大堆DOM元素。我的问题不一定是GWT,因为它是一个浏览器/ javascript相关的问题:



有没有任何已知的解决方案来改善GWT getAbsoluteLeft / javascript getBoundingClientRect问题为大DOM元素应用程序?



我没有在互联网上找到任何线索,但我想到了解决方案,如:




  • (减少这些方法的调用次数:-) ...

  • 通过iframe隔离部分DOM,为了减少浏览器要获得绝对位置的元素数量(尽管它会使困难的组件进行通信...)

  • 在同样的想法中,可能会有一些css属性(overflow ,位置?)或一些html元素(如iframe),告诉浏览器跳过整个dom的一部分,或者只是帮助浏览器更快地获得绝对位置。



编辑



使用Chrome TimeLine调试器,并执行一个具体的动作,而DOM中有很多元素,我有平均的表现:




  • 重新计算样式:几乎为零

  • 涂料:近1 ms

  • 布局:近900ms



Layout通过getBoundingClientRect方法需要900ms。此页面列表触发布局的所有方法WebKit ,包括getBoundingClientRect ...



由于我在dom中有很多元素不受我的操作影响,我假设 layout 正在整个DOM中进行重新计算,而 paint 可以通过css属性/ DOM树缩小其范围(例如,可以通过Mozbug中的MozAfterPaintEvent查看)。



除了分组和调用更少的触发布局的方法,有关如何减少布局时间的线索?



一些相关文章:




解决方案

我终于解决了我的问题: getBoundingClientRect 触发整个布局事件在应用程序中,这是通过繁重的CSS规则进行了很多次。



其实布局时间并不直接与DOM中的元素成正比。你可以用轻的样式绘制数十万个,而布局只需要2ms。



在我的情况下,我有两个CSS选择器和一个背景图片,它们匹配了数十万的DOM元素,这在布局过程中花费了大量的时间。通过简单地删除这些CSS规则,我将布局时间从900ms缩短到2ms。


I am using GWT to build a HTML application where the performance is correct in general.

Sometimes, it can load many objects in the DOM and the application becomes slow. I used Chrome Developer Tools Profiler to see where that time was spent (under Chrome once the app is compiled ie no GWT overhead) and it is clear that the methods getAbsoluteLeft()/getBoundingClientRect() consume the major part of this time.

Here is the implementation used under Chrome (com.google.gwt.dom.client.DOMImplStandardBase) :

private static native ClientRect getBoundingClientRect(Element element) /*-{
  return element.getBoundingClientRect && element.getBoundingClientRect();
}-*/;

@Override
public int getAbsoluteLeft(Element elem) {
  ClientRect rect = getBoundingClientRect(elem);
  return rect != null ? rect.getLeft()
     + elem.getOwnerDocument().getBody().getScrollLeft()
     : getAbsoluteLeftUsingOffsets(elem);
}

This makes sense to me, as the more elements in the DOM, the more time it may take to calculate absolute positions. But it is frustrating because sometimes you know just a subpart of your application has changed whereas those methods will still take time to calculate absolute positioning, probably because it unnecessarily recheck a whole bunch of DOM elements. My question is not necessarily GWT oriented as it is a browser/javascript related problem :

Is there any known solution to improve GWT getAbsoluteLeft/javascript getBoundingClientRect problem for large DOM elements application ?

I did not find any clues on the internet, but I thought about solution like :

  • (reducing number of calls for those methods :-) ...
  • isolate part of the DOM through iframe, in order to reduce the number of elements the browser has to evaluate to get an absolute position (although it would make difficult components to communicate ...)
  • in the same idea, there might be some css property (overflow, position ?) or some html element (like iframe) which tell the browser to skip a whole part of the dom or simply help the browser to get absolute position faster

EDIT :

Using Chrome TimeLine debugger, and doing a specific action while there are a lot of elements in the DOM, I have the average performance :

  • Recalculate style : nearly zero
  • Paint : nearly 1 ms
  • Layout : nearly 900ms

Layout takes 900ms through the getBoundingClientRect method. This page list all the methods triggering layout in WebKit, including getBoundingClientRect ...

As I have many elements in the dom that are not impacted by my action, I assume layout is doing recalculation in the whole DOM whereas paint is able through css property/DOM tree to narrow its scope (I can see it through MozAfterPaintEvent in firebug for example).

Except grouping and calling less the methods that trigger layout, any clues on how to reduce the time for layout ?

Some related articles :

解决方案

I finally solve my problem : getBoundingClientRect was triggering a whole layout event in the application, which was taking many times through heavy CSS rules.

In fact, layout time is not directly proportional to the number of elements in the DOM. You could draw hundred thousands of them with light style and layout will take only 2ms.

In my case, I had two CSS selectors and a background image which were matching hundred thousands of DOM elements, and that was consuming a huge amount of time during layout. By simply removing those CSS rules, I reduce the layout time from 900ms to 2ms.

这篇关于大型应用的回流/布局性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆