บทนำสู่ประสิทธิภาพ API
เผยแพร่แล้ว: 2022-08-10Performance API จะวัดการตอบสนองของเว็บแอปพลิเคชันที่ใช้งานจริงของคุณบนอุปกรณ์ของผู้ใช้จริงและการเชื่อมต่อเครือข่าย สามารถช่วยระบุปัญหาคอขวดในโค้ดฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ด้วย:
- เวลาของผู้ใช้: การวัดประสิทธิภาพของฟังก์ชัน JavaScript ฝั่งไคลเอ็นต์แบบกำหนดเอง
- กำหนดเวลาระบายสี: ตัวชี้วัดการแสดงผลเบราว์เซอร์
- เวลาทรัพยากร: กำลังโหลดประสิทธิภาพของสินทรัพย์และการเรียก Ajax
- เวลาการนำทาง: เมตริกการโหลดหน้าเว็บ รวมถึงการเปลี่ยนเส้นทาง การค้นหา DNS ความพร้อมของ DOM และอื่นๆ
API จัดการกับปัญหาหลายประการที่เกี่ยวข้องกับการประเมินประสิทธิภาพโดยทั่วไป:
- นักพัฒนามักจะทดสอบแอปพลิเคชันบนพีซีระดับไฮเอนด์ที่เชื่อมต่อกับเครือข่ายที่รวดเร็ว DevTools สามารถจำลองอุปกรณ์ที่ช้ากว่าได้ แต่จะไม่เน้นถึงปัญหาในโลกแห่งความเป็นจริงเสมอไป เมื่อลูกค้าส่วนใหญ่ใช้งานมือถืออายุ 2 ปีที่เชื่อมต่อกับ WiFi ของสนามบิน
- ตัวเลือกของบุคคลที่สาม เช่น Google Analytics มักถูกบล็อก ซึ่งนำไปสู่ผลลัพธ์และการตั้งสมมติฐานที่บิดเบือน คุณอาจประสบกับความเป็นส่วนตัวในบางประเทศ
- Performance API สามารถวัดเมตริกต่างๆ ได้อย่างแม่นยำดีกว่าเมธอด เช่น
Date()
ส่วนต่อไปนี้อธิบายวิธีที่คุณสามารถใช้ Performance API ขอแนะนำให้มีความรู้เกี่ยวกับ JavaScript และเมตริกการโหลดหน้าเว็บ
ความพร้อมใช้งานของ API ประสิทธิภาพ
เบราว์เซอร์ที่ทันสมัยส่วนใหญ่รองรับ Performance API – รวมถึง IE10 และ IE11 (แม้แต่ IE9 ก็รองรับอย่างจำกัด) คุณสามารถตรวจจับการมีอยู่ของ API โดยใช้:
if ('performance' in window) { // use Performance API }
ไม่สามารถ Polyfill API ได้อย่างสมบูรณ์ ดังนั้นควรระมัดระวังเกี่ยวกับเบราว์เซอร์ที่หายไป ถ้า 90% ของผู้ใช้ของคุณใช้งาน Internet Explorer 8 อย่างมีความสุข คุณจะวัดเพียง 10% ของลูกค้าด้วยแอปพลิเคชันที่มีความสามารถมากกว่า
สามารถใช้ API ใน Web Workers ซึ่งให้วิธีการดำเนินการคำนวณที่ซับซ้อนในเธรดพื้นหลังโดยไม่หยุดการทำงานของเบราว์เซอร์
เมธอด API ส่วนใหญ่สามารถใช้ได้ใน Node.js ฝั่งเซิร์ฟเวอร์ด้วยโมดูล perf_hooks มาตรฐาน:
// Node.js performance import { performance } from 'node:perf_hooks'; // or in Common JS: const { performance } = require('node:perf_hooks'); console.log( performance.now() );
Deno จัดเตรียม Performance API มาตรฐาน:
// Deno performance console.log( performance.now() );
คุณจะต้องเรียกใช้สคริปต์ที่ได้รับอนุญาต --allow-hrtime
เพื่อเปิดใช้งานการวัดเวลาที่มีความละเอียดสูง:
deno run --allow-hrtime index.js
โดยปกติแล้ว ประสิทธิภาพฝั่งเซิร์ฟเวอร์จะประเมินและจัดการได้ง่ายกว่า เนื่องจากขึ้นอยู่กับโหลด, CPU, RAM, ฮาร์ดดิสก์ และขีดจำกัดของบริการคลาวด์ การอัปเกรดฮาร์ดแวร์หรือตัวเลือกการจัดการกระบวนการ เช่น PM2 การทำคลัสเตอร์ และ Kubernetes อาจมีประสิทธิภาพมากกว่าการจัดเรียงโค้ดใหม่
ส่วนต่อไปนี้เน้นที่ประสิทธิภาพฝั่งไคลเอ็นต์ด้วยเหตุนี้
การวัดประสิทธิภาพแบบกำหนดเอง
Performance API สามารถใช้เพื่อจับเวลาความเร็วในการดำเนินการของฟังก์ชันแอปพลิเคชันของคุณได้ คุณอาจเคยใช้หรือพบฟังก์ชันจับเวลาโดยใช้ Date()
:
const timeStart = new Date(); runMyCode(); const timeTaken = new Date() - timeStart; console.log(`runMyCode() executed in ${ timeTaken }ms`);
Performance API มีประโยชน์หลักสองประการ:
- ความแม่นยำที่ดีขึ้น:
Date()
วัดเป็นมิลลิวินาทีที่ใกล้ที่สุด แต่ Performance API สามารถวัดเศษส่วนของมิลลิวินาที (ขึ้นอยู่กับเบราว์เซอร์) - ความน่าเชื่อถือที่ดีขึ้น: ผู้ใช้หรือระบบปฏิบัติการสามารถเปลี่ยนเวลาของระบบได้ ดังนั้นเมตริกตาม
Date()
จะไม่แม่นยำเสมอไป ซึ่งหมายความว่าฟังก์ชันของคุณอาจปรากฏช้าเป็นพิเศษเมื่อนาฬิกาเคลื่อนไปข้างหน้า!
Date()
เทียบเท่ากันคือ performance.now()
ซึ่งส่งคืนการประทับเวลาที่มีความละเอียดสูงซึ่งตั้งไว้ที่ศูนย์เมื่อกระบวนการที่รับผิดชอบในการสร้างเอกสารเริ่มต้นขึ้น (โหลดหน้าแล้ว):
const timeStart = performance.now(); runMyCode(); const timeTaken = performance.now() - timeStart; console.log(`runMyCode() executed in ${ timeTaken }ms`);
คุณสมบัติ performance.timeOrigin
ที่ไม่ได้มาตรฐานยังสามารถส่งคืนการประทับเวลาตั้งแต่ 1 มกราคม 1970 แม้ว่าจะไม่มีใน IE และ Deno
performance.now()
จะใช้งานไม่ได้เมื่อทำการวัดมากกว่าสองสามค่า Performance API จัดเตรียมบัฟเฟอร์ที่คุณสามารถบันทึกเหตุการณ์สำหรับการวิเคราะห์ในภายหลังโดยส่งชื่อป้ายกำกับไปที่ performance.mark()
:
performance.mark('start:app'); performance.mark('start:init'); init(); // run initialization functions performance.mark('end:init'); performance.mark('start:funcX'); funcX(); // run another function performance.mark('end:funcX'); performance.mark('end:app');
อาร์เรย์ของออบเจ็กต์เครื่องหมายทั้งหมดในบัฟเฟอร์ประสิทธิภาพสามารถแยกได้โดยใช้:
const mark = performance.getEntriesByType('mark');
ตัวอย่างผลลัพธ์:
[ { detail: null duration: 0 entryType: "mark" name: "start:app" startTime: 1000 }, { detail: null duration: 0 entryType: "mark" name: "start:init" startTime: 1001 }, { detail: null duration: 0 entryType: "mark" name: "end:init" startTime: 1100 }, ... ]
เมธอด performance.measure()
จะคำนวณเวลาระหว่างสองเครื่องหมายและเก็บไว้ในบัฟเฟอร์ประสิทธิภาพ คุณส่งชื่อหน่วยวัดใหม่ ชื่อเครื่องหมายเริ่มต้น (หรือค่าว่างเพื่อวัดจากการโหลดหน้า) และชื่อเครื่องหมายสิ้นสุด (หรือค่าว่างเพื่อวัดเป็นเวลาปัจจุบัน):
performance.measure('init', 'start:init', 'end:init');
วัตถุ PerformanceMeasure ถูกผนวกเข้ากับบัฟเฟอร์ด้วยระยะเวลาที่คำนวณได้ ในการรับค่านี้ คุณสามารถขออาร์เรย์ของการวัดทั้งหมดได้:
const measure = performance.getEntriesByType('measure');
หรือขอวัดตามชื่อ:
performance.getEntriesByName('init');
ตัวอย่างผลลัพธ์:
[ { detail: null duration: 99 entryType: "measure" name: "init" startTime: 1001 } ]
การใช้บัฟเฟอร์ประสิทธิภาพ
เช่นเดียวกับเครื่องหมายและการวัด บัฟเฟอร์ประสิทธิภาพใช้เพื่อบันทึกเวลาการนำทาง เวลาทรัพยากร และระยะเวลาระบายสีโดยอัตโนมัติ (ซึ่งเราจะพูดถึงในภายหลัง) คุณสามารถรับอาร์เรย์ของรายการทั้งหมดในบัฟเฟอร์:
performance.getEntries();
ตามค่าเริ่มต้น เบราว์เซอร์ส่วนใหญ่จะมีบัฟเฟอร์ที่เก็บเมตริกทรัพยากรได้มากถึง 150 รายการ ซึ่งน่าจะเพียงพอสำหรับการประเมินส่วนใหญ่ แต่คุณสามารถเพิ่มหรือลดขีดจำกัดบัฟเฟอร์ได้หากต้องการ:
// record 500 metrics performance.setResourceTimingBufferSize(500);
คุณสามารถล้างเครื่องหมายด้วยชื่อหรือคุณสามารถระบุค่าว่างเพื่อล้างเครื่องหมายทั้งหมด:
performance.clearMarks('start:init');
ในทำนองเดียวกัน การวัดสามารถล้างด้วยชื่อหรือค่าว่างเพื่อล้างทั้งหมด:
performance.clearMeasures();
การตรวจสอบการอัปเดตบัฟเฟอร์ประสิทธิภาพ
PerformanceObserver สามารถตรวจสอบการเปลี่ยนแปลงของบัฟเฟอร์ประสิทธิภาพและเรียกใช้ฟังก์ชันเมื่อเกิดเหตุการณ์เฉพาะ ไวยากรณ์จะคุ้นเคยหากคุณใช้ MutationObserver เพื่อตอบสนองต่อการอัปเดต DOM หรือ IntersectionObserver เพื่อตรวจจับเมื่อองค์ประกอบถูกเลื่อนเข้าไปในวิวพอร์ต
คุณต้องกำหนดฟังก์ชันผู้สังเกตการณ์ด้วยสองพารามิเตอร์:
- อาร์เรย์ของรายการผู้สังเกตการณ์ที่ตรวจพบและ
- วัตถุผู้สังเกต หากจำเป็น สามารถเรียกวิธีเลิก
disconnect()
เพื่อหยุดผู้สังเกตการณ์ได้
function performanceCallback(list, observer) { list.getEntries().forEach(entry => { console.log(`name : ${ entry.name }`); console.log(`type : ${ entry.type }`); console.log(`start : ${ entry.startTime }`); console.log(`duration: ${ entry.duration }`); }); }
ฟังก์ชันนี้ถูกส่งไปยังอ็อบเจ็กต์ PerformanceObserver ใหม่ วิธีการ observe()
ของมันถูกส่งผ่านอาร์เรย์ของ Performance buffer entryTypes เพื่อสังเกต:
let observer = new PerformanceObserver( performanceCallback ); observer.observe({ entryTypes: ['mark', 'measure'] });
ในตัวอย่างนี้ การเพิ่มเครื่องหมายหรือหน่วยวัดใหม่จะเรียกใช้ฟังก์ชัน performanceCallback()
แม้ว่าจะบันทึกเฉพาะข้อความที่นี่ แต่ก็สามารถใช้เพื่อทริกเกอร์การอัปโหลดข้อมูลหรือทำการคำนวณเพิ่มเติมได้

การวัดประสิทธิภาพสี
Paint Timing API ใช้ได้เฉพาะใน JavaScript ฝั่งไคลเอ็นต์ และบันทึกสองเมตริกที่มีความสำคัญต่อ Core Web Vitals โดยอัตโนมัติ:
- first-paint: เบราว์เซอร์เริ่มวาดหน้าแล้ว
- first-contentful-paint: เบราว์เซอร์ได้วาดรายการที่สำคัญอันดับแรกของเนื้อหา DOM เช่น หัวเรื่องหรือรูปภาพ
สิ่งเหล่านี้สามารถแยกจากบัฟเฟอร์ประสิทธิภาพไปยังอาร์เรย์:
const paintTimes = performance.getEntriesByType('paint');
โปรดใช้ความระมัดระวังก่อนที่หน้าเว็บจะโหลดเต็ม ค่าจะไม่พร้อม รอเหตุการณ์ window.load
หรือใช้ PerformanceObserver
เพื่อตรวจสอบ paint
entryTypes
ตัวอย่างผลลัพธ์:
[ { "name": "first-paint", "entryType": "paint", "startTime": 812, "duration": 0 }, { "name": "first-contentful-paint", "entryType": "paint", "startTime": 856, "duration": 0 } ]
การลงสีครั้งแรกที่ช้ามักเกิดจาก CSS หรือ JavaScript ที่บล็อกการแสดงผล ช่องว่างของสีที่มีเนื้อหาเป็นอันดับแรกอาจมีขนาดใหญ่หากเบราว์เซอร์ต้องดาวน์โหลดรูปภาพขนาดใหญ่หรือแสดงองค์ประกอบที่ซับซ้อน
การวัดประสิทธิภาพของทรัพยากร
การกำหนดเวลาเครือข่ายสำหรับทรัพยากร เช่น รูปภาพ สไตล์ชีต และไฟล์ JavaScript จะถูกบันทึกลงในบัฟเฟอร์ประสิทธิภาพโดยอัตโนมัติ แม้ว่าคุณจะทำอะไรได้บ้างเพื่อแก้ปัญหาความเร็วเครือข่าย (นอกเหนือจากการลดขนาดไฟล์) แต่ก็สามารถช่วยเน้นปัญหาที่มีเนื้อหาที่ใหญ่ขึ้น การตอบสนองของ Ajax ที่ช้า หรือสคริปต์ของบุคคลที่สามที่ทำงานได้ไม่ดี
อาร์เรย์ของเมทริก PerformanceResourceTiming สามารถดึงออกมาจากบัฟเฟอร์ได้โดยใช้:
const resources = performance.getEntriesByType('resource');
อีกวิธีหนึ่ง คุณสามารถดึงข้อมูลเมตริกสำหรับเนื้อหาโดยส่ง URL แบบเต็ม:
const resource = performance.getEntriesByName('https://test.com/script.js');
ตัวอย่างผลลัพธ์:
[ { connectEnd: 195, connectStart: 195, decodedBodySize: 0, domainLookupEnd: 195, domainLookupStart: 195, duration: 2, encodedBodySize: 0, entryType: "resource", fetchStart: 195, initiatorType: "script", name: "https://test.com/script.js", nextHopProtocol: "h3", redirectEnd: 0, redirectStart: 0, requestStart: 195, responseEnd: 197, responseStart: 197, secureConnectionStart: 195, serverTiming: [], startTime: 195, transferSize: 0, workerStart: 195 } ]
สามารถตรวจสอบคุณสมบัติต่อไปนี้:
- ชื่อ : URL ทรัพยากร
- ประเภทรายการ : “ทรัพยากร”
- initiatorType : วิธีเริ่มต้นของทรัพยากร เช่น "สคริปต์" หรือ "ลิงก์"
- serverTiming : อาร์เรย์ของออบเจ็กต์
PerformanceServerTiming
ที่ส่งผ่านโดยเซิร์ฟเวอร์ในส่วนหัว HTTP Server-Timing (แอปพลิเคชันฝั่งเซิร์ฟเวอร์ของคุณสามารถส่งเมตริกไปยังไคลเอนต์เพื่อการวิเคราะห์เพิ่มเติม) - startTime : เวลาประทับเมื่อการดึงข้อมูลเริ่มต้น
- nextHopProtocol : ใช้โปรโตคอลเครือข่าย
- workerStart : Timestamp ก่อนเริ่ม Progressive Web App Service Worker (0 หากคำขอไม่ถูกขัดขวางโดย Service Worker)
- redirectStart : Timestamp เมื่อการเปลี่ยนเส้นทางเริ่มต้น
- redirectEnd : เวลาประทับหลังจากไบต์สุดท้ายของการตอบกลับการเปลี่ยนเส้นทางล่าสุด
- fetchStart : Timestamp ก่อนดึงทรัพยากร
- domainLookupStart : การประทับเวลาก่อนการค้นหา DNS
- domainLookupEnd : การประทับเวลาหลังจากการค้นหา DNS
- connectStart : การประทับเวลาก่อนสร้างการเชื่อมต่อเซิร์ฟเวอร์
- connectEnd : การประทับเวลาหลังจากสร้างการเชื่อมต่อเซิร์ฟเวอร์
- SecureConnectionStart : การประทับเวลาก่อนการจับมือ SSL
- requestStart : Timestamp ก่อนที่เบราว์เซอร์จะร้องขอทรัพยากร
- responseStart : Timestamp เมื่อเบราว์เซอร์ได้รับข้อมูลไบต์แรก
- responseEnd : Timestamp หลังจากได้รับไบต์สุดท้ายหรือปิดการเชื่อมต่อ
- ระยะเวลา : ความแตกต่างระหว่าง startTime และ responseEnd
- transferSize : ขนาดทรัพยากรเป็นไบต์รวมถึงส่วนหัวและเนื้อหาที่บีบอัด
- encodedBodySize : เนื้อหาทรัพยากรเป็นไบต์ก่อนคลายการบีบอัด
- decodedBodySize : เนื้อความของทรัพยากรเป็นไบต์หลังจากคลายการบีบอัด
สคริปต์ตัวอย่างนี้ดึงคำขอ Ajax ทั้งหมดที่เริ่มต้นโดย Fetch API และส่งคืนขนาดและระยะเวลาการถ่ายโอนทั้งหมด:
const fetchAll = performance.getEntriesByType('resource') .filter( r => r.initiatorType === 'fetch') .reduce( (sum, current) => { return { transferSize: sum.transferSize += current.transferSize, duration: sum.duration += current.duration } }, { transferSize: 0, duration: 0 } );
การวัดประสิทธิภาพการนำทาง
การกำหนดเวลาเครือข่ายสำหรับการยกเลิกการโหลดหน้าก่อนหน้าและการโหลดหน้าปัจจุบันจะถูกบันทึกโดยอัตโนมัติไปยังบัฟเฟอร์ประสิทธิภาพเป็นอ็อบเจ็กต์ PerformanceNavigationTiming
เดียว
แยกไปยังอาร์เรย์โดยใช้:
const pageTime = performance.getEntriesByType('navigation');
…หรือโดยส่ง URL ของหน้าไปที่ .getEntriesByName()
:
const pageTiming = performance.getEntriesByName(window.location);
เมตริกจะเหมือนกันกับเมตริกสำหรับทรัพยากรแต่รวมค่าเฉพาะหน้าด้วย:
- ประเภทรายการ : เช่น “การนำทาง”
- ประเภท : “นำทาง”, “โหลดซ้ำ”, “back_forward” หรือ “prerender”
- redirectCount : จำนวนการเปลี่ยนเส้นทาง
- unloadEventStart : Timestamp ก่อนเหตุการณ์ unload ของเอกสารก่อนหน้า
- unloadEventEnd : เวลาประทับหลังจากเหตุการณ์ยกเลิกการโหลดของเอกสารก่อนหน้า
- domInteractive : การประทับเวลาเมื่อเบราว์เซอร์แยกวิเคราะห์ HTML และสร้าง DOM
- domContentLoadedEventStart : การประทับเวลาก่อนที่เหตุการณ์ DOMContentLoaded ของเอกสารจะเริ่มทำงาน
- domContentLoadedEventEnd : การประทับเวลาหลังจากเหตุการณ์ DOMContentLoaded ของเอกสารเสร็จสิ้น
- domComplete : การประทับเวลาหลังจากการสร้าง DOM และ DOMContentLoaded เสร็จสิ้นแล้ว
- loadEventStart : การประทับเวลาก่อนที่เหตุการณ์การโหลดหน้าเว็บจะเริ่มขึ้น
- loadEventEnd : การประทับเวลาหลังจากเหตุการณ์การโหลดหน้าเว็บและเนื้อหาทั้งหมดพร้อมใช้งาน
ปัญหาทั่วไป ได้แก่ :
- การหน่วงเวลานานระหว่าง unloadEventEnd และ domInteractive ซึ่งอาจบ่งบอกถึงการตอบสนองของเซิร์ฟเวอร์ที่ช้า
- การหน่วงเวลานานระหว่าง domContentLoadedEventStart และ domComplete ซึ่งอาจบ่งชี้ว่าสคริปต์เริ่มต้นของหน้าช้าเกินไป
- การหน่วงเวลานานระหว่าง domComplete และ loadEventEnd ซึ่งอาจบ่งชี้ว่าหน้ามีเนื้อหามากเกินไปหรือหลายรายการใช้เวลาในการโหลดนานเกินไป
การบันทึกและวิเคราะห์ประสิทธิภาพ
Performance API ช่วยให้คุณสามารถเปรียบเทียบข้อมูลการใช้งานจริงและอัปโหลดไปยังเซิร์ฟเวอร์เพื่อการวิเคราะห์เพิ่มเติม คุณ สามารถ ใช้บริการของบุคคลที่สาม เช่น Google Analytics เพื่อจัดเก็บข้อมูล แต่มีความเสี่ยงที่สคริปต์ของบุคคลที่สามอาจถูกบล็อกหรือทำให้เกิดปัญหาด้านประสิทธิภาพการทำงานใหม่ โซลูชันของคุณเองสามารถปรับแต่งตามความต้องการของคุณได้ เพื่อให้แน่ใจว่าการตรวจสอบจะไม่ส่งผลกระทบต่อการทำงานอื่นๆ
ระวังสถานการณ์ที่ไม่สามารถระบุสถิติได้ — อาจเป็นเพราะผู้ใช้ใช้เบราว์เซอร์รุ่นเก่า บล็อก JavaScript หรืออยู่เบื้องหลังพร็อกซีขององค์กร การทำความเข้าใจว่าข้อมูลใดที่ขาดหายไปจะมีผลมากกว่าการตั้งสมมติฐานโดยอาศัยข้อมูลที่ไม่สมบูรณ์
ตามหลักการแล้ว สคริปต์การวิเคราะห์ของคุณจะไม่ส่งผลเสียต่อประสิทธิภาพโดยเรียกใช้การคำนวณที่ซับซ้อนหรืออัปโหลดข้อมูลจำนวนมาก พิจารณาใช้ Web Worker และลดการใช้การเรียก localStorage แบบซิงโครนัสให้น้อยที่สุด เป็นไปได้เสมอที่จะประมวลผลข้อมูลดิบเป็นชุดในภายหลัง
สุดท้าย ให้ระวังสิ่งผิดปกติ เช่น อุปกรณ์ที่เร็วหรือช้ามาก และการเชื่อมต่อที่ส่งผลเสียต่อสถิติ ตัวอย่างเช่น หากผู้ใช้เก้าคนโหลดหน้าเว็บในสองวินาที แต่ผู้ใช้ที่สิบพบการดาวน์โหลด 60 วินาที เวลาแฝงเฉลี่ยจะออกมาเกือบ 8 วินาที เมตริกที่สมจริงยิ่งขึ้นคือค่ามัธยฐาน (2 วินาที) หรือเปอร์เซ็นไทล์ที่ 90 (9 ในทุก ๆ 10 ผู้ใช้มีเวลาในการโหลด 2 วินาทีหรือน้อยกว่า)
สรุป
ประสิทธิภาพของเว็บยังคงเป็นปัจจัยสำคัญสำหรับนักพัฒนา ผู้ใช้คาดหวังว่าไซต์และแอปพลิเคชันจะตอบสนองในอุปกรณ์ส่วนใหญ่ การเพิ่มประสิทธิภาพกลไกค้นหาอาจได้รับผลกระทบเช่นกัน เนื่องจากไซต์ที่ช้ากว่าจะถูกดาวน์เกรดใน Google
มีเครื่องมือตรวจสอบประสิทธิภาพมากมาย แต่ส่วนใหญ่จะประเมินความเร็วในการดำเนินการฝั่งเซิร์ฟเวอร์หรือใช้ไคลเอ็นต์ที่มีความสามารถจำนวนจำกัดเพื่อตัดสินการแสดงผลของเบราว์เซอร์ Performance API มีวิธีเปรียบเทียบเมทริกผู้ใช้จริงที่ไม่สามารถคำนวณด้วยวิธีอื่นได้