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

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

Alex Danilo

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

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

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

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

ส่วนพื้นฐานของการวัดเวลาที่แม่นยำคือความเที่ยงตรง ในอดีต เรามีการกำหนดเวลาตามการวัดระดับมิลลิวินาที ซึ่งก็ถือว่าใช้ได้ แต่การสร้างเว็บไซต์ 60 FPS ที่ไม่มีการกระตุกหมายความว่าแต่ละเฟรมจะต้องวาดใน 16 มิลลิวินาที ดังนั้นเมื่อคุณมีความแม่นยำระดับมิลลิวินาทีเท่านั้น ก็จะขาดความแม่นยำที่จำเป็นสำหรับการวิเคราะห์ที่ดี High Resolution Time เป็นประเภทการจับเวลาแบบใหม่ที่สร้างขึ้นในเบราว์เซอร์ที่ทันสมัย High Resolution Time ช่วยให้เราได้การประทับเวลาแบบจุดลอยตัวที่มีความแม่นยำถึงระดับไมโครวินาที ซึ่งดีกว่าเดิมถึง 1,000 เท่า

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

var myTime = window.performance.now();

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

ประเภท DOMHighResTimeStamp

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

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

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

อินเทอร์เฟซระยะเวลาของผู้ใช้มีฟังก์ชันที่ช่วยให้เราเรียกใช้เมธอดในตำแหน่งต่างๆ ของแอปพลิเคชัน ซึ่งจะแสดงเส้นทางเบรดครัมบ์แบบ Hansel and 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() ทั้งหมดเพื่อเรียกใช้ฟังก์ชันที่ตั้งค่าเครื่องหมาย และในขณะเดียวกันก็เปลี่ยน Callback ที่สำเร็จด้วยการเรียกใช้ฟังก์ชันที่ตั้งค่าเครื่องหมายอื่น จากนั้นสร้างการวัดระยะเวลาที่ใช้ในการส่งคำขอ

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