提高代碼效能技巧談—以建立千行表格為例

來源:互聯網
上載者:User
建立|技巧|效能

微軟的開發週期中很重要的一塊是調整產品的效能。效能調整也是開發人員應當留心的關鍵區段之一。 經過多年發展,業界對於如何最佳化Win32程式效能已經有非常多的瞭解。

現在開發人員遇到的問題之一是不太清楚是什麼導致DTHML和HTML頁面運行快或者慢。當然,有一些很簡單的方法——比如不要使用2MB大的圖片。我們曾經使用過另外一些有趣的技巧提高了DHTML頁面的效能,希望它們能協助你改善自己的頁面效能。

這裡我使用了一個建立Table的程式例子。其中用document.createElement()和element.insertBefore()方法建立了1000行(Row)的表(Table)。每行有一列(Cell)。Cell中包含的內容稱為"Text"。這段代碼能有多糟呢?這麼小的程式又能有多大調整餘地呢?請看介紹。

一開始我寫了一段自認為會很快的程式,我盡量避免一些低級問題----像沒有顯式定義變數、或者在一個頁面中同時使用VBScript和javascript。程式如下:

<html>
<body>
<script>
var tbl, tbody, tr, td, text, i, max;
max = 1000;

tbl = document.createElement("TABLE");
tbl.border = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore(tbody, null);
document.body.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = document.createElement("TR");
td = document.createElement("TD");
text = document.createTextNode("Text");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>


在PII233/64MB記憶體/NT4.0/IE5.0的機器上運行這段程式。頁面從本機上裝載。從開始裝載頁面到頁面完全安靜下來(所有的事件均已經運行,螢幕顯示完成)的時間為2328毫秒,這也是本次測試的基準(我稱之為Test1)。

這個頁面中,一個很耗時的操作是頻繁引用全域對象,如“document”、“body”、“window”等。引用所有這些類似的全域變數遠比引用一個本地變數代價高昂。

因此我作了第一次改進嘗試:緩衝(Cache)document.body 到本地變數“theBody”中:

增加了如下代碼:

var theBody = document.body;
然後修改這一行:

document.body.insertBefore(tbl, null);
將之改為:

theBody.insertBefore(tbl, null);
View the second sample.

這次修改並沒有太大影響到整體時間,它只縮短了3 ms。但它已經表明,如果在迴圈中也有document.body對象而對其引用做出修改,帶來的好處將是可觀的。

隨後,我緩衝了document對象----在我們這個測試中,document對象共被引用了3002次。修改後代碼如下:

<html>
<body>
<script>
var tbl, tbody, tr, td, text, i, max;
max = 1000;
var theDoc = document;
var theBody = theDoc.body;

tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Text");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
View the third sample.

此次已耗用時間只有2100ms,節約了大約10%的時間。使用本地變數而不是直接引用document對象平均每次節約了0.4毫秒。

一個常用的最佳化效能的方法是:當指令碼不需要立即運行時,在<SCRIPT>標籤中設定“defer”屬性。 (立即指令碼沒有被包含在一個function塊中,因此會在載入過程中執行。) 設定“defer”屬性後,IE就不必等待該指令碼裝載和執行完畢。這樣頁面載入會更快。一般來說,這也表明立即指令碼最好放在function塊中,並在document或者body對象的onload 控制代碼中處理該函數。在有一些指令碼需要依賴使用者操作而執行時----例如點擊按鈕,或者移動滑鼠到某個地區----使用該屬性非常有用。但當有一些指令碼需要在頁面載入過程中或載入完成後執行,使用defer屬性得到的好處就不太大。

下面是使用了defer屬性修改後的代碼版本:

<html>
<body >
<script defer>
function init() {
var tbl, tbody, tr, td, text, i, max;
max = 1000;
var theDoc = document;
var theBody = theDoc.body;

tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Text");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
}
</script>
</body>
</html>
View the fourth sample.

這次測試的時間為2043 ms。相對基準測試提高了12%,比上次測試提高了2.5%。

下面我們談到的一個改進方法非常有用,當然也稍微麻煩一點。當需要建立元素然後將其插入樹狀的結構中時,將其直接插入到主幹中效率更高----而不是首先將其插入大的子樹,然後再將大的子樹插入主幹。例如,如果你建立一個每行有一列、列中有一些文字的表,你可以這樣做:

1. 建立<TR>

2. 建立<TD>

3. 建立TextNode節點

4. 將TextNode 插入<TD>

5. 將<TD> 插入到 <TR>

6. 將<TR>插入到TBODY

當它要比下面的方法慢一些:

1. 建立<TR>

2. 建立<TD>

3. 建立TextNode

4. 將<TR> 插入到TBODY

5. 將<TD> 插入到<TR>

6. 將TextNode插入到<TD>

上面的四次測試使用的都是前一種方法。我們用後一種方法進行第5次測試。代碼如下:

<html>
<body >
<script defer>
function init() {
var tbl, tbody, tr, td, text, i, max;
max = 1000;
var theDoc = document;
var theBody = theDoc.body;

tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Text");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore(text, null);
}
}
</script>
</body>
</html>
View the fifth sample.

Test5隻需1649ms。這比上次測試提高了25%,比基準快了幾乎30%。

隨後的修改是使用了預製的樣式表。使用了預製樣式表的表格列寬或者是通過<COL>標籤設定,沒有<COL>標籤時,每列的寬度均勻分布。因為不需要對每一列重新計算大小等,使用樣式表實際上提高了效能,尤其當表格中的列數很多時。

增加樣式表(CSS)的代碼非常簡單,如下:

tbl.style.tableLayout = "fixed";
View the sixth sample.

因為我們測試中的表格只有一列,這種改變只提高了頁面1.6%的效能。如果有更多的列,效能增加會更多。

最後兩次測試改變了將文字插入到表格中的方法。前面的測試中,我們都先建立一個TextNode ,然後將其插入到TD中。在Test7中, 取而代之,我們通過innerText 指定包含的文字。修改的代碼是:

td.innerText = "Text";
View the seventh sample.

令人驚奇的是,這次修改產生的差異很大----比上次提高了9%的效能,比最初總共提高了36%的效能。時間從最初的2323ms到最後的1473ms。

現在,幾乎人人都知道使用element.innerHTML 非常慢. 為了看看究竟它如何慢,我做了最後一次測試:使用 innerHTML替代innerText插入文字。這大大降低了效能。時間達到3375ms,比上次測試慢了80%,比基準測試慢了45%。顯然,innerHTML是非常耗時的。

調整HTML頁面效能類似於調整Win32應用程式效能;需要知道什麼慢,什麼快。希望這些方法能幫你提高頁面效能。



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。