An important part of Microsoft's development cycle is adjusting product performance. Performance tuning is also one of the key areas that developers should pay attention to. After years of development, the industry has learned a lot about how to optimize the performance of Win32 programs.
One of the problems developers face today is that they don't quite understand what causes DTHML and HTML pages to run fast or slow. Of course, there are some simple solutions - such as not using 2MB images. We have used some other interesting techniques to improve the performance of DHTML pages. We hope they can help you improve the performance of your own pages.
Here I use an example of a program to create a Table. The document.createElement() and element.insertBefore() methods are used to create a table with 1000 rows (Row). Each row has one column (Cell). The content contained in the Cell is called "Text". How bad could this code be? How much room for adjustment does such a small program have? Please see the introduction.
At the beginning, I wrote a program that I thought would be fast. I tried to avoid some low-level problems-like not explicitly defining variables, or using VBScript and JavaScript at the same time in one page. The program is as follows:
<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>
Run this program on a PII233/64MB memory/NT4.0/IE5.0 machine. The page is loaded from this machine. The time from starting to load the page to the page completely quieting down (all events have been run and the screen display is completed) is 2328 milliseconds, which is also the baseline of this test (I call it Test1).
In this page, a very time-consuming operation is to frequently reference global objects, such as "document", "body", "window", etc. Referencing all these similar global variables is far more expensive than referencing one local variable.
So I made the first improvement attempt: cache (Cache) document.body into the local variable "theBody":
added the following code:
var theBody = document.body;
Then modify this line:
document.body.insertBefore(tbl, null);
Change it to:
theBody.insertBefore(tbl, null);
View the second sample.
This modification did not affect the overall time much, it only shortened 3 ms. But it has been shown that if there is also a document.body object in the loop and its reference is modified, the benefits will be considerable.
Subsequently, I cached the document object - in our test, the document object was referenced a total of 3002 times. The modified code is as follows:
<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.
This running time is only 2100ms, saving about 10% of the time. Using local variables instead of directly referencing the document object saved an average of 0.4 milliseconds each time.
A common way to optimize performance is to set the "defer" attribute in the <SCRIPT> tag when the script does not need to be run immediately. (The immediate script is not contained in a function block, so it will be executed during the loading process.) After setting the "defer" attribute, IE does not have to wait for the script to load and execute. This way the page will load faster. Generally speaking, this also means that immediate scripts are best placed in function blocks and handle the function in the onload handler of the document or body object. This property is useful when there are some scripts that need to be executed based on user actions - such as clicking a button or moving the mouse to a certain area. But when there are some scripts that need to be executed during or after the page is loaded, the benefits of using the defer attribute are not great.
The following is the modified version of the code using the defer attribute:
<html>
<body onload="init()">
<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.
The time of this test is 2043 ms. This is an increase of 12% relative to the baseline test and 2.5% higher than the previous test.
An improvement method we talk about below is very useful, of course, but a little more troublesome. When you need to create an element and then insert it into a tree-like structure, it is more efficient to insert it directly into the trunk--rather than first inserting it into a large subtree and then inserting the large subtree into the trunk. For example, if you create a table with one column in each row and some text in the column, you can do this:
1. Create <TR>
2. Create <TD>
3. Create TextNode node
4. Insert TextNode into <TD>
5 . Insert <TD> into <TR>
6. Insert <TR> into TBODY
When it is slower than the following method:
1. Create <TR>
2. Create <TD>
3. Create TextNode
4. Insert <TR > Insert into TBODY
5. Insert <TD> into <TR>
6. Insert TextNode into <TD>
The four tests above all use the former method. We used the latter method for the fifth test. The code is as follows:
<html>
<body onload="init()">
<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 only takes 1649ms. This is a 25% improvement over the last test and almost 30% faster than the baseline.
Subsequent modifications were made using pre-made stylesheets. The column width of a table that uses a pre-made style sheet or is set through the <COL> tag. When there is no <COL> tag, the width of each column is evenly distributed. Because there is no need to recalculate the size for each column, etc., using a style sheet actually improves performance, especially when the number of columns in the table is large.
The code to add a style sheet (CSS) is very simple, as follows:
tbl.style.tableLayout = "fixed";
View the sixth sample.
Because the table in our test only had one column, this change only improved page performance by 1.6%. If there are more columns, the performance increase will be even greater.
The last two tests changed the way text is inserted into the table. In the previous tests, we first created a TextNode and then inserted it into the TD. In Test7, instead, we specify the included text via innerText. The modified code is:
td.innerText = "Text";
View the seventh sample.
Surprisingly, the difference this modification made was huge—a 9% performance improvement over the last time, and a total of 36% performance improvement over the original. The time ranges from the first 2323ms to the last 1473ms.
Now, almost everyone knows that using element.innerHTML is very slow. To see just how slow it is, I did one last test: inserting text using innerHTML instead of innerText. This greatly reduces performance. The time reached 3375ms, which was 80% slower than the last test and 45% slower than the baseline test. Obviously, innerHTML is very time consuming.
Tuning HTML page performance is similar to tuning Win32 application performance; you need to know what is slow and what is fast. I hope these methods can help you improve page performance.