大型应用程序的回流/布局性能

时间:2012-11-05 14:33:34

标签: javascript html gwt dom

我正在使用GWT构建一个性能正常的HTML应用程序。

有时,它可以在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相关的问题:

是否有任何已知的解决方案可以改善大型DOM元素应用程序的GWT getAbsoluteLeft / javascript getBoundingClientRect问题?

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

  • (减少对这些方法的调用次数:-) ...
  • 通过iframe隔离DOM的一部分,以减少浏览器必须评估的元素数量以获得绝对位置(尽管它会使难以通信的组件...)
  • 在同样的想法中,可能有一些css属性(溢出,位置?)或一些html元素(如iframe)告诉浏览器跳过dom的整个部分或者只是帮助浏览器更快地获得绝对位置

编辑:

使用Chrome TimeLine调试器,并在DOM中有很多元素时执行特定操作,我有平均性能:

  • 重新计算风格:接近零
  • 油漆:接近1毫秒
  • 布局:近900毫秒

布局需要900毫秒通过getBoundingClientRect方法。此页面列表all the methods triggering layout in WebKit,包括getBoundingClientRect ...

由于我在dom中有许多不受我的动作影响的元素,我假设布局在整个DOM中重新计算,而 paint 能够通过css属性/ DOM树缩小范围(我可以通过firebug中的MozAfterPaintEvent看到它)。

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

一些相关文章:

2 个答案:

答案 0 :(得分:6)

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

实际上,布局时间与DOM中的元素数量不成正比。您可以使用轻型风格绘制数十万个,布局仅需2ms。

就我而言,我有两个CSS选择器和一个背景图像,它们匹配了数十万个DOM元素,并且在布局过程中耗费了大量时间。通过简单地删除这些CSS规则,我将布局时间从900毫秒减少到2毫秒。

答案 1 :(得分:0)

您问题的最基本答案是使用lazy evaluation,也称为延迟评估。原则是你只评估一个新的位置,当它依赖的东西发生了变化时。它通常需要相当数量的代码来设置,但一旦完成就可以使用得更清晰。您可以对某些内容(例如窗口大小)进行一次分配,然后自动传播所有新值,并且只传播需要传播的值。