TreeViewer 仅延迟加载图标
我有一个 TreeViewer,它显示项目列表。我的限制如下:
- 每个项目都表示为磁盘上的 XML 文件。
- ' -> 树中的项目“hello”)
- 每个 XML 文件都有一个“类型”,存储在 XML 中,这表示每个项目的图像
每个 XML 文件的文件名是图标的标签(' hello.xml 我为在每个 XML 文件中读取的 TreeViewer 项目执行 getChildren() 并从那里生成 Object[] 数组。直到最近,这还是可以接受的,但现在已经不再是这样了。 XML 文件的正常数量是 10 个,现在是 500 个。
我需要提高性能。但是,由于兼容性等多种原因,以下选项是不可能的
- 。 无法更改 XML 文件的格式(即使用数据库、序列化对象..)
- 无法创建 XML 文件的附加表示形式
- 无法更改 XML 文件的名称XML 文件(即“hello.xml”->“hello-type.xml”)
根据我的测试,当仅获取 XML 文件的目录列表并将其用于标签时,发现了合理的性能。标签名称是最重要的重要的方面,虽然图像类型很有用,但它的存在并不是立即需要的。
这些要求和限制使我得到了以下解决方案:
- 初始 getChilren() 扫描 XML 文件的目录并返回具有“缺失”类型的标签列表。 (getImage() = MissingImage)
- getChilren() 然后启动一个后台作业,该作业读取 XML 文件并获取类型
- 。 == 现在是properIcon)。这是由作业调用的。
- 然后,作业迭代树中的每个项目并调用 update(),对于
我已经实现的每个项目,性能仍有待提高。此外,由于我们对 Display.getDefault().asyncExec 进行了多次调用来进行更新,因此 GUI(虽然仍然具有响应性)将需要时间来响应用户交互(虽然实际上并未锁定)。有什么方法可以改善这一点吗?
已考虑/尝试过以下内容:
- 使用 DeferredTreeContentManager - 没有这样做,因为我希望首先快速获得名称,图像可以稍后按照自己的节奏进行更新
- 立即对所有项目执行 update() / 批量项目- 这会锁定 GUI,比许多单独的 update() 更糟糕
I have a TreeViewer, it displays a list of items. My constrains are as follows:
- Each item is represented as an XML file on the disk.
- The filename of each XML file is the label for the icon ('hello.xml' -> item 'hello' in tree)
- Each XML file has a 'type', stored in the XML, this represents the Image for each item
When I do a getChildren() for by TreeViewer items I read in each XML file and generate the Object[] array from there. Up until recently this has been acceptable but it is not any more. The normal number of XML files was 10, it is now 500.
I need to improve performance. However, for a variety of reasons such as compatablity the following options are not possible
- Cannot change the format of the XML files (i.e. use a database, serialized object..)
- Cannot create an additional representation of the XML files
- Cannot change the name of the XML files (i.e 'hello.xml' -> 'hello-type.xml'
From my tests a reasonable performance is found when just getting a directory listing of the XML files and using this for the labels. The label name is the most important aspect and whilst the image type is useful its presence is not immediately required.
These requirements and constrains have lead me to the following solution:
- Initial getChilren() scans the directory of XML files and returns a list of labels with a 'missing' type image. (getImage() = missingImage)
- getChilren() then starts up a background Job which reads in the XML files and attains the type.
- Each Object[] has a cacheImage() method which loads in the type image (so getImage() == properIcon now). This is called by the Job.
- Job then iterates over each item in the tree and calls an update(), for each item
I have implemented this and the performance leaves something to be desired. Additionally, because we have so many calls to Display.getDefault().asyncExec to do the update, the GUI (whilst still be responsive) will take time to respond to user interactions (whilst not actually locking). Are there any ways I can improve this?
The following has been considered/tried:
- Use a DeferredTreeContentManager - did not do this because I want the names first and quickly, the images can follow later at their own pace
- Performing an update() on all of the items at once / batching up items - This locks the GUI, worse so than many individual update()s
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
来降低后台线程的优先级
尝试通过调用
Thread
。对
asyncExec
的 500 次调用不应使 GUI 无响应,如果它们除了在TreeItem
中设置图像之外没有做更多的事情。为了确保您对TreeViewer.update
的调用成本低廉,请调用它来实现元素到 TreeItems 的高效映射。
Try lowering the priority of your background thread by calling
in your
Thread
.500 calls to
asyncExec
should not make the GUI unresponsive, if they don't do more than setting an Image in aTreeItem
. To ensure, that your calls toTreeViewer.update
are cheap, callwhich enables efficient mapping of elements to TreeItems.
如果您在后台作业中将所有图像加载到 ImageRegistry(可能使用 XML),然后简单地从该注册表添加图像,这不是有帮助吗?
Wouldn't it help, if you load all images to an ImageRegistry in a background job (possibly using the XML), and then simply adding the images from this registry?
我会推荐以下优化策略(按顺序)...
批量更新调用。也就是说,有一个列表,您可以在其中存储已计算图像的内容对象。当列表大小达到某个阈值(或者用完对象)时,开始更新列表中当前的所有对象。确保先复制列表的内容并清除列表,以便缓存线程可以不断累积。使用阈值参数,您可能会通过减少 asyncExec 调用的数量来获得所需的性能。
如果#1 本身还不够(不太可能),您可能还需要考虑围绕可视区域进行优化。 Tree 类具有跟踪哪些项目可见的 api,并且您可以侦听滚动事件。这里的想法是优先考虑可见项目的图像计算,并仅在项目变得可见后调用更新。
I would recommend the following optimization strategies (in order)...
Batch update calls. That is, have a list into which you deposit content objects whose image has been calculated. When the list size arrives at a certain threshold (or you run out of objects), kick off an update of all the objects presently in the list. Make sure to copy the contents of the list first and clear the list so that the caching thread can keep accumulating. Play around with the threshold parameter and you will likely get the perf you are after by reducing the number of asyncExec calls.
If #1 is not sufficient by itself (unlikely), you may also want to consider optimizing around the viewable region. Tree class has api around tracking which items are visible and you can listen for scroll events. The idea here is to prioritize image calculation for items that are visible and to call update on items only after they've become visible.
我建议在后台线程中一次加载/创建多个图像(从你所说的看来,你可以做至少 10 个 w/oa 性能问题)。所以你的线程看起来像这样:
I would suggest loading/creating several images at once in the background thread (from what you said it sounds like you could do at least 10 w/o a performance issue). So your thread would look something like: