近期發現有人在ASP.Net項目開發中使用一種叫dtree的樹狀列表組件加載緩慢。這也是筆者撰寫本章的動機。毛主席教導我們,做事要發現問題,分析問題和解決問題。首先我們發現了已有的樹狀列表WEB控件加載緩慢的問題,接下來就很自然的是分析問題了。
下圖就是dtree 運行界面的例子
分析問題
現在我們分析問題,對使用dtree生成樹狀列表的程序代碼的分析,可以了解程序運行過程如下圖所示
在這樣的程序中,首先服務器端的C#代碼查詢數據庫,然後根據查詢所得數據拼湊出一個Javascript代碼字符串,然後發往客戶端,客戶端浏覽器獲得這個Javascript代碼字符串並開始執行它,而在Javascript腳本中也是字符串拼湊出一段HTML代碼字符串,然後使用浏覽器提供的 document.write方法或obj.innerHTML屬性將生成的HTML字符串填充到Html頁面中進行展示。
這是是分析了dtree的流程,但使用其他的一些樹狀列表控件也大體如此。
現在我們根據這個流程圖來判斷是哪個環節速度緩慢。基本上數據庫本身查詢速度是沒問題;將查詢結果傳遞到C#程序中問題也不大,因為一般的數據庫服務器和ASP.Net程序是在一台電腦上或者同一個高速局域網中;C#程序生成Javascript字符串的過程也是沒多大問題,因為C#運行速度是相當的快的,而且還有StringBuilder來加速字符串拼湊操作,因此只要邏輯算法沒有問題,速度是有保障的。總體來說服務器端內部是沒有速度問題。
將Javascript字符串通過網絡從服務器端發送到客戶端,所花的的時間是字符串長度除以網絡傳輸速度,若WEB系統運行在高速的局域網中,則速度沒多大問題,但若WEB程序運行在緩慢的廣域網或英特網中,則Javascript字符串長度會比較大的影響程序運行速度。由於公司系統主要運行在局域網中,因此網絡傳輸速度不是主要問題。
在客戶端浏覽器中,浏覽器接受並執行Javascript腳本代碼,在Javascript腳本中使用字符串拼湊來生成用於展現樹狀列表的Html 字符串。Javascript代碼是解釋方式執行的,速度相當慢,而字符串拼湊操作也是比較緩慢的操作,Javascript中沒有任何手段來優化字符串拼湊操作。因此由Javascript代碼生成Html字符串的過程是緩慢的,這是一個速度瓶頸。
Javascript代碼還調用浏覽器提供的document.write函數或innerHTML屬性將生成的HTML字符串填充到頁面中,浏覽器會解析這個HTML代碼並展現出樹狀列表。由於document.write或innerHtml是運行在浏覽器內部的,外部程序無法控制,而且速度也不算慢,因此這裡也就沒有什麼好優化的。
經過上述分析,可以看到整個展現樹狀列表的過程中最緩慢的環節就是使用Javascript腳本來生成Html代碼字符串,其次就是數據從服務器端發送到客戶端的過程。若一個樹狀列表要顯示數千個節點,則Javascript腳本將拼湊出幾百K甚至過MB的Html字符串,這個過程是相當緩慢的,很容易導致IE浏覽器由於腳本運行過於緩慢而提示用戶是否繼續執行腳本。
因此Javascript腳本生成Html字符串將是我們主要的優化環節,也是新開發的樹狀列表控件的重點關注部分。