Flex3 性能提示

Flex3 性能提示

最近一直在使用 Flex3 对原有项目进行重构和 bug 修改。遇到不少性能问题,分析发现由于 Flex 在和 Servlet 交互时使用了大量的 XML 作为传输格式,导致某些功能在处理 XML 时非常的慢,甚至还 Error #1502: A script has executed for longer than 15 seconds。让人痛不欲生!

和 RIA Meeting 组织者 lwz7512 交流后,他建议使用 BlazeDS 来代替 XML 操作。随着对 BlazeDS 的渐渐了解,的确能解决不少性能问题。Adobe 的 Flex 技术传道士 James Ward 在 BlazeBench: Why you want AMF and BlazeDS一文中详细比较了利用 BlazeDS 所带来的性能提升,下图是 James Ward 写的性能测试工具。

通过上面的测试数据发现,正如 BlazeDS 官方网站所提到的:在使用 AMF3 作为传输协议后,Flex 和后台交互的性能大约提高了10倍。面对这一结果,想必大家很兴奋,看来是时候用 BlazeDS 来替换 XML 了。不过问题并不是这么容易就解决了,由于 BlazeDS 在 2007年12月12日才正式开源发布,而在这之前项目都是以 XML 作为传输格式(当然也没用GraniteDS),并且 Flex 代码中处处可见对 XML 的操作,要对这样的代码进行重构......难。

要解决 XML 处理的性能问题。就应该好好的利用 E4X,尽量避免在解析 XML 的过程中使用循环。这里介绍几篇文章让大家了解下《E4X:出色的 JavaScript《E4X 教程》《AS3中新的XML处理方法 – E4X》E4X给我最大的便利就是..运算符。思考下面的XML

var myXML:XML =
                
< groups  name ="大组" >
                    
< group  name ="小牛组" >
                        
< person  fullname ="rosenjiang" />
                        
< person  fullname ="abc" />
                    
</ group >
                    
< group  name ="柴鸡组" >
                        
< person  fullname ="rosenjiang" />
                    
</ group >
                    
< group  name ="柴鸭组" >
                        
< person  fullname ="rosenjiang" />
                        
< person  fullname ="rosen jiang" />
                    
</ group >
                    
< group  name ="独立大队" >
                        
< person  fullname ="rosenjiang" />
                    
</ group >
                   
</ groups > ;

要得到所有属性fullname是”rosenjiang”的person节点的个数怎么做?在没详细了解 E4X 之前,我会用 myXML.group 操作得到 group 的 XMLList 集合,然后再用循环去找寻每个 group 中 person 节点属性 fullname 为”rosenjiang”的数据:

               function on_click(): void {
                   var list:XMLList 
=  myXML.group;
                   var count:
int   =   0 ;
                   
for (var i: int = 0 ; i < list.length(); i ++ ){
                       var persons:XMLList 
=  list[i].person;
                       
if (persons.length()  ==   1   &&  persons.@fullname  ==   " rosenjiang " ){
                           count 
++ ;
                       }
else {
                           
for (var j: int = 0 ; j < persons.length(); j ++ ){
                               
if (persons[j].@fullname  ==   " rosenjiang " ){
                                   count 
++ ;
                               }
                           }
                       }
                   }
                   Alert.show(count
+ " " );
               }

上面的写法的确很傻,下面是改进之后的代码,关键部分只有一行:

               function on_click(): void {
                   var list:XMLList 
=  myXML..person.(@fullname  ==   " rosenjiang " );
                   Alert.show(list.length()
+ " " );
               }

通过合理使用 E4X 语法,顺利的避免了循环带来的性能问题。过了几天,来个新的需求,需要统计出在这个 XML 中有几个不同姓名的 person。思考片刻,我可不可以用眼睛数出来啊?这里有 3 个...... 好吧,看来又是循环问题,第一个想到的是用两个嵌套 for 循环来进行排除处理,这是最直观的想法......

下面我介绍下如何用 ArrayCollection 并只使用一个循环来计算个数。由于 Flex 里面不支持 Map 类型,而我 Google 了一圈,且 RIACN 论坛上网友的 Map 实现性能都不行,遂打算用 ArrayCollection 模拟 Map 进行操作:

                import  mx.collections. * ;
               function on_click():
void {
                   var list:XMLList 
=  myXML..person;
                   var ac:ArrayCollection 
=   new  ArrayCollection();
                
for  each (var item:XML in list){
                    var fullname:String 
=  item.@fullname;
                    
if (ac.getItemIndex(fullname)  ==   - 1 ){
                        ac.addItem(fullname);
                    }
                }
                   Alert.show(ac.length
+ " " );
               }

上面代码没什么过多解释,思路是取出一个 fullname 放进 ArrayCollection,然后判定下一个 fullname 是否存在于 ArrayCollection 中,如果存在就跳过,不存在就放进去再取下一个。另外我发现,使用 for each 比单纯的使用 for 性能要高一点点。

做了以上的努力后,性能还是低下!怎么办?看来没什么办法了,和你的 boss 谈谈吧,考虑下进行大刀阔斧重构的可能性。或者能否在超时后给用户一个提示,让他操作的数据量少点,需要做的是捕获超时异常,既 ScriptTimeoutError,请参阅http://www.cs.vu.nl/~eliens/pim/assets/flex3/langref/flash/errors/ScriptTimeoutError.html,进行 try catch 。 Good luck!



请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处: http://www.blogjava.net/rosen

你可能感兴趣的:(Flex3 性能提示)