JavaScript มักทริกเกอร์การเปลี่ยนแปลงที่มองเห็นได้ บางครั้งการเปลี่ยนแปลงนั้นเกิดขึ้นผ่านการจัดการสไตล์โดยตรง และบางครั้งเป็นการคำนวณที่ทำให้เกิดการเปลี่ยนแปลงที่มองเห็นได้ เช่น การค้นหาหรือการจัดเรียงข้อมูล JavaScript ที่ทำงานนานหรือทำงานไม่ตรงเวลาเป็นสาเหตุที่พบบ่อยของปัญหาด้านประสิทธิภาพ คุณควรพยายามลดผลกระทบให้ได้มากที่สุด
JavaScript มักทริกเกอร์การเปลี่ยนแปลงที่มองเห็นได้ บางครั้งการดำเนินการดังกล่าวจะดำเนินการผ่านการจัดการสไตล์โดยตรง และบางครั้งก็เป็นการคำนวณที่ทำให้เกิดการเปลี่ยนแปลงที่มองเห็นได้ เช่น การค้นหาหรือการจัดเรียงข้อมูล JavaScript ที่ทำงานนานหรือมีการกำหนดเวลาไม่ดีเป็นสาเหตุที่พบบ่อยของปัญหาด้านประสิทธิภาพ คุณควรพยายามลดผลกระทบให้ได้มากที่สุด
การแสดงภาพประสิทธิภาพของ JavaScript อาจเป็นศาสตร์อย่างหนึ่ง เนื่องจาก JavaScript ที่คุณเขียนไม่เหมือนโค้ดที่ดำเนินการจริง เบราว์เซอร์สมัยใหม่ใช้คอมไพเลอร์ JIT และการเพิ่มประสิทธิภาพและเทคนิคทุกรูปแบบเพื่อพยายามทำให้การเรียกใช้โค้ดเร็วที่สุดเท่าที่จะเป็นไปได้ ซึ่งทำให้ลักษณะการทำงานของโค้ดเปลี่ยนแปลงไปอย่างมาก
อย่างไรก็ตาม ยังมีบางสิ่งที่คุณทําได้อย่างแน่นอนเพื่อช่วยให้แอปเรียกใช้ JavaScript ได้ดี
สรุป
- หลีกเลี่ยงการใช้ setTimeout หรือ setInterval สำหรับการอัปเดตภาพ ให้ใช้ requestAnimationFrame แทนเสมอ
- ย้าย JavaScript ที่ทำงานเป็นเวลานานออกจากเทรดหลักไปยัง Web Worker
- ใช้ไมโครแทสก์เพื่อทําการเปลี่ยนแปลง DOM ในหลายเฟรม
- ใช้ไทม์ไลน์และเครื่องมือวิเคราะห์ JavaScript ของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome เพื่อประเมินผลกระทบของ JavaScript
ใช้ requestAnimationFrame
สำหรับการเปลี่ยนแปลงที่มองเห็นได้
เมื่อการเปลี่ยนแปลงภาพเกิดขึ้นบนหน้าจอ คุณต้องการทํางานในเวลาที่เหมาะสมสําหรับเบราว์เซอร์ ซึ่งก็คือช่วงเริ่มต้นของเฟรม วิธีเดียวที่จะรับประกันได้ว่า JavaScript จะทำงานเมื่อเริ่มต้นเฟรมคือการใช้ requestAnimationFrame
/**
* If run as a requestAnimationFrame callback, this
* will be run at the start of the frame.
*/
function updateScreen(time) {
// Make visual updates here.
}
requestAnimationFrame(updateScreen);
เฟรมเวิร์กหรือตัวอย่างเพลงอาจใช้ setTimeout
หรือ setInterval
เพื่อทําการเปลี่ยนแปลงภาพ เช่น ภาพเคลื่อนไหว แต่ปัญหาของวิธีนี้คือ Callback จะทํางานเมื่อใดเวลาหนึ่งในเฟรม ซึ่งอาจเป็นตอนท้ายเลยก็ได้ และมักจะทําให้เราพลาดเฟรมหนึ่งๆ ซึ่งส่งผลให้ภาพกระตุก
อันที่จริง jQuery เคยใช้ setTimeout
สำหรับลักษณะการทำงาน animate
เปลี่ยนเป็นใช้ requestAnimationFrame
ในเวอร์ชัน 3
หากใช้ jQuery เวอร์ชันเก่า คุณสามารถแก้ไขเพื่อใช้ requestAnimationFrame
ได้ ซึ่งเราขอแนะนําอย่างยิ่ง
ลดความซับซ้อนหรือใช้ Web Worker
JavaScript จะทํางานบนเธรดหลักของเบราว์เซอร์ควบคู่ไปกับการคํานวณสไตล์ เลย์เอาต์ และในกรณีจํานวนมาก คือการวาด หาก JavaScript ทำงานเป็นเวลานาน ก็จะบล็อกงานอื่นๆ เหล่านี้ ซึ่งอาจทำให้พลาดเฟรม
คุณควรพิจารณาอย่างรอบคอบว่าจะให้ JavaScript ทำงานเมื่อใดและนานเท่าใด ตัวอย่างเช่น หากคุณอยู่ในภาพเคลื่อนไหว เช่น การเลื่อน คุณควรทำให้ JavaScript ทำงานในกรอบเวลาประมาณ 3-4 มิลลิวินาที หากใช้เวลานานกว่านั้น คุณอาจใช้เวลามากเกินไป หากอยู่ในช่วงที่ไม่ได้ใช้งาน คุณก็ไม่ต้องกังวลเรื่องเวลาที่ใช้
ในหลายกรณี คุณสามารถย้ายงานคำนวณล้วนๆ ไปยัง Web Worker ได้ เช่น หากงานนั้นไม่จําเป็นต้องเข้าถึง DOM การจัดการหรือการสํารวจข้อมูล เช่น การจัดเรียงหรือการค้นหา มักเหมาะกับรูปแบบนี้ รวมถึงการโหลดและการสร้างโมเดล
var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker.postMesssage(dataToSort);
// The main thread is now free to continue working on other things...
dataSortWorker.addEventListener('message', function(evt) {
var sortedData = evt.data;
// Update data on screen...
});
การทำงานบางอย่างอาจไม่เหมาะกับรูปแบบนี้ เนื่องจาก Web Worker ไม่มีสิทธิ์เข้าถึง DOM หากงานต้องอยู่ในเธรดหลัก ให้พิจารณาใช้แนวทางการแยกกลุ่ม ซึ่งคุณแบ่งงานขนาดใหญ่ออกเป็นงานเล็กๆ แต่ละงานใช้เวลาไม่เกิน 2-3 มิลลิวินาที และทำงานภายในตัวแฮนเดิล requestAnimationFrame
ในแต่ละเฟรม
แนวทางนี้ส่งผลต่อ UX และ UI และคุณจะต้องตรวจสอบว่าผู้ใช้ทราบว่าระบบกำลังประมวลผลงานอยู่ ไม่ว่าจะใช้ตัวบ่งชี้ความคืบหน้าหรือกิจกรรม ไม่ว่าในกรณีใด แนวทางนี้จะทําให้ชุดข้อความหลักของแอปว่างอยู่เสมอ ซึ่งช่วยให้แอปตอบสนองต่อการโต้ตอบของผู้ใช้ได้อยู่เสมอ
ทราบ "ค่าธรรมเนียมเฟรม" ของ JavaScript
เมื่อประเมินเฟรมเวิร์ก ไลบรารี หรือโค้ดของคุณเอง คุณควรประเมินค่าใช้จ่ายในการเรียกใช้โค้ด JavaScript แบบเฟรมต่อเฟรม ซึ่งสำคัญอย่างยิ่งเมื่อทำภาพเคลื่อนไหวที่ส่งผลต่อประสิทธิภาพ เช่น การเปลี่ยนเฟรมหรือเลื่อน
แผงประสิทธิภาพของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome เป็นวิธีที่ดีที่สุดในการวัดต้นทุนของ JavaScript โดยปกติแล้ว คุณจะได้รับระเบียนระดับล่างดังต่อไปนี้
ส่วนหลักจะมีแผนภูมิเปลวไฟของการเรียกใช้ JavaScript เพื่อให้คุณวิเคราะห์ได้อย่างแม่นยำว่ามีการเรียกใช้ฟังก์ชันใดและแต่ละฟังก์ชันใช้เวลานานเท่าใด
เมื่อทราบข้อมูลนี้ คุณจะประเมินผลกระทบด้านประสิทธิภาพของ JavaScript ในแอปพลิเคชันได้ และเริ่มค้นหาและแก้ไขจุดร้อนที่ฟังก์ชันใช้เวลาในการดำเนินการนานเกินไป ดังที่ได้กล่าวไว้ก่อนหน้านี้ คุณควรนํา JavaScript ที่ทํางานเป็นเวลานานออก หรือหากทําไม่ได้ ให้ย้ายไปยัง Web Worker เพื่อปลดปล่อยชุดข้อความหลักให้ทํางานอื่นๆ ต่อ
ดูวิธีใช้แผงประสิทธิภาพได้ที่เริ่มต้นใช้งานการวิเคราะห์ประสิทธิภาพรันไทม์
หลีกเลี่ยงการเพิ่มประสิทธิภาพ JavaScript ในระดับไมโคร
การทราบว่าเบราว์เซอร์สามารถเรียกใช้สิ่งหนึ่งๆ เวอร์ชันหนึ่งได้เร็วกว่าอีกเวอร์ชันหนึ่ง 100 เท่า เช่น การขอ offsetTop
ขององค์ประกอบหนึ่งๆ เร็วกว่าการคํานวณ getBoundingClientRect()
นั้นเป็นเรื่องที่น่ายินดี แต่เกือบทุกครั้งที่คุณเรียกใช้ฟังก์ชันเหล่านี้จะมีจำนวนไม่มากต่อเฟรม ดังนั้นการมุ่งเน้นที่ประสิทธิภาพด้านนี้ของ JavaScript จึงเป็นเรื่องที่เสียเปล่า โดยปกติแล้วคุณจะประหยัดเวลาได้เพียงเศษเสี้ยวของมิลลิวินาที
หากคุณกำลังสร้างเกมหรือแอปพลิเคชันที่มีการคำนวณที่ต้องใช้ทรัพยากรมาก คุณอาจยกเว้นจากคำแนะนำนี้ได้ เนื่องจากปกติแล้วคุณจะต้องใส่การคำนวณจำนวนมากลงในเฟรมเดียว และในกรณีนี้ทุกอย่างจะช่วยได้
กล่าวโดยย่อคือ คุณควรระมัดระวังอย่างยิ่งเกี่ยวกับการเพิ่มประสิทธิภาพแบบไมโคร เนื่องจากโดยทั่วไปแล้วจะไม่ตรงกับประเภทแอปพลิเคชันที่คุณกำลังสร้าง