最近一直在使用 Flex3 對(duì)原有項(xiàng)目進(jìn)行重構(gòu)和 bug 修改。遇到不少性能問題,分析發(fā)現(xiàn)由于 Flex 在和 Servlet 交互時(shí)使用了大量的 XML 作為傳輸格式,導(dǎo)致某些功能在處理 XML 時(shí)非常的慢,甚至還 Error #1502: A script has executed for longer than 15 seconds。讓人痛不欲生!
和 RIA Meeting 組織者 lwz7512 交流后,他建議使用 BlazeDS 來代替 XML 操作。隨著對(duì) BlazeDS 的漸漸了解,的確能解決不少性能問題。Adobe 的 Flex 技術(shù)傳道士 James Ward 在 BlazeBench: Why you want AMF and BlazeDS一文中詳細(xì)比較了利用 BlazeDS 所帶來的性能提升,下圖是 James Ward 寫的性能測(cè)試工具。
通過上面的測(cè)試數(shù)據(jù)發(fā)現(xiàn),正如 BlazeDS 官方網(wǎng)站所提到的:在使用 AMF3 作為傳輸協(xié)議后,Flex 和后臺(tái)交互的性能大約提高了10倍。面對(duì)這一結(jié)果,想必大家很興奮,看來是時(shí)候用 BlazeDS 來替換 XML 了。不過問題并不是這么容易就解決了,由于 BlazeDS 在 2007年12月12日才正式開源發(fā)布,而在這之前項(xiàng)目都是以 XML 作為傳輸格式(當(dāng)然也沒用GraniteDS),并且 Flex 代碼中處處可見對(duì) XML 的操作,要對(duì)這樣的代碼進(jìn)行重構(gòu)......難。
要解決 XML 處理的性能問題。就應(yīng)該好好的利用 E4X,盡量避免在解析 XML 的過程中使用循環(huán)。這里介紹幾篇文章讓大家了解下《E4X:出色的 JavaScript》、《E4X 教程》、《AS3中新的XML處理方法 – E4X》。E4X給我最大的便利就是..運(yùn)算符。思考下面的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 ="獨(dú)立大隊(duì)" > ???????????????????????? < person? fullname ="rosenjiang" /> ???????????????????? </ group > ??????????????????? </ groups > ;
要得到所有屬性fullname是”rosenjiang”的person節(jié)點(diǎn)的個(gè)數(shù)怎么做?在沒詳細(xì)了解 E4X 之前,我會(huì)用 myXML.group 操作得到 group 的 XMLList 集合,然后再用循環(huán)去找尋每個(gè) group 中 person 節(jié)點(diǎn)屬性 fullname 為”rosenjiang”的數(shù)據(jù):
上面的寫法的確很傻,下面是改進(jìn)之后的代碼,關(guān)鍵部分只有一行:
通過合理使用 E4X 語法,順利的避免了循環(huán)帶來的性能問題。過了幾天,來個(gè)新的需求,需要統(tǒng)計(jì)出在這個(gè) XML 中有幾個(gè)不同姓名的 person。思考片刻,我可不可以用眼睛數(shù)出來啊?這里有 3 個(gè)...... 好吧,看來又是循環(huán)問題,第一個(gè)想到的是用兩個(gè)嵌套 for 循環(huán)來進(jìn)行排除處理,這是最直觀的想法......
下面我介紹下如何用 ArrayCollection 并只使用一個(gè)循環(huán)來計(jì)算個(gè)數(shù)。由于 Flex 里面不支持 Map 類型,而我 Google 了一圈,且 RIACN 論壇上網(wǎng)友的 Map 實(shí)現(xiàn)性能都不行,遂打算用 ArrayCollection 模擬 Map 進(jìn)行操作:
上面代碼沒什么過多解釋,思路是取出一個(gè) fullname 放進(jìn) ArrayCollection,然后判定下一個(gè) fullname 是否存在于 ArrayCollection 中,如果存在就跳過,不存在就放進(jìn)去再取下一個(gè)。另外我發(fā)現(xiàn),使用 for each 比單純的使用 for 性能要高一點(diǎn)點(diǎn)。
做了以上的努力后,性能還是低下!怎么辦?看來沒什么辦法了,和你的 boss 談?wù)劙桑紤]下進(jìn)行大刀闊斧重構(gòu)的可能性。或者能否在超時(shí)后給用戶一個(gè)提示,讓他操作的數(shù)據(jù)量少點(diǎn),需要做的是捕獲超時(shí)異常,既 ScriptTimeoutError,請(qǐng)參閱http://www.cs.vu.nl/~eliens/pim/assets/flex3/langref/flash/errors/ScriptTimeoutError.html,進(jìn)行 try catch 。 Good luck!
Powered by: BlogJava Copyright © Rosen