【问题标题】:GWT FlexTable performance and optimizationGWT FlexTable 性能和优化
【发布时间】:2011-11-09 12:52:35
【问题描述】:

我正在处理 GWT 项目,我们使用FlexTable 来显示一些数据。我知道我们可能应该使用CellTable,因为它具有更好的性能,但是 FlexTable 更容易设置样式(设置特定单元格的样式)并且更容易更新特定单元格。

为了接收我们正在使用 WebSockets 的表的更新。我们现在面临的问题是当每秒有超过 100 次更新通过 WebSockets 时,CPU 负载很高。来自 WebSocket 连接的每条消息都包含表中多个单元格的更新。所以在实践中,每秒应该在 FlexTable 中呈现超过 100 次更新。我的 3GHz i5 和 4GB RAM 的 CPU 负载约为 50%。如果我禁用数据的实际呈现(注释掉 setText() 方法调用),那么 CPU 负载会下降到 5-10%。所以我知道 DOM 更新是瓶颈,而不是代码的其他部分。

会不会更好

  1. 改用网格
  2. 切换到 CellTable(但是如何进行单个单元格更新)?
  3. 使用 JS/JSNI 来处理 DOM 而不是 FlexTable setText()

有没有更好的方法来实现表格并提高性能?

如果有人在使用 FlexTable 时遇到类似问题,我曾尝试用 Google 搜索,但发现只是普遍认为它很慢,没有具体内容。我们有纯粹用 JavaScript 完成的应用程序原型,同样每秒 100 次更新,CPU 负载约为 15%

更新
删除我们用来指示单元格值变化的 css 淡入淡出效果将 CPU 负载降低了约 10%。所以看来DOM不是唯一的问题。

【问题讨论】:

    标签: gwt flextable


    【解决方案1】:

    使用 CellTable 您必须重新渲染整个表格才能更新单个单元格。但是,这样的更新将是对 DOM 的一次更新。使用 FlexTable,即使您将所有更新批处理在一起,您也将执行一系列单独的 DOM 操作。因此,即使使用 CellTable 可能看起来效率低下,因为您冗余地更新了一些单元格,但仍然值得切换。 特别是在您更新的单元格数量接近单元格总数的情况下:批量更新 100 个更新,并在一次 DOM 写入中一次完成所有更新。

    我有一个应用程序,它的 CellTable 可以大到 30x100。它在任意单元格上具有任意样式,每个单元格都有复杂的内容(<img>、一些 <div>s 和一些文本),有时我需要更新单个单元格。在我的 macbook pro 开发模式下,重绘整个东西(以我的人类感知)是不明显的。

    如果您想要实时更新(例如每秒 100 次更新,因为它们会发生),那么我认为您可能想要一个不同的平台。甚至您的显示器也没有每秒刷新 100 次。

    【讨论】:

    • 在某些情况下,表中可能有 100 行,8 列。其中 6 列使用来自 WebSocket 提要的数据进行更新。在我们的模拟中,我们每 10 毫秒生成 1 条消息,总共每秒给我们 100 条消息,600 次 DOM 更新。这对 FlexTable 来说太难处理了。但是很容易注意到数据更新很快,因为它在不同的地方(单元格)更新。最小化它的一种方法是使用 JSNI 并用一个 DOM 更新替换整行。但是我不确定当代码从 Java 编译为 JavaScript 之后,GWT 会不会做其他事情。
    • 你是说你想要一种 100hz 的闪亮效果,在不同的时间在不同的地方发生更新?在那种情况下,我认为任何<table> 结构都是不合适的——更新太多了。画布元素或 Flash 怎么样?
    • 如果你不需要闪闪发光,只想每秒更新一次所有 100 行,你应该完全使用CellTable
    • 不,我们需要能够独立更新每个单元格(最好的情况)。 JavaScript 原型能够以 10-15% 的 CPU 负载(同一台机器)每秒处理相同的 100 条消息。所以我知道这应该是可能的。我只需要在 GWT 中找到最好的方法。 CellTable 似乎不是最佳选择。
    【解决方案2】:

    作为上述所有方法的替代方案(或除此之外,取决于您获得的结果),我会考虑使用一些调度程序方法。特别是 Scheduler.get().scheduleIncremental() 并一次以 10 次为一组进行更新。这将允许浏览器在更新之间处理其他事件,并且应该对 CPU 使用率产生积极影响。

    CellTable 在这里根本无法帮助您,因为您无法更新单个单元格。因此,作为替代方案,它只剩下 Grid 并手动管理 TableElement。

    【讨论】:

    • 单元的实际更新是在 SchedulerImpl.get().scheduleDeferred() 内部完成的,但这并没有多大帮助。尽管它使浏览器更具响应性。使用 SchedulerImpl.get().scheduleIncremental() 将不起作用,因为我们获得的数据量可能会有所不同。到目前为止,看起来我们应该尝试 Grid 或自己实现 Table。
    • 在这种情况下,到目前为止,增量比延迟要好得多。 Deferred 将在每个操作中使用一个新的 js 计时器,而 incremental 会将多个更新批处理到单个 js 执行堆栈中,从而导致单个页面重绘,从而允许渲染线程也可以批量执行操作。
    【解决方案3】:

    您可以使用cellTable.redrawRow(index);,这在大桌子上速度更快。
    好在行索引是由FieldUpdater 给出的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多