好用到掉渣的IE8 Developer Tools--JS效能調校經驗
22 |
對我來說,IE8最讓人興奮的新功能非"IE8 Developer Tools"莫屬!! (沒騙你們,我有文章為憑: 1 2 3)
上市後,IE8立即取代Firefox成為我開發網頁時的主力測試工具,也開始體驗它的強大威力。
像是可任意下指令的Console視窗我就超愛,把整個網頁玩弄於股掌之間的感覺真好~~
就拿新聞網站為例,先用上次提過的技巧載入jquery-1.3.2.js,用HTML Tab的工具觀察DOM結構,然後可以在Script Tab的Conosle區一行一行下指令,便可邊試邊改,恣意地上下其手(邪笑),享受惡搞的樂趣,哇哈哈哈~~~ (謎之聲: 應該沒人像你這麼無聊吧?)
CSS編輯器可以任意新增Rule、啟用停用Rule的功能也很讚,這點先前已介紹過。
如果你跟IE8 Developer Toolbar還不熟,點部落上好幾篇精彩的介紹文可以為你們搭起友誼的橋樑:
- [IE8] 活用開發者工具的HTML/CSS解譯
- [IE8] Internet Explorer 8 中的JavaScript
- [IE8 修練] Internet Explorer 8 強大新工具 – Developer Tools
- [IE8修練大會] IE8與AJAX (II): 開發者工具與JavaScript偵錯
IE8 Dev Tools的介紹已經很多了,今天則來談談我這兩天利用它調校Javascript效能的實戰經驗。
故事是這樣的,手上的案子需要寫一個類似Excel試算表的網頁介面,總共有近1500格(120列*12欄)的大表格,每列有兩個欄位可以輸入數字,而任一格修改數字(如紅框所示)後,會影響整個分配結構,全表有大半的欄位都要重算過(如綠框所示)。
開發初期,我用最直覺的寫法,$("..input..").change()時利用$(this).parent().next()之類的技巧去找前後格子讀取數字,重新計算加總,再將結果回寫其中。一開始只有十來列時速度還OK,等到測試極端案例(120列)時,問題就大了。每更改一格的內容平均要等上3-5秒才會完成更新,有時甚至IE8會跳出Slow Script警告,詢問是否要停止執行。
觀察到這種現象,心中已有不祥預感。顫抖著雙手,用未來使用者的標準配備---老爺PC+IE6組合而成的魔王機(由來)做一次測試,果不其然,IE6以從頭到尾CPU 100%的姿態當住不動,連正常關閉程式都沒辦法。
好了,是該調校效能的時候了。永遠記得效能調校的第一步驟-->要能找出效能衡量的明確指標!
IE8 Dev Tools的Profiler可以分析並記錄各個Javascript函數被呼叫的次數以及執行所耗時間,無疑是絕佳的觀察工具。操作的方法是,先按下"Start Profiling"(橘框所在),接著在網頁上進行操作,再按下"Stop Profiling"。每次按下"Stop Profiling",就會產生一份Report,介面上有個下拉選單(藍框處)可以切換多次測試的結果進行比較。
報告結果可以依函數做統計,但我偏好的是"Call Tree"方式(紫框),可像Call Stack一樣,列出函數間彼此呼叫的來龍去脈。一般來說,我們首先關心的是累計執行時間,值愈大代表效能愈差。因此,整個調校的過程就是設法讓這個數字愈來愈小!
Call Tree檢視的好處在於,你可以先鎖定最慢的函數,展開它所呼叫的函數,再找出這些子呼叫中最慢的再展開,一路找下去,很快就能查到效能不彰的根源並加以改善,立竿見影。找到有問題的函數,右方會有函數所在的js檔案URL以及列數,點兩下,IE8 Dev Tools馬上就會在Script Tab開啟該js,並捲到該列程式所在位置,貼心到破錶吧! 當然,要改JS程式內容得回VS2008,修改後重新整理網頁,再做一次同樣動作並用Profiler監測,比較看看修改後累積耗用時間是否明顯下降。
重覆以上的步驟,我終於每次改值重算的時間由4,5秒降到1秒左右,雖不滿意,但可接受了。
應該有人很好奇Javascript程式要怎麼修改才會變快,我想這部份Case by Case,並無通用的簡便法則,有時甚至要違背一般的程式設計準則才能達到目的。(就像設計資料庫Schema時,透過"反正規化"改善查詢效率一樣)
但我還是整理一下本次修改的心得:
- 原本的設計將數值直接存在td裡,讀寫時都要涉及UI元素的存取,是效能不彰的最大元凶。我後來利用Javascript Object在背後建立出對應表格的完整資料陣列,每次重算時先在物件陣列裡算好,再將結果寫回前端。這樣做較不直覺,且程式複雜許多,但存取UI元素比操作Javascript元件慢上數倍,為了達到預期的效能,似乎是唯一解。
- 加總最直覺的算法是用for迴圈累加全部的數字,當其中一個值改變時,更快的寫法是將加總值扣掉原值,加上新值,避免重新跑迴圈重算。一樣的,這種設計較不直覺淺顯,但CPU耗用及速度都改善許多。
- children()比find()快
- 少用Regular Expression
- 為每個td取專屬名字, 利用$("#...")找元素
- 直接存取elem.propName取代$(elem).data("propName")
非良好慣例,但真的變快很多 - $(node).text("...")改寫成node.innerHTML = "..."
因指定的文字內容很單純(純數字),所以可用這種不周全的寫法瓜代。直接寫Javascript不用jQuery,速度變快蠻多,但犠牲了相容性。 - 不需要串接且會被大量呼叫的Plugin,就把return this.each拿掉
注意: 上述橘色斜體字部分表示非正規建議做法,純粹因加速而走的偏鋒,大家參考時要特別注意,切忌誤用!! (有個比喻,就像賽車都不裝方向燈跟喇叭一樣,是針對特殊情境才有的設計,可別任意仿效改裝你的愛車)
Comments
# by mOMo
哈,看到黑暗大這篇的內容,也讓我想起之前一個case的夢彥,當時也是類似像這個Excel表的需求,只不過,是用在計算成績,使用者可以輸入每個球員的成績(高爾夫球),並每輸入一個洞數的成績就要把整個row (tr)作成績運算,也是遇到有點慢的問題,目前最高筆數是350人,也就是350*20的table,想了很多處理方式,不過有一點跟您作的一樣,就是原本的設計將數值直接存在td裡,讀寫時都要涉及UI元素的存取,是效能不彰的最大元凶。我後來利用Javascript Object在背後建立出對應表格的完整資料陣列,每次重算時先在物件陣列裡算好,因為直接操作DOM物件實在慢啊!
# by Ted
其實IE 6,7也有toolbar做到inspect DOM,跟javascript console, http://www.debugbar.com/ 不過沒有"Slow Script警告"這種功能就是了。
# by maxi
屌阿!我還沒有學會怎麼用
# by 匿名
@@ 這個方法不錯,但我還有以下疑慮。 如果把資料copy一份到Javascript裡,資源會不會佔很大? = =||| 最害怕它用完又不放出來。(~. ~ 又要想Closure) 把IE7升到IE8,使用它的相容模式,是否現在等於在IE7下的效果? Orz 不然的話,又要開啟VM來測試。
# by Jeffrey
to 匿名,背後Javascript物件裡多是些number, string的簡單屬性,佔用記憶體不致於大多。相形之下,如果想將資料存在DOM元素上省空間,付出的效率代價有到"致命"的程度。 我用window.myArray的方式來保存,以達到隨時可用的涵蓋性,倒沒用Closure解決。(怕生出一堆黏在函數上的分身) 據我所知,IE8的IE7相容模式,還是不完全等於IE7,但多是一些安全防護相關的特性,細節可以參考這篇: http://blogs.msdn.com/ie/archive/2009/03/12/site-compatibility-and-ie8.aspx Differences between IE8 Compatibility View and IE7
# by 博士家教中心
感謝你,不然可能完全不會去碰 ie 8,也不會去發現這種有趣的工具了
# by walter
請問我在 IE8 Profiler 按下 Start Profiling,操作完後再按下 Stop Profiling 後,URL 及 Line Number 都是空的,是否要先做什麼設定呢?謝謝!
# by Jeffrey
to walter, 若是內建的Javascript函數指令,是不會顯示URL及line number的(如我圖例中的Array.join())。寫在HTML及js中的Javascript自訂函數則會顯示檔案URL及行數,應不需額外設定才是。
# by condos in hyde park
Hi I like this comment and it is so informational and I am gonna save it. One thing to say the Indepth analysis you have done is greatly remarkable.
# by Eden
請問 Yahoo!News 會促使 IE8 當機的原因是什麼?
# by Jeffrey
to Eden, 經常性當機亦或是某個特別操作才會發生? 依經驗,大型入口網站改版時都經過測試,不致與現役瀏覽器版本嚴重不相容,而IE當機問題很高的比例與附加元件(Add-On)有關,建議你停用所有附加元件後瀏覽看看,若停用後正常,即可開始在附加元件中找尋凶手。 如果是某個特殊操作才會當機,可提供給大家幫你驗證或直接反應給Yahoo客服。
# by Eden
to Jeffrey Yahoo!News 關於那部份我還是希望你幫忙測試一下 不知道跟我CPU是屬雙核心有沒有關係 因為他是卡在留言版那邊
# by Jeffrey
to Eden,需要有明確的URL(如果有當機畫面更好),大家才能幫你測試哦~
# by Eden
to Jeffrey http://tw.news.yahoo.com 我現在的狀況是只要點選任何一篇新聞都會當機
# by Jeffrey
to Eden, 我的測試: IE8.0.6001.18702 on Windows XP SP3, 瀏覽tw.news.yahoo.com時,出現JavaScript錯誤(與videoplayer, flash4物件有關),但未出現當機。
# by Edrn
請問與XP SP2 ,SP3有沒有關係?
# by Jeffrey
to Eden, 很難說,目前的線索不多,難以論斷。我建議有幾個偵辦方向: 1)手邊如果找得到其他類似的IE8環境,試試是否也有當機問題? 若無,代表屬主機環境的因素造成,可試著找出主機環境間的差異。 2)是否只有Yahoo News會當機,其他任何網站都不會? 若是,則清查Yahoo News用了什麼特殊元件;若有其他網站也有狀況,會當機的網頁有什麼共通點? 3)試著停用IE的所有附加元件(Add-On)再瀏覽,若因此不當機,則逐一啟用附加元件重新驗證,以盤查誰是凶手。 4)試著重設IE[http://support.microsoft.com/kb/923737/zh-tw]看看。
# by Eden
to Jeffrey 改灌SP3以後問題就解決了,可是到底是為什麼?
# by 王王
為什麼要少用regular expression
# by Jeffrey
to 王王,Regular Expression功能強大,但相對地在執行效能上不如單純的字串搜尋或取代,因此在可以用indexOf()、一般replace()解決的需求,避用RegExp可以提升網頁執行速度。
# by maxi
但直的變快很多?? 還是真的變快很多??
# by Jeffrey
to maxi, 應為"真的變快很多"。謝謝指正。