提高ipad浏览器下大尺寸xml文件解析的性能
昨天,客戶報(bào)了個(gè)Bug過來:html5應(yīng)用在ipad下卡住不動(dòng)了。按照他發(fā)過來的地址,初步診斷是xml解析的性能問題。應(yīng)用初始化時(shí)要加載幾個(gè)xml配置文件,客戶給的地址中,一個(gè)配置文件有800多K(文件A),另一個(gè)配置文件有400多K(文件B)。我修改了程序,在PC機(jī)上用Safari模擬ipad登錄,解析文件A花了30多秒。一般來說,ipad2的性能是我的PC機(jī)的1/5,在ipad上解析這個(gè)xml文件至少要花150秒。這是不能接受的。同樣的程序,在ie下測(cè)試,僅僅耗時(shí)160ms!我用的是haXe的xml庫,在ie9和在safari上竟然有這么大的性能差距。
又找了幾個(gè)xml庫,不是無法運(yùn)行,就是執(zhí)行失敗。實(shí)在沒有辦法,只好用domparser來解析,當(dāng)html文件處理。使用domparser可以極大的提高性能,還是以文件A為例子,在PC的safari上解析耗時(shí)降為1秒左右,這個(gè)時(shí)間是可以承受的。然而,使用domparser存在一個(gè)問題,就是無法提取出CData數(shù)據(jù)。http://stackoverflow.com/questions/5227592/extract-cdata-from-rss-xml-using-javascript 給出了一個(gè)解決方案:將CData數(shù)據(jù)用標(biāo)簽圍住,這是一種思路。于是,修改程序,將<![CDATA[替換為<cdata>,將]]>替換成</cdata>。
提取cdata標(biāo)簽的數(shù)據(jù),當(dāng)作XML文件的CData數(shù)據(jù)/。問題似乎解決了,經(jīng)過多次測(cè)試,又發(fā)現(xiàn)了新的問題:
CData中有很多字符沒有轉(zhuǎn)義。在CData中倒是無害,但在<cdata></cdata>中就變成有害了。這里又要表揚(yáng)下ie9:ie9在這種情況下能夠正確解析,Safari不能!
既然問題出現(xiàn)在CData,那么我們就對(duì)CData數(shù)據(jù)進(jìn)行預(yù)處理:
(1),找到每個(gè)CData數(shù)據(jù),為它編號(hào);
(2),對(duì)每個(gè)CData片段,用它的編號(hào)進(jìn)行替換,這樣就屏蔽了敏感字符;
(3),將替換后的文本,用domparser解析。
這樣一來,當(dāng)使用這個(gè)Dom時(shí),碰到CData編號(hào),再將它替換為對(duì)應(yīng)的CData數(shù)據(jù)即可。因?yàn)槲募嗀在ipad上無法解析成功,這里只對(duì)文件B的解析進(jìn)行了都比。之前解析文件B耗時(shí)是13-16秒,使用新方法后,解析時(shí)間縮短為32毫秒,提高了約400倍。
====
下面的代碼是用haXe寫的,haXe很容易讀,就不詳加解釋了。
CData類,存儲(chǔ)鍵值對(duì):
{
?public?var?key:String;
?
?public?var?val:String;
?
?public?function?new()?
?{
?}?
}
Xml2Html類,對(duì)xml文本進(jìn)行預(yù)處理,并存儲(chǔ)CData信息:
class?Xml2Html?{
?private?var?map:Array<CData>;
?public?function?new()?
?{
?}
?
?public?function?getCData(key:String):String
?{
??if?(map?==?null)?return?null;
??
??for?(i?in?0?...?map.length)
??{
???var?item:CData?=?map[i];
???if?(item.key?==?key)
???{
????return?item.val;
???}
??}
??
??return?null;
?}
?
?public?function?prepareXmlAsHtml(txt:String):String
?{
??map?=?new?Array<CData>();
??txt?=?StringTools.replace(txt,?"<![CDATA[",?"]]>");
??var?lines:Array<String>?=?txt.split("]]>");
??if?(lines.length?==?0)?return?txt;
??var?buff:StringBuf?=?new?StringBuf();
??var?k:Int?=?0;
??for?(i?in?0?...?lines.length)
??{
???var?val:String?=?lines[i];
???if?(i?%?2?==?0)?//?正常內(nèi)容
???{
????buff.add(val);
???}
???else
???{
????var?key:String?=?Std.string(k);
????buff.add("<cdata>"?+?key?+?"</cdata>");
????var?cdata:CData?=?new?CData();
????cdata.key?=?key;
????cdata.val?=?val;
????map.push(cdata);
????k++;
???}
??}
??
??return?buff.toString();
?}
}
下面是解析示例:
var?ctx:Xml2Html?=?new?Xml2Html();??searchInfo?=?dom.parseFromString(ctx.prepareXmlAsHtml(data),?"text/xml");
????
??var?dom:HtmlDom?=?searchInfo;
??var?pages:HtmlCollection<HtmlDom>?=?dom.getElementsByTagName("page");
??for?(i?in?0?...?pages.length)
??{
???var?node:HtmlDom?=?pages[i];
???var?pageNumVal:String?=?node.getAttribute("pageNumber");
???var?htmlText:String?=?null;
???var?htmlTextDoms:HtmlCollection<HtmlDom>?=?node.getElementsByTagName("cdata");
???if?(htmlTextDoms?!=?null?&&?htmlTextDoms.length?>?0)
???{
????htmlText?=?StringTools.trim(htmlTextDoms[0].childNodes[0].nodeValue);
????htmlText?=?ctx.getCData(htmlText);
???}
???
???for?(k?in?0?...?book.pages.length)
???{
????var?page:Page?=?book.pages[k];
????if?(page.id?==?pageNumVal)
????{
?????page.content?=?htmlText;
????}
???}
??}
====
小結(jié):
(1)IE9很厲害!
(2)haXe是好東東,用它寫js程序很舒服。但因?yàn)槭情_源社區(qū)的作品,還不夠成熟,需要使用者自己想辦法來彌補(bǔ)其缺陷。
總結(jié)
以上是生活随笔為你收集整理的提高ipad浏览器下大尺寸xml文件解析的性能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#学习笔记(二)运算符 乘方 判断语句
- 下一篇: C#基础解析之Ⅲ 【循环结构】