具有大量 UI 对象的 Flex 应用程序 == 速度慢?

发布于 2024-07-25 00:59:44 字数 1063 浏览 8 评论 0原文

我正在 Flex 3 中构建我的第一个 Flex 自定义组件。它是一个基于“Grid”容器类的数据表,每个单元格中都有一个简单的文本标签。 (DataGrid 和 AdvancedDataGrid 不是满足我的需求的合适起点。)该组件在使用较小的表时工作得很好,但我尝试使用较大的表对其进行压力测试,并对结果感到失望。

组件创建过程有一些缓慢的地方,但这些是我有能力优化的,并不是我主要关心的。 让我更担心的是 Flex 框架本身的局限性。

这个“大”样本表中有超过 7000 个单元格。 这是很大的,但仍然比我需要容纳的最大数量小 1-2 个数量级。 在标准网格结构中,组件的主要部分由一个具有 400 个 GridRows(每个 16 个 GridItems)的 Grid 以及一些其他较小的辅助网格组成。

表格渲染后,我发现以下内容:

  • 与鼠标相关的事件触发缓慢。 具体来说,我在每个表格单元格上注册了 rollOver/rollOut 事件处理程序,以便我突出显示指针下方的单元格。 在小桌子上,我可以非常快速地在桌子上移动鼠标,并且突出显示会实时跟随指针。 对于较大的表格,突出显示非常不稳定,每秒仅更改大约两次,跳过许多单元格。
  • 如果我将鼠标光标放在该组件上并将其留在那里,我的 CPU 就会被固定(无论如何,一个处理器核心),并保持这种状态,直到我离开该组件,此时它会进入空闲状态。 我的组件此时根本没有执行任何操作。

感觉 Flex 根本无法扩展以支持这么大的组件树。 我不敢想象 100,000 个细胞会如何表现。 也许我正在推动 Grid 超出其预期用途,但每个表单元格都有一个对象似乎并不是一个不合理的模型,并且树中大约 14,000 个对象(每个单元格一个 GridItem 和一个 Label)似乎相当适中。

我还没有从 FlexBuilder 分析器中获取有用的数据; 我在做这个工作。 目前,我最大的问题是:

  • 我真的通过这个适度的测试突破了 Flex 的极限吗?
  • 我对这个组件的处理方法是否完全错误?

我在 WinXP 上的 Firefox 下的 Flash Player 9 上运行它。

I'm building my first Flex custom component, in Flex 3. It is a data table based on the 'Grid' container class, with a simple text Label in each cell. (DataGrid and AdvancedDataGrid were not appropriate starting points for my needs.) The component works quite well using smallish tables, but I tried stress-testing it using a larger table, and have been disappointed by the results.

The component creation process has some slow spots, but those are in my power to optimize and aren't my primary concern. What worry me more are what appear to be limitations in the Flex framework itself.

This 'large' sample table has a bit over 7000 cells in it. This is largish, but still 1-2 orders of magnitude less than the biggest I need to accommodate. In standard Grid structure, the main portion of the component consists of a Grid with 400 GridRows of 16 GridItems each, plus a few other smaller ancillary Grids.

Once the table renders, I find the following:

  • Mouse-related events are slow to fire. Specifically, I have rollOver/rollOut event handlers registered on each table cell, to let me highlight the cell under the pointer. On a small table, I could move the mouse over the table very quickly, and the highlighting would follow the pointer in real-time. With the larger table, the highlighting is very jerky, changing only about twice per second, skipping over many cells.
  • If I place the mouse cursor over the component and leave it there, my CPU is pegged (one processor core, anyway), and stays that way until I move off of the component, when it drops to idle. My component isn't doing anything at all at this point.

It feels like Flex simply cannot scale to support component trees that are this large. I shudder to imagine how it would behave with 100,000 cells. Perhaps I'm pushing the Grid beyond its intended use, but having an object per table cell doesn't seem like an unreasonable model, and ~14,000 objects in the tree (a GridItem and a Label per cell) seems pretty modest.

I have yet to get useful data out of the FlexBuilder profiler; I'm working on it. For now, my biggest questions are:

  • Am I really pushing the limits of Flex with this modest test?
  • Is my approach to this component completely off-base?

I'm running this on Flash Player 9 under Firefox on WinXP.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

聚集的泪 2024-08-01 00:59:44

是的,Flex 的设计目的并不是支持大量组件,众所周知,您应该最大限度地减少组件数量,并且不要使用不需要的功能(例如,如果不需要,请使用 DisplayObject 而不是 Canvas)需要额外的功能)。

将数据与显示的对象精确镜像是不明智的。 DisplayObjects(和相关类)相对重量级,您需要控制拥有的数量。

我想说的是,您正在使用的规模(包含 1000 多个单元,并且每个单元都有一个事件侦听器)肯定会达到 Flex 的极限。

我认为你应该更好地审视你的方法和架构。 我假设您不会同时显示所有 1000 多个项目,也许您应该使用分页并在每个屏幕上显示 100 左右,并使用上一个/下一个按钮移动到另一个页面。 您还可以考虑使用自定义滚动条动态添加和删除行,模拟滚动效果。 这做起来要复杂得多。

Yes, Flex is not designed to support very large numbers of components, it is well known that you should minimize the number of components and don't use features that you don't need (Eg. DisplayObject instead of Canvas if you don't need the extra functions).

It's unwise to mirror your data exactly with displayed objects. DisplayObjects (and related classes) are relatively heavyweight, and you need to control how many of those you have.

I would say that the scale you're working at, with 1000+ Cells, and an event listener for each one, would definitely reach Flex's limits.

I think you should take a better look at your approach and architecture. I assume you are not displaying all 1000+ items at the same time, perhaps you should use paging and display 100ish with each screen, with previous/next buttons to move on to another page. You could also consider dynamically adding and removing rows using a custom scrollbar, simulating the scroll effect. This is much more complicated to do.

鹿港小镇 2024-08-01 00:59:44

天哪,看来我们可以写一本关于这个主题的书。 或者至少一章。 在开发我们的产品时,我们在这个领域学到了很多东西。

底线 - 是的,当您在屏幕上添加 1000 多个“东西”时,Flex 会减慢速度直至停止。 这里有一些要点,以及已经提到的一些内容的重复(只是为了简洁)

1)始终只绘制可见的内容。 新 Spark DataGrid 的架构师 Hans Muller 在 ViewPorts 上有一篇很棒的文章。 http://hansmuller-flex.blogspot.com /2009/06/introduction-to-viewports-and-scrolling.html。 因此,实例化足够的“单元格”来填充可见区域,并在用户滚动时基本上回收它们。

2) 回收,回收,再回收:继上面之后,当用户滚动时,您显然必须回收现在不在视图中的单元格以显示在视图中的单元格。 这里有一些我们通过艰难的方式学到的东西:-)
-> 不要处置和创建新单元格,而是使用重新父级或使用重新定位(首选重新定位)

这意味着什么:假设您有一个 10X10 网格(可见),显示 100X100 数据提供程序。当用户滚动到单元格 20X20 时,最快的方法将现有单元格的 X 和 Y 设置到新位置,然后为每个单元格调用 set data。 我们之前使用了重定父级,因为我们的场景是一系列相关的容器,因此这可能不适用于您。 但最重要的是——我们只是在可见区域周围移动“行”。 因此,创建和销毁会很慢,删除和添加到显示对象列表会更快,而仅在 (x,y) 周围移动会最快。

3) 明智地选择您继承的内容:Flex SDK 是一个野兽。 因此,明智地选择你的“细胞”基类。 例如,SDK DataGrids 有一个继承自 UITextField (Halo) 的轻量级渲染器,而不是 Label。 即使 UIComponent 在某些场景下也会很重。 查找 UIComponent 的 asdocs,看看您是否需要其中的所有内容,否则请考虑从其层次结构的更高层继承。

4) 缓存计算:在开发周期的最后进行。 完成某个功能后,运行 flex profiler。 确定运行时间最长的方法和调用次数最多的方法。 我们在发布时总是这样做,因为总是需要改进。 当您开发高度可视化的组件时,涉及大量数学知识,过多的计算会减慢速度。

5) 确保对内存进行分析:未连接的事件侦听器、恶意对象引用等会降低性能。 Flex profiler 是一个很好的工具来解决这个问题,所以一定要使用它。

我们这里有一些很好的链接:
http://www.flexicious.com/resources/Ultimate/Docs/LargeDataset.htm

希望这可以帮助!

Boy, it seems we can write a book on this topic. Or atleast a chapter. We learnt quite a few things in this area as we were developing our products.

Bottom line - yes, Flex will slow down to a halt when you add 1000+ "things" on the screen. Here are a few bullet points, and some repetitions of what's already mentioned (just to be concise)

1) Always draw only what is visible. Hans Muller, the architect on the new Spark DataGrid has a great writeup on ViewPorts. http://hansmuller-flex.blogspot.com/2009/06/introduction-to-viewports-and-scrolling.html. So instantiate enough "cells" to fill up the visible area, and basically recycle them as the user scrolls.

2) Recycle, recycle, recycle: Further to above, as the user scrolls, you obviously have to recycle cells that are now out of view to show the ones that are in view. Here there are a few things we learned the hard way :-)
-> Instead of disposing and creating new cells, either use reparenting or use repositioning (prefer repositioning)

What this means is this: Say you have a 10X10 grid (visible) showing a 100X100 data provider.When the user scrolls to cells 20X20, the quickest way will be to set the X and Y of the existing cells to the new locations, and then call set data for each. We used reparenting earlier because our scenario was a series of related containers, so this may not apply to you. But bottom line - we simply move "rows" around the visible area. So creating and destroying will be slow, removing and adding to the display object list will be faster, and just moving around (x,y) will be fastest.

3) Choose what you inherit from wisely: The Flex SDK is a beast. So choose your "cells" base class wisely. For example, the SDK DataGrids, have a lightweight renderer that inherits from UITextField (Halo), as opposed to Label. Even UIComponent will be heavy in certain scenarios. Look up the asdocs for UIComponent and see if you need everything in there, else consider inheriting from further up its hierarchy.

4) Cache Calculations: Do this last in your development cycle. Once you are done with a feature, run flex profiler. Identify the longest running methods, and the most called methods. We always do this when we release, because there's always improvements to be made. There's a lot of math involved when you're developing a highly visual component, and too many calculations will slow things down.

5) Make sure you profile for memory : Unwired event listeners, rogue object references, etc will kill performance. Flex profiler is an excellent tool to combat this, so make sure you use it.

We have some good links here:
http://www.flexicious.com/resources/Ultimate/Docs/LargeDataset.htm?

Hope this helps!

空城旧梦 2024-08-01 00:59:44

如果您查看 Flex 框架中任何基于列表的控件,您会发现它们大量使用了可回收的项目渲染器。 因此,显示 20 行的 DataGrid 仅创建大约 22 个渲染器,并在您滚动列表时回收它们。 这就是为什么 DataGrid 可以容纳数千条记录并且仍然具有相当快的性能。 我建议您查看 Peter Ent 关于项目渲染器的系列文章,并查看 ListBase/List 和一些相关的类,以了解如何构建类似的内容:

http://weblogs.macromedia.com/pent/archives/2008/03/itemrenderers_p.html

If you look at any List-based control in the Flex framework, you'll see that they make significant use of item renderers which are recycled. So a DataGrid with 20 rows displayed only creates about 22 renderers and recycles them as you scroll through the list. This is why a DataGrid can hold thousands of records and still have pretty snappy performance. I recommend you check out Peter Ent's series of articles on item renderers and take a look at ListBase/List and some of the related classes to understand how to build something similar:

http://weblogs.macromedia.com/pent/archives/2008/03/itemrenderers_p.html

惟欲睡 2024-08-01 00:59:44

没有看到你的代码,也没有确切地知道你想要做什么……看起来你确实在通过一次性将如此多的数据推送到框架中来突破 Flex 的极限。

请记住,Flash 运行时并不是为处理大型应用程序而设计的...而是在浏览器内运行一些轻型应用程序。 您的用户似乎也不太可能需要同时访问所有这些控件。

您可以尝试提供数据服务(Java、.NET 等)来驱动应用程序中的数据。 然后,您可以对数据进行分页,以便框架一次仅处理 200 - 300 多个元素。

Without seeing your code and knowing exactly what you're trying to do...it definitely seems like you're pushing the limits of Flex by pushing that much data into the framework all at once.

Keep in mind that the Flash runtime wasn't designed to handle huge applications...but run somewhat light applications inside the browser. It also seems unlikely that your users are going to need to have access to all of those controls all at once.

You could try providing data services (Java, .NET, etc.) to drive the data in your application. You would then page through the data so that the framework is only dealing with maybe 200 - 300+ elements at a time.

無處可尋 2024-08-01 00:59:44

在flex中,如果您使用鼠标移动事件来重绘任何内容..您可能会遇到渲染速度非常慢的情况。

例如:

this.addEventListener(MouseEvent.MOUSE_MOVE, 重画);

解决

public function redraw(anything:Object=null):void{
        //draw something here
            this.graphics.clear();
            this.graphics.lineStyle(3, 0x000000);
            this.graphics.moveTo(startPoint.x, startPoint.y);
            this.graphics.lineTo(endPoint.x, endPoint.y);
            this.scaleTextInput.x = centerPoint.x;
            this.scaleTextInput.y = centerPoint.y;

    }

上面的代码导致渲染速度非常慢...

方案:

使用 Event.ENTER_FRAME 事件代替? 虽然比鼠标移动事件更耗费资源,但您每秒应该收到更多的更新,从而使鼠标对用户显得更加敏感:

例如:

this.addEventListener(Event.ENTER_FRAME, redraw); 而不是

this.addEventListener(MouseEvent.MOUSE_MOVE, 重画);

一切顺利。.快乐弯曲

更多信息:
http://www.deepakdhakal.com

In flex, if you using Mouse move event to redraw anything .. You might have experienced very slow rendering .

eg:

this.addEventListener(MouseEvent.MOUSE_MOVE, redraw);

and

public function redraw(anything:Object=null):void{
        //draw something here
            this.graphics.clear();
            this.graphics.lineStyle(3, 0x000000);
            this.graphics.moveTo(startPoint.x, startPoint.y);
            this.graphics.lineTo(endPoint.x, endPoint.y);
            this.scaleTextInput.x = centerPoint.x;
            this.scaleTextInput.y = centerPoint.y;

    }

The Above code results very slow rendering ...

Solution:

Use Event.ENTER_FRAME event instead? Although more resource intensive than the mouse move event, you should receive considerably more updates per second, allowing the mouse to appear more responsive to the user:

Eg:

this.addEventListener(Event.ENTER_FRAME, redraw); instead of

this.addEventListener(MouseEvent.MOUSE_MOVE, redraw);

and You are good to go ..Happy Flexing

More on:
http://www.deepakdhakal.com

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文