Monday, June 08, 2009 - 文章

好用到掉渣的IE8 Developer Tools--JS效能調校經驗

對我來說,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 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拿掉

注意: 上述橘色斜體字部分表示非正規建議做法,純粹因加速而走的偏鋒,大家參考時要特別注意,切忌誤用!! (有個比喻,就像賽車都不裝方向燈跟喇叭一樣,是針對特殊情境才有的設計,可別任意仿效改裝你的愛車)

搜尋

Go

<June 2009>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication