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

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

Alex Danilo

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

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

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

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

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

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

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 พอสมควรแล้ว เราก็สามารถใช้ User Timing 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 ในแอปพลิเคชันของคุณได้เลย คุณจะได้เรียนรู้วิธีเพิ่มความเร็วให้กับแอปพลิเคชัน และผู้ใช้ของคุณจะรู้สึกขอบคุณที่ทำให้ประสบการณ์การใช้งานดีขึ้นมาก