ส่วนสำคัญของวงจรการพัฒนาของ Microsoft คือการปรับประสิทธิภาพของผลิตภัณฑ์ การปรับแต่งประสิทธิภาพก็เป็นหนึ่งในประเด็นสำคัญที่นักพัฒนาควรใส่ใจ หลังจากหลายปีของการพัฒนา อุตสาหกรรมได้เรียนรู้มากมายเกี่ยวกับวิธีการเพิ่มประสิทธิภาพการทำงานของโปรแกรม Win32
ปัญหาประการหนึ่งที่นักพัฒนาเผชิญอยู่ในปัจจุบันคือพวกเขาไม่ค่อยเข้าใจว่าอะไรทำให้เพจ DTHML และ HTML ทำงานเร็วหรือช้า แน่นอนว่ามีวิธีแก้ไขง่ายๆ บางอย่าง เช่น การไม่ใช้รูปภาพขนาด 2MB เราได้ใช้เทคนิคที่น่าสนใจอื่นๆ เพื่อปรับปรุงประสิทธิภาพของเพจ DHTML เราหวังว่าเทคนิคเหล่านี้จะช่วยคุณปรับปรุงประสิทธิภาพของเพจของคุณเองได้
ที่นี่ฉันใช้ตัวอย่างของโปรแกรมเพื่อสร้างตาราง document.createElement() และ element.insertBefore() วิธีการใช้เพื่อสร้างตารางที่มี 1,000 แถว (แถว) แต่ละแถวมีหนึ่งคอลัมน์ (เซลล์) เนื้อหาที่อยู่ในเซลล์เรียกว่า "ข้อความ" รหัสนี้จะแย่แค่ไหน? โปรแกรมขนาดเล็กดังกล่าวมีพื้นที่สำหรับการปรับเปลี่ยนเท่าใด โปรดดูบทนำ
ในตอนแรก ฉันเขียนโปรแกรมที่ฉันคิดว่าน่าจะเร็ว ฉันพยายามหลีกเลี่ยงปัญหาระดับต่ำบางอย่าง เช่น ไม่ได้กำหนดตัวแปรอย่างชัดเจน หรือใช้ VBScript และ JavaScript พร้อมกันในหน้าเดียว โปรแกรมจะเป็นดังนี้:
<html>
<ร่างกาย>
<สคริปต์>
var tbl, tbody, tr, td, ข้อความ, i, สูงสุด;
สูงสุด = 1,000;
tbl = document.createElement("ตาราง");
tbl.border = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore (tbody, null);
document.body.insertBefore (tbl, null);
สำหรับ (i=0; i<สูงสุด; i++) {
tr = document.createElement("TR");
td = document.createElement("TD");
text = document.createTextNode("ข้อความ");
td.insertBefore (ข้อความ, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
-
</สคริปต์>
</ร่างกาย>
</html>
รันโปรแกรมนี้บนเครื่อง PII233/64MB/NT4.0/IE5.0 เพจนี้ถูกโหลดจากเครื่องนี้ เวลาตั้งแต่เริ่มโหลดเพจจนถึงเพจเงียบสนิท (เหตุการณ์ทั้งหมดถูกเรียกใช้และการแสดงผลหน้าจอเสร็จสมบูรณ์) คือ 2328 มิลลิวินาที ซึ่งเป็นบรรทัดฐานของการทดสอบนี้ (ฉันเรียกว่า Test1)
ในหน้านี้ การดำเนินการที่ใช้เวลานานมากคือการอ้างอิงออบเจ็กต์ส่วนกลางบ่อยครั้ง เช่น "เอกสาร" "เนื้อหา" "หน้าต่าง" ฯลฯ การอ้างอิงตัวแปรโกลบอลที่คล้ายกันทั้งหมดนี้มีราคาแพงกว่าการอ้างอิงตัวแปรโลคอลตัวเดียวมาก
ดังนั้นฉันจึงพยายามปรับปรุงครั้งแรก: แคช (แคช) document.body ลงในตัวแปรท้องถิ่น "theBody":
เพิ่มรหัสต่อไปนี้:
var theBody = document.body;
จากนั้นแก้ไขบรรทัดนี้:
document.body.insertBefore(tbl, null);
เปลี่ยนเป็น:
theBody.insertBefore(tbl, null);
ดูตัวอย่างที่สอง
การปรับเปลี่ยนนี้ไม่ส่งผลต่อเวลาโดยรวมมากนัก แต่สั้นลงเพียง 3 ms เท่านั้น แต่ได้แสดงให้เห็นว่าหากมีอ็อบเจ็กต์ document.body ในลูปและมีการแก้ไขการอ้างอิง คุณจะได้รับประโยชน์อย่างมาก
ต่อมา ฉันแคชวัตถุเอกสาร - ในการทดสอบของเรา วัตถุเอกสารถูกอ้างอิงทั้งหมด 3,002 ครั้ง รหัสที่แก้ไขจะเป็นดังนี้:
<html>
<ร่างกาย>
<สคริปต์>
var tbl, tbody, tr, td, ข้อความ, i, สูงสุด;
สูงสุด = 1,000;
var theDoc = เอกสาร;
var theBody = theDoc.body;
tbl = theDoc.createElement("ตาราง");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore (tbody, null);
theBody.insertBefore (tbl, null);
สำหรับ (i=0; i<สูงสุด; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("ข้อความ");
td.insertBefore (ข้อความ, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
-
</สคริปต์>
</ร่างกาย>
</html>
ดูตัวอย่างที่สาม
เวลาทำงานนี้เพียง 2100ms ประหยัดเวลาได้ประมาณ 10% การใช้ตัวแปรท้องถิ่นแทนการอ้างอิงออบเจ็กต์เอกสารโดยตรงจะบันทึกค่าเฉลี่ย 0.4 มิลลิวินาทีในแต่ละครั้ง
วิธีทั่วไปในการเพิ่มประสิทธิภาพการทำงานคือการตั้งค่าแอตทริบิวต์ "defer" ในแท็ก <SCRIPT> เมื่อไม่จำเป็นต้องเรียกใช้สคริปต์ทันที (สคริปต์ทันทีไม่อยู่ในบล็อกฟังก์ชัน ดังนั้นสคริปต์จะถูกดำเนินการในระหว่างกระบวนการโหลด) หลังจากตั้งค่าแอตทริบิวต์ "defer" แล้ว IE ไม่จำเป็นต้องรอให้สคริปต์โหลดและดำเนินการ วิธีนี้จะทำให้เพจโหลดเร็วขึ้น โดยทั่วไปแล้ว นี่ยังหมายความว่าสคริปต์ทันทีจะถูกวางไว้ในบล็อกฟังก์ชันได้ดีที่สุด และจัดการฟังก์ชันในตัวจัดการ onload ของเอกสารหรืออ็อบเจ็กต์เนื้อหา คุณสมบัตินี้มีประโยชน์เมื่อมีสคริปต์บางตัวที่จำเป็นต้องดำเนินการตามการกระทำของผู้ใช้ เช่น การคลิกปุ่มหรือเลื่อนเมาส์ไปยังพื้นที่ใดพื้นที่หนึ่ง แต่เมื่อมีสคริปต์บางตัวที่จำเป็นต้องดำเนินการระหว่างหรือหลังจากโหลดเพจแล้ว การใช้แอตทริบิวต์ defer ก็มีข้อดีไม่มากนัก
ต่อไปนี้เป็นโค้ดเวอร์ชันที่แก้ไขโดยใช้แอตทริบิวต์ defer:
<html>
<body onload="init()">
<เลื่อนสคริปต์>
ฟังก์ชั่น init() {
var tbl, tbody, tr, td, ข้อความ, i, สูงสุด;
สูงสุด = 1,000;
var theDoc = เอกสาร;
var theBody = theDoc.body;
tbl = theDoc.createElement("ตาราง");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore (tbody, null);
theBody.insertBefore (tbl, null);
สำหรับ (i=0; i<สูงสุด; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("ข้อความ");
td.insertBefore (ข้อความ, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
-
-
</สคริปต์>
</ร่างกาย>
</html>
ดูตัวอย่างที่สี่
เวลาของการทดสอบนี้คือ 2043 มิลลิวินาที นี่คือการเพิ่มขึ้น 12% เมื่อเทียบกับการทดสอบพื้นฐาน และสูงกว่าการทดสอบครั้งก่อน 2.5%
แน่นอนว่าวิธีการปรับปรุงที่เราพูดถึงด้านล่างนี้มีประโยชน์มาก แต่ก็ยุ่งยากกว่าเล็กน้อย เมื่อคุณต้องการสร้างองค์ประกอบแล้วแทรกลงในโครงสร้างที่มีลักษณะคล้ายต้นไม้ จะมีประสิทธิภาพมากกว่าในการแทรกองค์ประกอบลงใน Trunk โดยตรง แทนที่จะแทรกลงในทรีย่อยขนาดใหญ่ก่อนแล้วจึงแทรกทรีย่อยขนาดใหญ่ลงใน Trunk ตัวอย่างเช่น หากคุณสร้างตารางที่มีหนึ่งคอลัมน์ในแต่ละแถวและมีข้อความบางส่วนในคอลัมน์ คุณสามารถทำได้:
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>
การทดสอบทั้งสี่ด้านบนทั้งหมดใช้วิธีการเดิม เราใช้วิธีหลังสำหรับการทดสอบครั้งที่ห้า รหัสจะเป็นดังนี้:
<html>
<body onload="init()">
<เลื่อนสคริปต์>
ฟังก์ชั่น init() {
var tbl, tbody, tr, td, ข้อความ, i, สูงสุด;
สูงสุด = 1,000;
var theDoc = เอกสาร;
var theBody = theDoc.body;
tbl = theDoc.createElement("ตาราง");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore (tbody, null);
theBody.insertBefore (tbl, null);
สำหรับ (i=0; i<สูงสุด; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("ข้อความ");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore (ข้อความ, null);
-
-
</สคริปต์>
</ร่างกาย>
</html>
ดูตัวอย่างที่ห้า
Test5 ใช้เวลาเพียง 1649ms นี่เป็นการปรับปรุง 25% จากการทดสอบครั้งล่าสุดและเร็วกว่าการทดสอบพื้นฐานเกือบ 30%
การแก้ไขในภายหลังเกิดขึ้นโดยใช้สไตล์ชีตที่สร้างไว้ล่วงหน้า ความกว้างของคอลัมน์ของตารางที่ใช้สไตล์ชีตที่สร้างไว้ล่วงหน้าหรือตั้งค่าผ่านแท็ก <COL> เมื่อไม่มีแท็ก <COL> ความกว้างของแต่ละคอลัมน์จะกระจายเท่าๆ กัน เนื่องจากไม่จำเป็นต้องคำนวณขนาดสำหรับแต่ละคอลัมน์ใหม่ ฯลฯ การใช้สไตล์ชีตจึงช่วยเพิ่มประสิทธิภาพได้จริง โดยเฉพาะอย่างยิ่งเมื่อจำนวนคอลัมน์ในตารางมีขนาดใหญ่
รหัสในการเพิ่มสไตล์ชีต (CSS) นั้นง่ายมากดังนี้:
tbl.style.tableLayout = "fixed";
ดูตัวอย่างที่หก
เนื่องจากตารางในการทดสอบของเรามีเพียงคอลัมน์เดียว การเปลี่ยนแปลงนี้จึงปรับปรุงประสิทธิภาพหน้าเว็บได้เพียง 1.6% หากมีคอลัมน์มากขึ้น ประสิทธิภาพก็จะเพิ่มมากขึ้น
การทดสอบสองครั้งล่าสุดเปลี่ยนวิธีการแทรกข้อความลงในตาราง ในการทดสอบก่อนหน้านี้ เราสร้าง TextNode ก่อนแล้วจึงแทรกลงใน TD ใน Test7 เราระบุข้อความที่รวมผ่าน InnerText แทน รหัสที่แก้ไขคือ:
td.innerText = "Text";
ดูตัวอย่างที่เจ็ด
น่าประหลาดใจที่การเปลี่ยนแปลงนี้เกิดขึ้นอย่างมาก โดยปรับปรุงประสิทธิภาพ 9% จากครั้งล่าสุด และปรับปรุงประสิทธิภาพทั้งหมด 36% จากรุ่นดั้งเดิม ช่วงเวลาตั้งแต่ 2323ms แรกถึง 1473ms สุดท้าย
ตอนนี้ เกือบทุกคนรู้แล้วว่าการใช้ element.innerHTML นั้นช้ามาก เพื่อดูว่ามันช้าแค่ไหน ฉันได้ทำการทดสอบครั้งสุดท้าย: การแทรกข้อความโดยใช้ innerHTML แทน innerText สิ่งนี้จะลดประสิทธิภาพลงอย่างมาก เวลาดังกล่าวอยู่ที่ 3,375 มิลลิวินาที ซึ่งช้ากว่าการทดสอบครั้งล่าสุด 80% และช้ากว่าการทดสอบพื้นฐาน 45% แน่นอนว่า innerHTML ใช้เวลานานมาก
การปรับแต่งประสิทธิภาพของเพจ HTML นั้นคล้ายคลึงกับการปรับแต่งประสิทธิภาพของแอปพลิเคชั่น Win32 คุณจำเป็นต้องรู้ว่าอะไรช้าและอะไรเร็ว ฉันหวังว่าวิธีการเหล่านี้สามารถช่วยคุณปรับปรุงประสิทธิภาพของเพจได้