แผงประสิทธิภาพที่ทำงานเร็วขึ้น 400% ผ่านการรับรู้

Andrés Olivares
Andrés Olivares
Nancy Li
Nancy Li

ไม่ว่าคุณจะพัฒนาแอปพลิเคชันประเภทใด การเพิ่มประสิทธิภาพและตรวจสอบว่าแอปพลิเคชันโหลดได้อย่างรวดเร็วและมีการโต้ตอบที่ราบรื่นเป็นสิ่งสำคัญอย่างยิ่งต่อประสบการณ์ของผู้ใช้และความสำเร็จของแอปพลิเคชัน วิธีหนึ่งในการทำเช่นนี้คือการตรวจสอบกิจกรรมของแอปพลิเคชันโดยใช้เครื่องมือสร้างโปรไฟล์เพื่อดูสิ่งที่เกิดขึ้นเบื้องหลังขณะที่แอปทํางานในช่วงระยะเวลาหนึ่ง แผงประสิทธิภาพในเครื่องมือสำหรับนักพัฒนาเว็บเป็นเครื่องมือสร้างโปรไฟล์ที่ยอดเยี่ยมในการวิเคราะห์และเพิ่มประสิทธิภาพของเว็บแอปพลิเคชัน หากแอปของคุณทํางานใน Chrome แอปจะแสดงภาพรวมโดยละเอียดว่าเบราว์เซอร์กําลังทําอะไรอยู่ขณะที่แอปพลิเคชันของคุณทํางาน การทำความเข้าใจกิจกรรมนี้จะช่วยให้คุณระบุรูปแบบ จุดคอขวด และจุดที่มีประสิทธิภาพสูงซึ่งคุณสามารถดำเนินการเพื่อปรับปรุงประสิทธิภาพได้

ตัวอย่างต่อไปนี้จะอธิบายวิธีใช้แผงประสิทธิภาพ

การตั้งค่าและสร้างสถานการณ์การสร้างโปรไฟล์ขึ้นใหม่

เมื่อไม่นานมานี้ เราได้ตั้งเป้าหมายที่จะทำให้แผงประสิทธิภาพทำงานได้ดีขึ้น โดยเฉพาะอย่างยิ่ง เราต้องการให้โหลดข้อมูลประสิทธิภาพจำนวนมากได้เร็วขึ้น เช่น เมื่อสร้างโปรไฟล์กระบวนการที่ใช้เวลานานหรือซับซ้อน หรือบันทึกข้อมูลที่มีรายละเอียดสูง เพื่อให้บรรลุเป้าหมายนี้ เราจึงต้องทำความเข้าใจวิธีการทำงานของแอปพลิเคชันและเหตุผลที่แอปพลิเคชันทำงานในลักษณะดังกล่าวก่อน ซึ่งทำได้โดยใช้เครื่องมือสร้างโปรไฟล์

ดังที่คุณอาจทราบ เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome เองก็เป็นเว็บแอปพลิเคชัน ดังนั้น คุณจึงสร้างโปรไฟล์ได้โดยใช้แผงประสิทธิภาพ หากต้องการสร้างโปรไฟล์ของแผงนี้เอง คุณสามารถเปิดเครื่องมือสำหรับนักพัฒนาเว็บ แล้วเปิดอินสแตนซ์เครื่องมือสำหรับนักพัฒนาเว็บอีกอินสแตนซ์ที่แนบมากับแผงนี้ ที่ Google การตั้งค่านี้เรียกว่า DevTools-on-DevTools

เมื่อตั้งค่าเรียบร้อยแล้ว คุณต้องสร้างสถานการณ์ที่จะสร้างโปรไฟล์ขึ้นมาใหม่และบันทึก เพื่อไม่ให้เกิดความสับสน เราจะเรียกหน้าต่าง DevTools เดิมว่า "อินสแตนซ์ DevTools แรก" และเรียกหน้าต่างที่ตรวจสอบอินสแตนซ์แรกว่า "อินสแตนซ์ DevTools ที่สอง"

ภาพหน้าจอของอินสแตนซ์เครื่องมือสำหรับนักพัฒนาเว็บที่ตรวจสอบองค์ประกอบในเครื่องมือสำหรับนักพัฒนาเว็บเอง
เครื่องมือสำหรับนักพัฒนาเว็บในเครื่องมือสำหรับนักพัฒนาเว็บ: การตรวจสอบเครื่องมือสำหรับนักพัฒนาเว็บด้วยเครื่องมือสำหรับนักพัฒนาเว็บ

ในอินสแตนซ์ที่ 2 ของเครื่องมือสำหรับนักพัฒนาเว็บ แผงประสิทธิภาพ (ซึ่งต่อไปนี้จะเรียกว่าแผง perf) จะสังเกตอินสแตนซ์แรกของเครื่องมือสำหรับนักพัฒนาเว็บเพื่อสร้างสถานการณ์ใหม่ ซึ่งจะโหลดโปรไฟล์

ในอินสแตนซ์ DevTools ที่ 2 จะเริ่มการบันทึกแบบสด ส่วนในอินสแตนซ์แรก จะโหลดโปรไฟล์จากไฟล์ในดิสก์ ระบบจะโหลดไฟล์ขนาดใหญ่เพื่อสร้างโปรไฟล์ประสิทธิภาพการประมวลผลอินพุตขนาดใหญ่อย่างแม่นยำ เมื่อทั้ง 2 อินสแตนซ์โหลดเสร็จแล้ว คุณจะเห็นข้อมูลการจัดทำโปรไฟล์ประสิทธิภาพ ซึ่งโดยทั่วไปเรียกว่าการติดตาม ในอินสแตนซ์ที่ 2 ของเครื่องมือสำหรับนักพัฒนาเว็บในแผง Perf ที่โหลดโปรไฟล์

สถานะเริ่มต้น: ระบุโอกาสในการปรับปรุง

หลังจากโหลดเสร็จแล้ว เราสังเกตเห็นสิ่งต่อไปนี้ในอินสแตนซ์แผงประสิทธิภาพที่ 2 ในภาพหน้าจอถัดไป มุ่งเน้นที่กิจกรรมของเทรดหลัก ซึ่งจะปรากฏภายใต้แทร็กที่มีป้ายกำกับว่าหลัก จะเห็นได้ว่ามีกลุ่มกิจกรรมขนาดใหญ่ 5 กลุ่มในแผนภูมิเปลวไฟ ซึ่งประกอบด้วยงานที่ใช้เวลาในการโหลดนานที่สุด เวลาทั้งหมดของงานเหล่านี้คือประมาณ 10 วินาที ในภาพหน้าจอต่อไปนี้ เราใช้แผงประสิทธิภาพเพื่อมุ่งเน้นที่กลุ่มกิจกรรมแต่ละกลุ่มเพื่อดูว่ามีอะไรบ้าง

ภาพหน้าจอของแผงประสิทธิภาพในเครื่องมือสำหรับนักพัฒนาเว็บที่ตรวจสอบการโหลดของการติดตามประสิทธิภาพในแผงประสิทธิภาพของอินสแตนซ์เครื่องมือสำหรับนักพัฒนาเว็บอีกอินสแตนซ์หนึ่ง โปรไฟล์จะใช้เวลาโหลดประมาณ 10 วินาที โดยส่วนใหญ่แล้ว เวลาดังกล่าวจะแบ่งออกเป็น 5 กลุ่มกิจกรรมหลัก

กลุ่มกิจกรรมแรก: งานที่ไม่จำเป็น

เราพบว่ากลุ่มกิจกรรมแรกเป็นโค้ดเดิมที่ยังคงทำงานอยู่ แต่จริงๆ แล้วไม่จำเป็น กล่าวโดยสรุปคือ ทุกอย่างที่อยู่ใต้บล็อกสีเขียวที่มีป้ายกำกับว่า processThreadEvents เป็นความพยายามที่สูญเปล่า ซึ่งเป็นวิธีที่ได้ผลลัพธ์อย่างรวดเร็ว การนำการเรียกฟังก์ชันดังกล่าวออกช่วยประหยัดเวลาได้ประมาณ 1.5 วินาที เยี่ยมเลย

กลุ่มกิจกรรมที่ 2

ในกลุ่มกิจกรรมที่ 2 โซลูชันไม่ได้ง่ายเหมือนกลุ่มแรก buildProfileCalls ใช้เวลาประมาณ 0.5 วินาที และเป็นสิ่งที่หลีกเลี่ยงไม่ได้

ภาพหน้าจอของแผงประสิทธิภาพในเครื่องมือสำหรับนักพัฒนาเว็บที่ตรวจสอบอินสแตนซ์แผงประสิทธิภาพอื่น งานที่เชื่อมโยงกับฟังก์ชัน buildProfileCalls จะใช้เวลาประมาณ 0.5 วินาที

ด้วยความสงสัย เราจึงเปิดใช้ตัวเลือกหน่วยความจำในแผงประสิทธิภาพเพื่อตรวจสอบเพิ่มเติม และพบว่ากิจกรรม buildProfileCalls ก็ใช้หน่วยความจำมากเช่นกัน ที่นี่คุณจะเห็นว่ากราฟเส้นสีน้ำเงินเพิ่มขึ้นอย่างรวดเร็วในช่วงเวลาที่ buildProfileCalls ทำงาน ซึ่งบ่งบอกถึงการรั่วไหลของหน่วยความจำที่อาจเกิดขึ้น

ภาพหน้าจอของโปรไฟล์หน่วยความจำในเครื่องมือสำหรับนักพัฒนาเว็บที่ประเมินการใช้หน่วยความจำของแผงประสิทธิภาพ เครื่องมือตรวจสอบแนะนำว่าฟังก์ชัน buildProfileCalls เป็นสาเหตุที่ทำให้เกิดหน่วยความจำรั่ว

เพื่อตรวจสอบข้อสงสัยนี้ เราจึงใช้แผงหน่วยความจำ (อีกแผงหนึ่งใน DevTools ซึ่งแตกต่างจากลิ้นชักหน่วยความจำในแผงประสิทธิภาพ) ในแผงหน่วยความจำ มีการเลือกประเภทการสร้างโปรไฟล์ "การสุ่มตัวอย่างการจัดสรร" ซึ่งบันทึกสแนปชอตฮีปสำหรับแผงประสิทธิภาพที่โหลดโปรไฟล์ CPU

ภาพหน้าจอของสถานะเริ่มต้นของโปรไฟล์หน่วยความจำ ตัวเลือก "การสุ่มตัวอย่างการจัดสรร" จะไฮไลต์ด้วยกรอบสีแดง และระบุว่าตัวเลือกนี้เหมาะที่สุดสำหรับการสร้างโปรไฟล์หน่วยความจำ JavaScript

ภาพหน้าจอต่อไปนี้แสดงภาพรวมฮีปที่รวบรวมไว้

ภาพหน้าจอของโปรไฟล์หน่วยความจำ โดยเลือกการดำเนินการตามชุดที่ใช้หน่วยความจำมาก

จาก Heap Snapshot นี้ เราพบว่าคลาส Set ใช้หน่วยความจำมาก จากการตรวจสอบจุดเรียกใช้ เราพบว่าเรากําลังกําหนดพร็อพเพอร์ตี้ประเภท Set ให้กับออบเจ็กต์ที่สร้างขึ้นเป็นจํานวนมากโดยไม่จําเป็น ค่าใช้จ่ายนี้เพิ่มขึ้นเรื่อยๆ และใช้หน่วยความจำจำนวนมาก จนทำให้แอปพลิเคชันมักจะขัดข้องเมื่อได้รับอินพุตขนาดใหญ่

ชุดข้อมูลมีประโยชน์ในการจัดเก็บรายการที่ไม่ซ้ำกัน และมีโอเปอเรชันที่ใช้ความไม่ซ้ำกันของเนื้อหา เช่น การลบข้อมูลที่ซ้ำกันในชุดข้อมูลและการค้นหาที่มีประสิทธิภาพมากขึ้น อย่างไรก็ตาม ฟีเจอร์เหล่านั้นไม่จำเป็นเนื่องจากข้อมูลที่จัดเก็บรับประกันได้ว่าไม่ซ้ำกับแหล่งที่มา ด้วยเหตุนี้จึงไม่จำเป็นต้องมีฉากตั้งแต่แรก เราได้เปลี่ยนประเภทพร็อพเพอร์ตี้จาก Set เป็นอาร์เรย์ธรรมดาเพื่อปรับปรุงการจัดสรรหน่วยความจำ หลังจากใช้การเปลี่ยนแปลงนี้แล้ว เราได้ถ่ายภาพรวมฮีปอีกครั้งและสังเกตเห็นว่ามีการจัดสรรหน่วยความจำลดลง แม้ว่าการเปลี่ยนแปลงนี้จะไม่ได้ช่วยให้ความเร็วเพิ่มขึ้นอย่างเห็นได้ชัด แต่ข้อดีรองคือแอปพลิเคชันขัดข้องน้อยลง

ภาพหน้าจอของโปรไฟล์หน่วยความจำ เราได้เปลี่ยนการดำเนินการตามชุดที่ใช้หน่วยความจำมากก่อนหน้านี้ให้ใช้อาร์เรย์ธรรมดา ซึ่งช่วยลดต้นทุนด้านหน่วยความจำได้อย่างมาก

กลุ่มกิจกรรมที่ 3: การพิจารณาข้อดีข้อเสียของโครงสร้างข้อมูล

ส่วนที่ 3 มีลักษณะเฉพาะคือคุณจะเห็นในแผนภูมิเปลวไฟว่าประกอบด้วยคอลัมน์แคบแต่สูง ซึ่งแสดงถึงการเรียกฟังก์ชันแบบลึก และการเรียกซ้ำแบบลึกในกรณีนี้ โดยรวมแล้ว ส่วนนี้ใช้เวลาประมาณ 1.4 วินาที เมื่อดูที่ด้านล่างของส่วนนี้ จะเห็นได้ชัดว่าความกว้างของคอลัมน์เหล่านี้กำหนดโดยระยะเวลาของฟังก์ชันหนึ่ง นั่นคือ appendEventAtLevel ซึ่งบ่งชี้ว่าอาจเป็นคอขวด

ในส่วนการใช้งานฟังก์ชัน appendEventAtLevel มีสิ่งหนึ่งที่โดดเด่น สำหรับรายการข้อมูลทุกรายการในอินพุต (ซึ่งรู้จักกันในโค้ดว่า "เหตุการณ์") ระบบจะเพิ่มรายการลงในแผนที่ที่ติดตามตำแหน่งแนวตั้งของรายการไทม์ไลน์ ซึ่งเป็นปัญหาเนื่องจากมีรายการที่จัดเก็บจำนวนมาก แผนที่ช่วยให้ค้นหาตามคีย์ได้อย่างรวดเร็ว แต่ข้อดีนี้ไม่ได้มาฟรีๆ เมื่อแผนที่มีขนาดใหญ่ขึ้น การเพิ่มข้อมูลลงในแผนที่อาจมีค่าใช้จ่ายสูงขึ้น เช่น เนื่องจากการแฮชซ้ำ คุณจะสังเกตเห็นต้นทุนนี้เมื่อเพิ่มรายการจำนวนมากไปยังแผนที่อย่างต่อเนื่อง

/**
 * Adds an event to the flame chart data at a defined vertical level.
 */
function appendEventAtLevel (event, level) {
  // ...

  const index = data.length;
  data.push(event);
  this.indexForEventMap.set(event, index);

  // ...
}

เราได้ทดลองใช้วิธีอื่นที่ไม่จำเป็นต้องเพิ่มรายการในแผนที่สำหรับแต่ละรายการในแผนภูมิเปลวไฟ การปรับปรุงนี้มีความสำคัญอย่างยิ่ง ซึ่งยืนยันว่าคอขวดเกี่ยวข้องกับค่าใช้จ่ายที่เกิดขึ้นจากการเพิ่มข้อมูลทั้งหมดลงในแผนที่ เวลาที่กลุ่มกิจกรรมใช้ลดลงจากประมาณ 1.4 วินาทีเป็นประมาณ 200 มิลลิวินาที

ก่อน

ภาพหน้าจอของแผงประสิทธิภาพก่อนที่จะทำการเพิ่มประสิทธิภาพฟังก์ชัน appendEventAtLevel เวลารวมที่ฟังก์ชันทำงานคือ 1,372.51 มิลลิวินาที

หลัง

ภาพหน้าจอของแผงประสิทธิภาพหลังจากทำการเพิ่มประสิทธิภาพฟังก์ชัน appendEventAtLevel เวลารวมที่ฟังก์ชันทำงานคือ 207.2 มิลลิวินาที

กลุ่มกิจกรรมที่ 4: เลื่อนงานที่ไม่สำคัญและแคชข้อมูลเพื่อป้องกันการทำงานซ้ำ

เมื่อซูมเข้าที่หน้าต่างนี้ คุณจะเห็นว่ามีบล็อกการเรียกฟังก์ชัน 2 บล็อกที่เกือบจะเหมือนกัน เมื่อดูชื่อของฟังก์ชันที่เรียกใช้ คุณจะอนุมานได้ว่าบล็อกเหล่านี้ประกอบด้วยโค้ดที่สร้างแผนผัง (เช่น มีชื่ออย่าง refreshTree หรือ buildChildren) อันที่จริงแล้ว โค้ดที่เกี่ยวข้องคือโค้ดที่สร้างมุมมองแผนผังในลิ้นชักด้านล่างของแผง สิ่งที่น่าสนใจคือมุมมองแบบต้นไม้เหล่านี้จะไม่แสดงทันทีหลังจากโหลด แต่ผู้ใช้ต้องเลือกมุมมองแบบต้นไม้ (แท็บ "จากล่างขึ้นบน" "แผนภูมิการเรียก" และ "บันทึกเหตุการณ์" ในลิ้นชัก) เพื่อให้ระบบแสดงแผนภูมิ นอกจากนี้ ดังที่คุณเห็นจากภาพหน้าจอ กระบวนการสร้างแผนผังดำเนินการ 2 ครั้ง

ภาพหน้าจอของแผงประสิทธิภาพที่แสดงงานที่ซ้ำกันหลายอย่างซึ่งดำเนินการแม้ว่าจะไม่จำเป็นก็ตาม คุณอาจเลื่อนงานเหล่านี้ไปดำเนินการตามความต้องการแทนที่จะดำเนินการล่วงหน้า

เราพบปัญหา 2 อย่างในรูปภาพนี้ ได้แก่

  1. งานที่ไม่สำคัญทำให้ประสิทธิภาพของเวลาในการโหลดลดลง ผู้ใช้ไม่จำเป็นต้องใช้เอาต์พุตเสมอไป ดังนั้น งานนี้จึงไม่สำคัญต่อการโหลดโปรไฟล์
  2. ระบบไม่ได้แคชผลลัพธ์ของงานเหล่านี้ ด้วยเหตุนี้ ระบบจึงคำนวณต้นไม้ 2 ครั้งแม้ว่าข้อมูลจะไม่เปลี่ยนแปลงก็ตาม

เราเริ่มต้นด้วยการเลื่อนการคำนวณแผนผังไปเป็นเมื่อผู้ใช้เปิดมุมมองแผนผังด้วยตนเอง เมื่อนั้นจึงจะคุ้มค่าที่จะจ่ายราคาในการสร้างต้นไม้เหล่านี้ เวลาทั้งหมดในการเรียกใช้ฟังก์ชันนี้ 2 ครั้งอยู่ที่ประมาณ 3.4 วินาที ดังนั้นการเลื่อนการเรียกใช้จึงทำให้เวลาในการโหลดแตกต่างกันอย่างมาก เรายังคงตรวจสอบการแคชงานประเภทนี้ด้วย

กลุ่มกิจกรรมที่ 5: หลีกเลี่ยงลำดับชั้นการเรียกที่ซับซ้อนหากเป็นไปได้

เมื่อพิจารณากลุ่มนี้อย่างละเอียด เราพบว่ามีการเรียกใช้ห่วงโซ่การเรียกใช้หนึ่งๆ ซ้ำๆ รูปแบบเดียวกันนี้ปรากฏ 6 ครั้งในตำแหน่งต่างๆ ในแผนภูมิเปลวไฟ และระยะเวลาทั้งหมดของหน้าต่างนี้อยู่ที่ประมาณ 2.4 วินาที

ภาพหน้าจอของแผงประสิทธิภาพที่แสดงการเรียกฟังก์ชันแยกกัน 6 รายการสำหรับการสร้างมินิแมปการติดตามเดียวกัน ซึ่งแต่ละรายการมีสแต็กการเรียกใช้แบบละเอียด

โค้ดที่เกี่ยวข้องซึ่งมีการเรียกใช้หลายครั้งคือส่วนที่ประมวลผลข้อมูลที่จะแสดงใน "แผนที่ขนาดเล็ก" (ภาพรวมของกิจกรรมในไทม์ไลน์ที่ด้านบนของแผง) เราไม่แน่ใจว่าเหตุใดจึงเกิดข้อผิดพลาดหลายครั้ง แต่ไม่จำเป็นต้องเกิดถึง 6 ครั้ง ในความเป็นจริง เอาต์พุตของโค้ดควรเป็นข้อมูลล่าสุดหากไม่มีการโหลดโปรไฟล์อื่น ในทางทฤษฎีแล้ว โค้ดควรทำงานเพียงครั้งเดียว

จากการตรวจสอบพบว่าโค้ดที่เกี่ยวข้องถูกเรียกใช้เนื่องจากหลายส่วนในไปป์ไลน์การโหลดเรียกใช้ฟังก์ชันที่คำนวณมินิแมปโดยตรงหรือโดยอ้อม เนื่องจากกราฟการเรียกของโปรแกรมมีความซับซ้อนมากขึ้นเรื่อยๆ และมีการเพิ่มการอ้างอิงโค้ดนี้โดยไม่รู้ตัว ปัญหานี้ไม่มีวิธีแก้ไขอย่างรวดเร็ว วิธีแก้ปัญหานี้ขึ้นอยู่กับสถาปัตยกรรมของโค้ดเบสที่เป็นปัญหา ในกรณีของเรา เราต้องลดความซับซ้อนของลำดับชั้นการเรียกใช้ลงเล็กน้อย และเพิ่มการตรวจสอบเพื่อป้องกันการเรียกใช้โค้ดหากข้อมูลนำเข้ายังคงไม่เปลี่ยนแปลง หลังจากใช้การตั้งค่านี้ เราก็เห็นภาพรวมของไทม์ไลน์ดังนี้

ภาพหน้าจอของแผงประสิทธิภาพที่แสดงการเรียกฟังก์ชันแยกกัน 6 รายการสำหรับการสร้างมินิแมปการติดตามเดียวกัน ซึ่งลดลงเหลือเพียง 2 ครั้ง

โปรดทราบว่าการดำเนินการแสดงผลมินิแมปจะเกิดขึ้น 2 ครั้ง ไม่ใช่ครั้งเดียว เนื่องจากมีการวาดมินิแมป 2 รายการสำหรับทุกโปรไฟล์ ได้แก่ รายการหนึ่งสำหรับภาพรวมที่ด้านบนของแผง และอีกรายการหนึ่งสำหรับเมนูแบบเลื่อนลงที่เลือกโปรไฟล์ที่มองเห็นได้ในปัจจุบันจากประวัติ (ทุกรายการในเมนูนี้มีภาพรวมของโปรไฟล์ที่เลือก) อย่างไรก็ตาม ทั้ง 2 รายการนี้มีเนื้อหาเหมือนกันทุกประการ ดังนั้นจึงควรนำรายการหนึ่งไปใช้ซ้ำกับอีกรายการหนึ่งได้

เนื่องจากมินิแมปเหล่านี้เป็นรูปภาพที่วาดบน Canvas จึงเป็นเรื่องของการใช้drawImage canvas utility และต่อมาก็รันโค้ดเพียงครั้งเดียวเพื่อประหยัดเวลาเพิ่มเติม ความพยายามนี้ส่งผลให้ระยะเวลาของกลุ่มลดลงจาก 2.4 วินาทีเป็น 140 มิลลิวินาที

บทสรุป

หลังจากใช้การแก้ไขทั้งหมดนี้ (และอีก 2-3 รายการเล็กๆ น้อยๆ) การเปลี่ยนแปลงไทม์ไลน์การโหลดโปรไฟล์มีลักษณะดังนี้

ก่อน

ภาพหน้าจอของแผงประสิทธิภาพที่แสดงการโหลดการติดตามก่อนการเพิ่มประสิทธิภาพ กระบวนการนี้ใช้เวลาประมาณ 10 วินาที

หลัง

ภาพหน้าจอของแผงประสิทธิภาพที่แสดงการโหลดการติดตามหลังจากการเพิ่มประสิทธิภาพ ตอนนี้กระบวนการนี้ใช้เวลาประมาณ 2 วินาที

เวลาในการโหลดหลังจากปรับปรุงคือ 2 วินาที ซึ่งหมายความว่ามีการปรับปรุงประมาณ 80% โดยใช้ความพยายามค่อนข้างน้อย เนื่องจากสิ่งที่ทำส่วนใหญ่เป็นการแก้ไขอย่างรวดเร็ว แน่นอนว่าการระบุสิ่งที่ต้องทำในตอนแรกอย่างถูกต้องเป็นสิ่งสำคัญ และแผงประสิทธิภาพก็เป็นเครื่องมือที่เหมาะสมสำหรับเรื่องนี้

นอกจากนี้ สิ่งสำคัญที่ควรเน้นย้ำคือตัวเลขเหล่านี้เป็นตัวเลขเฉพาะของโปรไฟล์ที่ใช้เป็นหัวข้อการศึกษา โปรไฟล์ดังกล่าวเป็นที่น่าสนใจสำหรับเราเนื่องจากมีขนาดใหญ่เป็นพิเศษ อย่างไรก็ตาม เนื่องจากไปป์ไลน์การประมวลผลเหมือนกันสำหรับทุกโปรไฟล์ การปรับปรุงที่สำคัญจึงมีผลกับทุกโปรไฟล์ที่โหลดในแผงประสิทธิภาพ

สรุปประเด็นสำคัญ

ผลลัพธ์เหล่านี้ให้บทเรียนบางอย่างเกี่ยวกับการเพิ่มประสิทธิภาพของแอปพลิเคชัน ดังนี้

1. ใช้เครื่องมือสร้างโปรไฟล์เพื่อระบุรูปแบบประสิทธิภาพรันไทม์

เครื่องมือสร้างโปรไฟล์มีประโยชน์อย่างยิ่งในการทําความเข้าใจสิ่งที่เกิดขึ้นในแอปพลิเคชันขณะที่แอปทํางาน โดยเฉพาะอย่างยิ่งในการระบุโอกาสในการปรับปรุงประสิทธิภาพ แผงประสิทธิภาพใน Chrome DevTools เป็นตัวเลือกที่ยอดเยี่ยมสำหรับเว็บแอปพลิเคชัน เนื่องจากเป็นเครื่องมือสร้างโปรไฟล์เว็บดั้งเดิมในเบราว์เซอร์ และมีการบำรุงรักษาอย่างต่อเนื่องเพื่อให้ทันสมัยอยู่เสมอด้วยฟีเจอร์ล่าสุดของแพลตฟอร์มเว็บ นอกจากนี้ ตอนนี้ยังเร็วขึ้นมากด้วย 😉

ใช้ตัวอย่างที่ใช้เป็นภาระงานที่เป็นตัวแทนได้ แล้วดูว่าคุณจะพบอะไร

2. หลีกเลี่ยงลำดับชั้นการโทรที่ซับซ้อน

หลีกเลี่ยงการทำให้กราฟการเรียกใช้ซับซ้อนเกินไปหากเป็นไปได้ เมื่อมีลำดับชั้นการเรียกที่ซับซ้อน ก็จะเกิดการถดถอยของประสิทธิภาพได้ง่าย และเข้าใจได้ยากว่าทำไมโค้ดจึงทำงานในลักษณะที่เป็นอยู่ ทำให้ปรับปรุงได้ยาก

3. ระบุงานที่ไม่จำเป็น

โดยปกติแล้ว โค้ดเบสที่เก่ามักจะมีโค้ดที่ไม่จำเป็นอีกต่อไป ในกรณีของเรา โค้ดเดิมและโค้ดที่ไม่จำเป็นใช้เวลาในการโหลดเป็นส่วนสำคัญของเวลาในการโหลดทั้งหมด การนำออกจึงเป็นวิธีที่ง่ายที่สุด

4. ใช้โครงสร้างข้อมูลอย่างเหมาะสม

ใช้โครงสร้างข้อมูลเพื่อเพิ่มประสิทธิภาพ แต่ก็ต้องเข้าใจต้นทุนและข้อแลกเปลี่ยนที่โครงสร้างข้อมูลแต่ละประเภทนำมาด้วยเมื่อตัดสินใจว่าจะใช้โครงสร้างข้อมูลใด ซึ่งไม่ใช่แค่ความซับซ้อนของพื้นที่ของโครงสร้างข้อมูลเท่านั้น แต่ยังรวมถึงความซับซ้อนของเวลาของการดำเนินการที่เกี่ยวข้องด้วย

5. แคชผลลัพธ์เพื่อหลีกเลี่ยงการทำงานที่ซ้ำกันสำหรับการดำเนินการที่ซับซ้อนหรือซ้ำๆ

หากการดำเนินการมีค่าใช้จ่ายสูง การจัดเก็บผลลัพธ์ไว้ใช้ในครั้งถัดไปที่จำเป็นจึงเป็นเรื่องสมเหตุสมผล นอกจากนี้ คุณควรทำเช่นนี้หากดำเนินการหลายครั้ง แม้ว่าแต่ละครั้งจะไม่เสียค่าใช้จ่ายมากนักก็ตาม

6. เลื่อนงานที่ไม่สำคัญออกไป

หากไม่จำเป็นต้องใช้เอาต์พุตของงานทันทีและงานนั้นขยายเส้นทางวิกฤต ให้พิจารณาเลื่อนงานออกไปโดยเรียกใช้แบบเลื่อนเวลาเมื่อจำเป็นต้องใช้เอาต์พุตจริงๆ

7. ใช้อัลกอริทึมที่มีประสิทธิภาพกับอินพุตขนาดใหญ่

สำหรับอินพุตขนาดใหญ่ อัลกอริทึมความซับซ้อนของเวลาที่เหมาะสมจะมีความสำคัญอย่างยิ่ง เราไม่ได้พิจารณาหมวดหมู่นี้ในตัวอย่างนี้ แต่ความสำคัญของหมวดหมู่นี้ก็ไม่ควรมองข้าม

8. โบนัส: เปรียบเทียบไปป์ไลน์

การตรวจสอบลักษณะการทำงานและเปรียบเทียบกับมาตรฐานเป็นวิธีที่ดีเพื่อให้โค้ดที่พัฒนาขึ้นยังคงทำงานได้อย่างรวดเร็ว วิธีนี้จะช่วยให้คุณระบุการถดถอยได้ตั้งแต่เนิ่นๆ และปรับปรุงความน่าเชื่อถือโดยรวม ซึ่งจะช่วยให้คุณประสบความสำเร็จในระยะยาว