1. 性能瓶颈分析
以下为 CPU
性能限定为 4x slowdown
情况下录制。
切页时,会调用两个函数 initMenuTree
(耗时 1.12 s)和 refreshWnd
(耗时 84.2 ms)。
其中,initMenuTree
函数分成 3 个部分,第一部分(匿名函数)用来向树中插入节点,耗时 87.7 ms;第二部分展开所有节点,耗时 888.5 ms;第三部分选中需要的节点,耗时 142.5 ms。
通过分析可知,有以下几方面可以考虑优化:
- 在第二部分
e.expandAll
中,花费大量时间将所有节点展开,然后紧接着在onClickTreeNode
中调用e.collapseAll
又将所有节点折叠。需要评估一下,展开所有节点的目的是什么,是否可以删除。 - 在
onClickTreeNode
中调用了refreshWnd
函数,然后initMenuTree
结束后再次调用了一次refreshWnd
函数,同一个操作中,可能不需要重复调用。
- 在
refreshWnd
函数(耗时 84.2 ms)中,有 73% 的时间被refreshReddot
函数占用(耗时 61.6 ms)。可以尝试优化小红点的判断逻辑,或者延迟判断。
2. 优化方法
总体思路是,没必要的函数不调用,不需要立即执行的函数延迟调用,耗时长的函数拆分后分帧执行。
2.1 删除 expandAll
函数
分析发现,e.expandAll()
函数耗时特别长,且树的节点越多耗时越长。
经测试,这个函数并非必须的,删除以后对功能几乎没有影响,但是对性能的提升非常明显。
2.2 refreshWnd
函数的调用次数
在代码中,refreshWnd()
函数调用的位置有以下几处
- 界面初始化结束后,
onInit()
- 收到刷新界面消息时,
Msg()
- 切换子页签时,
setPageIndex()
- 切换选中的树节点时,
onClickTreeNode()
这几处调用都是合理且有必要的。
但是通过性能分析工具可知,在 Msg()
和 setPageIndex()
中都会调用 initMenuTree()
来初始化树状列表,而 initMenuTree()
中又会调用 onClickTreeNode()
来选中一个默认的节点。这样就会导致每次切换页签或者其它操作都会重复调用 refreshWnd()
函数。
解决方法
在 initMenuTree()
不再调用 onClickTreeNode()
,选中默认节点的功能改用其它方式实现。
// 通过 selectNode() 函数实现选中节点
this.itemTree.selectNode(defaultNode);
这样保证了每次切页等操作,只会调用一次 refreshWnd()
函数,节省了不必要的界面刷新。
2.3 refreshReddot
小红点刷新优化
目前每次刷新界面,都会调用一次小红点刷新。但是小红点状态判断需要的计算量很大,耗时比较长。
这部分优化有三个方向的思路,
- 优化小红点状态判断算法,减少计算量;
- 对小红点刷新时机做更精细化的判断,减少函数调用;
- 将小红点刷新操作进行分帧处理。
第一个,优化空间不大,因为该系统本身就是需要判断所有物品的小红点状态,而且每个物品的合成条件由配置决定,没有固定的规律,所以优化空间不大。
第二个,经测试,在每次刷新界面时,都必须相应地刷新小红点,任何一处没刷,都会导致小红点显示异常。所以这里也没有办法。
第三个,分帧处理,将一些耗时的操作分帧处理,来缓解每一帧的运算压力,是一种几乎通用而且好用的优化手段。
经过分帧处理后,将耗时 60ms 左右的小红点刷新函数剥离出去,原来的 refreshWnd()
函数执行时间降低到 30 ms 左右。
3. 优化效果
通过优化,合成系统的切页操作耗时,由原来的 1200 ms
左右降低到 103 ms
左右,节省了 91.5%
左右的时间。
此处评论已关闭