API ระยะเวลาของผู้ใช้

ทำความเข้าใจเว็บแอป

Alex Danilo

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

คุณไม่สามารถเพิ่มประสิทธิภาพสิ่งที่วัดไม่ได้

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

เวลาและ now() ความละเอียดสูง

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

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

var myTime = window.performance.now();

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

ประเภท DOMHighResTimeStamp

เมื่อพยายามวัดเวลาของเว็บแอปพลิเคชันที่ผ่านมา คุณอาจใช้ Date.now() ซึ่งจะแสดงผล DOMTimeStamp DOMTimeStamp จะแสดงผลค่าเป็นจำนวนเต็มของมิลลิวินาที เราได้เปิดตัวประเภทใหม่ชื่อ DOMHighResTimeStamp เพื่อเพิ่มความแม่นยำที่จำเป็นสำหรับเวลาความละเอียดสูง ประเภทนี้เป็นค่าตัวเลขทศนิยมที่แสดงผลเวลาเป็นมิลลิวินาทีด้วย แต่เนื่องจากเป็นทศนิยม ค่าจึงแสดงมิลลิวินาทีแบบเศษทศนิยมได้ จึงให้ค่าที่แม่นยำถึง 1 ในพันมิลลิวินาที

อินเทอร์เฟซระยะเวลาของผู้ใช้

เมื่อเรามีการประทับเวลาที่มีความละเอียดสูงแล้ว เรามาลองใช้อินเทอร์เฟซการวัดเวลาของผู้ใช้เพื่อดึงข้อมูลการวัดเวลากัน

อินเทอร์เฟซการวัดเวลาของผู้ใช้มีฟังก์ชันที่ช่วยให้เราเรียกใช้เมธอดในตําแหน่งต่างๆ ในแอปพลิเคชัน ซึ่งสามารถระบุร่องรอยเบรดครัมบ์สไตล์ Hansel และ Gretel เพื่อให้เราติดตามได้ว่าผู้ใช้ใช้เวลาไปกับส่วนใด

กำลังใช้ mark()

วิธี mark() เป็นเครื่องมือหลักในชุดเครื่องมือการวิเคราะห์ช่วงเวลา สิ่งที่ mark() ทําคือจัดเก็บการประทับเวลาให้เรา สิ่งที่มีประโยชน์อย่างยิ่งเกี่ยวกับ mark() คือเราสามารถตั้งชื่อการประทับเวลาได้ และ API จะจดจำชื่อและการประทับเวลาเป็นหน่วยเดียว

การเรียกใช้ mark() ในตําแหน่งต่างๆ ของแอปพลิเคชันจะช่วยให้คุณทราบจํานวนเวลาที่ใช้ในการเข้าถึง "เครื่องหมาย" นั้นในเว็บแอปพลิเคชัน

ข้อกำหนดระบุชื่อที่แนะนำสำหรับเครื่องหมายที่อาจน่าสนใจและสื่อความหมายในตัว เช่น mark_fully_loaded, mark_fully_visible,mark_above_the_fold เป็นต้น

ตัวอย่างเช่น เราอาจทำเครื่องหมายเมื่อแอปพลิเคชันโหลดเสร็จแล้วโดยใช้โค้ดต่อไปนี้

window.performance.mark('mark_fully_loaded');

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

การคำนวณการวัดด้วย measure()

เมื่อตั้งเครื่องหมายเวลาไว้แล้ว คุณจะต้องดูเวลาผ่านไประหว่างเครื่องหมายเหล่านั้น คุณใช้เมธอด measure() เพื่อทำเช่นนั้น

เมธอด measure() จะคํานวณเวลาผ่านไประหว่างเครื่องหมาย และวัดเวลาระหว่างเครื่องหมายกับชื่อเหตุการณ์ที่รู้จักกันดีในอินเทอร์เฟซ PerformanceTiming ได้ด้วย

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

window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');

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

การทิ้งเครื่องหมายด้วย clearMarks()

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

คุณนำเครื่องหมายที่ตั้งไว้ออกได้ง่ายๆ โดยการเรียกใช้ clearMarks()

ดังนั้นโค้ดตัวอย่างด้านล่างจะลบเครื่องหมายที่มีอยู่ทั้งหมดเพื่อให้คุณตั้งค่าการเรียกใช้การจับเวลาอีกครั้งได้หากต้องการ

window.performance.clearMarks();

แน่นอนว่ามีบางสถานการณ์ที่คุณอาจไม่ต้องการล้างเครื่องหมายทั้งหมด ดังนั้นหากต้องการนำเครื่องหมายที่เฉพาะเจาะจงออก คุณก็เพียงแค่ส่งชื่อเครื่องหมายที่ต้องการนำออก เช่น โค้ดด้านล่าง

window.performance.clearMarks('mark_fully_loaded');

จะนำเครื่องหมายที่เราตั้งไว้ในตัวอย่างแรกออก โดยไม่เปลี่ยนแปลงเครื่องหมายอื่นๆ ที่เราตั้งไว้

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

window.performance.clearMeasures('measure_load_from_dom');

จะนําการวัดที่เราทําในตัวอย่าง measure() ด้านบนออก หากต้องการนําการวัดทั้งหมดออก การดำเนินการนี้จะทํางานเหมือนกับ clearMarks() นั่นคือคุณเพียงเรียกใช้ clearMeasures() โดยไม่ต้องใช้อาร์กิวเมนต์

การแสดงข้อมูลการจับเวลา

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

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

โค้ดด้านล่าง

var items = window.performance.getEntriesByType('mark');

แสดงรายการเครื่องหมายทั้งหมดที่มีการเรียกใช้ในเว็บแอปพลิเคชันของเรา ขณะที่โค้ดจะทําดังนี้

var items = window.performance.getEntriesByType('measure');

แสดงรายการการวัดผลทั้งหมดที่เราทํา

นอกจากนี้ คุณยังดูรายการรายการต่างๆ อีกครั้งได้โดยใช้ชื่อที่เฉพาะเจาะจงที่คุณตั้งไว้ ตัวอย่างเช่น โค้ด

var items = window.performance.getEntriesByName('mark_fully_loaded');

จะแสดงรายการที่มี 1 รายการซึ่งมีการประทับเวลา "mark_fully_loaded" ในพร็อพเพอร์ตี้ startTime

การกำหนดเวลาคำขอ XHR (ตัวอย่าง)

ตอนนี้เรามีภาพรวมที่ชัดเจนของ User Timing API แล้ว เราจึงใช้ API นี้เพื่อวิเคราะห์ระยะเวลาที่ XMLHttpRequests ทั้งหมดใช้ในการเรียกใช้เว็บแอปพลิเคชันได้

ก่อนอื่น เราจะแก้ไขคําขอ send() ทั้งหมดเพื่อออกคําเรียกฟังก์ชันที่ตั้งเครื่องหมาย และในเวลาเดียวกันก็เปลี่ยนการเรียกกลับสําเร็จด้วยคําเรียกฟังก์ชันที่ตั้งเครื่องหมายอื่น จากนั้นสร้างการวัดระยะเวลาที่ใช้ในการส่งคําขอ

ดังนั้นโดยปกติแล้ว XMLHttpRequest จะมีลักษณะดังนี้

var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
  do_something(e.responseText);
}
myReq.send();

ในตัวอย่างนี้ เราจะเพิ่มตัวนับส่วนกลางเพื่อติดตามจํานวนคําขอ รวมถึงใช้ตัวนับดังกล่าวเพื่อจัดเก็บการวัดผลสําหรับคําขอแต่ละรายการที่ส่ง โค้ดสําหรับดําเนินการนี้จะมีลักษณะดังนี้

var reqCnt = 0;

var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
  window.performance.mark('mark_end_xhr');
  reqCnt++;
  window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr');
  do_something(e.responseText);
}
window.performance.mark('mark_start_xhr');
myReq.send();

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

เมื่อเว็บแอปพลิเคชันส่งคําขอจํานวนมากแล้ว เราอาจส่งออกคําขอทั้งหมดไปยังคอนโซลได้โดยใช้โค้ดด้านล่างนี้

var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length; ++i) {
  var req = items[i];
  console.log('XHR ' + req.name + ' took ' + req.duration + 'ms');
}

บทสรุป

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