วิธีประเมินประสิทธิภาพการโหลดในการใช้งานจริงด้วยระยะเวลาในการนําทางและระยะเวลาของทรัพยากร

ดูข้อมูลพื้นฐานของการใช้ Navigation และ Resource Timing API เพื่อประเมินประสิทธิภาพการโหลดภาคสนาม

เผยแพร่เมื่อวันที่ 8 ตุลาคม 2021

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

การทดสอบแบบสังเคราะห์ไม่ได้แย่โดยเนื้อแท้ แต่ไม่ได้แสดงถึงความเร็วในการโหลดเว็บไซต์สำหรับผู้ใช้จริง ซึ่งต้องใช้ข้อมูลภาคสนาม ซึ่งคุณรวบรวมได้จาก Navigation Timing API และ Resource Timing API

API ที่ช่วยคุณประเมินประสิทธิภาพการโหลดในสนาม

การจับเวลาการนำทางและระยะเวลาการใช้ทรัพยากรเป็น API 2 ประเภทที่คล้ายกันซึ่งมีการซ้อนทับกันอย่างมีนัยสำคัญ ซึ่งจะวัด 2 สิ่งที่แตกต่างกันดังนี้

API เหล่านี้จะแสดงข้อมูลใน performance entry buffer ซึ่งเข้าถึงได้ในเบราว์เซอร์ด้วย JavaScript การค้นหาบัฟเฟอร์ประสิทธิภาพทำได้หลายวิธี แต่วิธีที่ใช้กันโดยทั่วไปคือการใช้ performance.getEntriesByType ดังนี้

// Get Navigation Timing entries:
performance.getEntriesByType('navigation');

// Get Resource Timing entries:
performance.getEntriesByType('resource');

performance.getEntriesByType รับสตริงที่อธิบายประเภทของรายการที่คุณต้องการดึงข้อมูลจากบัฟเฟอร์รายการประสิทธิภาพ 'navigation' และ 'resource' จะดึงข้อมูลเวลาสําหรับ Navigation Timing API และ Resource Timing API ตามลําดับ

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

ระยะเวลาและช่วงเวลาของคําขอเครือข่าย

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

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

ระยะเวลาของคำขอเครือข่ายมีระยะที่แตกต่างกัน เช่น การค้นหา DNS, การสร้างการเชื่อมต่อ, การเจรจา TLS และแหล่งที่มาอื่นๆ ของเวลาในการตอบสนอง ช่วงเวลาเหล่านี้จะแสดงเป็น DOMHighResTimestamp รายละเอียดของช่วงเวลาอาจลดลงถึงไมโครวินาทีหรือปัดเศษขึ้นเป็นมิลลิวินาที ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ของคุณ คุณควรตรวจสอบระยะเหล่านี้โดยละเอียด และดูว่าระยะเหล่านี้เกี่ยวข้องกับเวลาในการนําทางและเวลาในการตอบสนองของทรัพยากรอย่างไร

การค้นหา DNS

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

  • domainLookupStart คือเวลาที่การค้นหา DNS เริ่มต้น
  • domainLookupEnd คือเวลาที่การค้นหา DNS สิ้นสุดลง

การคำนวณเวลาทั้งหมดในการค้นหา DNS ทำได้โดยลบเมตริกเริ่มต้นออกจากเมตริกสิ้นสุด ดังนี้

// Measuring DNS lookup time
const [pageNav] = performance.getEntriesByType('navigation');
const totalLookupTime = pageNav.domainLookupEnd - pageNav.domainLookupStart;

การเจรจาต่อรองการเชื่อมต่อ

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

  • connectStart คือเวลาที่เบราว์เซอร์เริ่มเปิดการเชื่อมต่อกับเว็บเซิร์ฟเวอร์
  • secureConnectionStart จะทำเครื่องหมายเมื่อไคลเอ็นต์เริ่มการเจรจา TLS
  • connectEnd คือเวลาที่สร้างการเชื่อมต่อกับเว็บเซิร์ฟเวอร์

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

// Quantifying total connection time
const [pageNav] = performance.getEntriesByType('navigation');
const connectionTime = pageNav.connectEnd - pageNav.connectStart;
let tlsTime = 0; // <-- Assume 0 to start with

// Was there TLS negotiation?
if (pageNav.secureConnectionStart > 0) {
  // Awesome! Calculate it!
  tlsTime = pageNav.connectEnd - pageNav.secureConnectionStart;
}

เมื่อการค้นหา DNS และการเจรจาการเชื่อมต่อสิ้นสุดลง เวลาที่เกี่ยวข้องกับการดึงข้อมูลเอกสารและทรัพยากรที่เกี่ยวข้องจะเข้ามามีบทบาท

คำขอและการตอบกลับ

ปัจจัย 2 ประเภทส่งผลต่อประสิทธิภาพในการโหลด ดังนี้

  • ปัจจัยภายนอก: ปัจจัยต่างๆ เช่น เวลาในการตอบสนองและแบนด์วิดท์ นอกจากการเลือกบริษัทโฮสติ้งและอาจรวมถึง CDN แล้ว บริษัทเหล่านี้ (ส่วนใหญ่) ไม่มีสิทธิ์ควบคุม เนื่องจากผู้ใช้สามารถเข้าถึงเว็บได้จากทุกที่
  • ปัจจัยภายใน: ปัจจัยต่างๆ เช่น สถาปัตยกรรมฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ ตลอดจนขนาดทรัพยากรและความสามารถในการเพิ่มประสิทธิภาพเพื่อสิ่งเหล่านั้นซึ่งอยู่ในการควบคุมของเรา

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

  • fetchStart หมายถึงเวลาที่เบราว์เซอร์เริ่มดึงข้อมูลทรัพยากร (เวลาในการตอบสนองของทรัพยากร) หรือดึงข้อมูลเอกสารสําหรับคําขอไปยังส่วนต่างๆ (เวลาในการตอบสนองในการนําทาง) ซึ่งอยู่ก่อนคำขอจริง และเป็นจุดที่เบราว์เซอร์กำลังตรวจสอบแคช (เช่น HTTP และอินสแตนซ์ Cache)
  • workerStart จะทำเครื่องหมายเมื่อเริ่มจัดการคำขอภายในเครื่องจัดการเหตุการณ์ fetch ของ Service Worker ซึ่งจะเป็น 0 เมื่อไม่มี Service Worker กำลังควบคุมหน้าปัจจุบัน
  • requestStart คือเวลาที่เบราว์เซอร์ส่งคำขอ
  • responseStart คือเวลาที่ไบต์แรกของการตอบกลับมาถึง
  • responseEnd คือเวลาที่ไบต์สุดท้ายของคำตอบมาถึง

ช่วงเวลาเหล่านี้ช่วยให้คุณวัดประสิทธิภาพการโหลดได้หลายด้าน เช่น การค้นหาแคชภายใน Service Worker และเวลาดาวน์โหลด

// Cache seek plus response time of the current document
const [pageNav] = performance.getEntriesByType('navigation');
const fetchTime = pageNav.responseEnd - pageNav.fetchStart;

// Service worker time plus response time
let workerTime = 0;

if (pageNav.workerStart > 0) {
  workerTime = pageNav.responseEnd - pageNav.workerStart;
}

นอกจากนี้ คุณยังวัดแง่มุมอื่นๆ ของคำขอและเวลาในการตอบสนองของการตอบกลับได้ด้วย

const [pageNav] = performance.getEntriesByType('navigation');

// Request time only (excluding redirects, DNS, and connection/TLS time)
const requestTime = pageNav.responseStart - pageNav.requestStart;

// Response time only (download)
const responseTime = pageNav.responseEnd - pageNav.responseStart;

// Request + response time
const requestResponseTime = pageNav.responseEnd - pageNav.requestStart;

การวัดผลอื่นๆ ที่คุณสามารถทำได้

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

  • การเปลี่ยนเส้นทางหน้าเว็บ: การเปลี่ยนเส้นทางเป็นสาเหตุที่อาจทำให้เวลาในการตอบสนองเพิ่มขึ้นที่ถูกมองข้าม โดยเฉพาะห่วงโซ่การเปลี่ยนเส้นทาง เวลาในการตอบสนองจะเพิ่มขึ้นด้วยวิธีต่างๆ เช่น Hop จาก HTTP ไปยัง HTTPs รวมถึงการเปลี่ยนเส้นทาง 302/301 ที่ไม่ได้แคช การกําหนดเวลา redirectStart, redirectEnd และ redirectCount มีประโยชน์ในการประเมินเวลาในการตอบสนองของการเปลี่ยนเส้นทาง
  • การยกเลิกการโหลดเอกสาร: ในหน้าเว็บที่เรียกใช้โค้ดในเครื่องจัดการเหตุการณ์ unload เบราว์เซอร์จะต้องเรียกใช้โค้ดนั้นก่อนจึงจะไปยังหน้าถัดไปได้ unloadEventStart และ unloadEventEnd วัดการยกเลิกการโหลดเอกสาร
  • การประมวลผลเอกสาร: ระยะเวลาในการประมวลผลเอกสารอาจไม่ส่งผลต่อประสิทธิภาพ เว้นแต่ว่าเว็บไซต์จะส่งเพย์โหลด HTML ขนาดใหญ่มาก หากตรงกับสถานการณ์ของคุณ เวลา domInteractive, domContentLoadedEventStart, domContentLoadedEventEnd และ domComplete อาจน่าสนใจ

วิธีดูเวลาในโค้ด

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

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

// Create the performance observer:
const perfObserver = new PerformanceObserver((observedEntries) => {
  // Get all resource entries collected so far:
  const entries = observedEntries.getEntries();

  // Iterate over entries:
  for (let i = 0; i < entries.length; i++) {
    // Do the work!
  }
});

// Run the observer for Navigation Timing entries:
perfObserver.observe({
  type: 'navigation',
  buffered: true
});

// Run the observer for Resource Timing entries:
perfObserver.observe({
  type: 'resource',
  buffered: true
});

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

วิธีโทรหาบ้าน

เมื่อรวบรวมช่วงเวลาทั้งหมดที่ต้องการแล้ว คุณจะส่งไปยังปลายทางเพื่อวิเคราะห์เพิ่มเติมได้ ซึ่งทำได้ 2 วิธี ได้แก่ navigator.sendBeacon หรือ fetch ที่มีการตั้งค่าตัวเลือก keepalive ทั้ง 2 วิธีจะส่งคําขอไปยังปลายทางที่ระบุโดยไม่บล็อก และระบบจะจัดคิวคําขอในลักษณะที่ยาวนานกว่าเซสชันหน้าเว็บปัจจุบัน หากจําเป็น

// Check for navigator.sendBeacon support:
if ('sendBeacon' in navigator) {
  // Caution: If you have lots of performance entries, don't
  // do this. This is an example for illustrative purposes.
  const data = JSON.stringify(performance.getEntries());

  // Send the data!
  navigator.sendBeacon('/analytics', data);
}

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

บทสรุป

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

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

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

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