Cách đánh giá hiệu suất tải trong trường bằng Thời gian điều hướng và Thời gian tài nguyên

Tìm hiểu kiến thức cơ bản về cách sử dụng API Điều hướng và API Thời gian tài nguyên để đánh giá hiệu suất tải trong trường.

Ngày phát hành: 8 tháng 10 năm 2021

Nếu bạn đã sử dụng tính năng điều tiết kết nối trong bảng điều khiển mạng trong các công cụ cho nhà phát triển của trình duyệt (hoặc Lighthouse trong Chrome) để đánh giá hiệu suất tải, thì bạn đã biết những công cụ đó có thuận tiện cho việc điều chỉnh hiệu suất không. Bạn có thể nhanh chóng đo lường tác động của hoạt động tối ưu hoá hiệu suất với tốc độ kết nối cơ sở nhất quán và ổn định. Vấn đề duy nhất là đây là kiểm thử tổng hợp, cho ra dữ liệu trong phòng thí nghiệm chứ không phải dữ liệu thực địa.

Thử nghiệm tổng hợp không phải là không tốt, nhưng không thể hiện tốc độ tải trang web của bạn đối với người dùng thực. Điều đó yêu cầu dữ liệu trường mà bạn có thể thu thập từ các API Thời gian điều hướng và Thời gian tài nguyên.

API giúp bạn đánh giá hiệu suất tải trong thực tế

Navigation Timing (Thời gian điều hướng) và Resource Timing (Thời gian tài nguyên) là hai API tương tự nhau, có nhiều điểm trùng lặp đáng kể và đo lường hai điều khác biệt:

  • Navigation Timing (Thời gian điều hướng) đo lường tốc độ của các yêu cầu đối với tài liệu HTML (tức là các yêu cầu điều hướng).
  • Điều tiết tài nguyên đo tốc độ của các yêu cầu đối với các tài nguyên phụ thuộc vào tài liệu, chẳng hạn như CSS, JavaScript, hình ảnh và các loại tài nguyên khác.

Các API này hiển thị dữ liệu của chúng trong một vùng đệm mục nhập hiệu suất. Bạn có thể truy cập vào vùng đệm này trong trình duyệt bằng JavaScript. Có nhiều cách để truy vấn vùng đệm hiệu suất, nhưng cách phổ biến là sử dụng performance.getEntriesByType:

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

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

performance.getEntriesByType chấp nhận một chuỗi mô tả loại mục nhập bạn muốn truy xuất từ vùng đệm mục nhập hiệu suất. 'navigation''resource' truy xuất thời gian tương ứng cho các API Thời gian điều hướng và API Thời gian tài nguyên.

Lượng thông tin mà những API này cung cấp có thể quá lớn, nhưng đó là yếu tố then chốt để đo lường hiệu suất tải trong trường hợp này, vì bạn có thể thu thập những dấu thời gian này từ người dùng khi họ truy cập vào trang web của bạn.

Vòng đời và thời gian của một yêu cầu mạng

Việc thu thập và phân tích quá trình điều hướng và thời gian tài nguyên giống như khảo cổ học, trong đó bạn đang xây dựng lại vòng đời ngắn ngủi của một yêu cầu mạng sau khi kết thúc. Đôi khi, công cụ cho nhà phát triển trên trình duyệt của bạn có thể trợ giúp bạn bằng cách trực quan hoá các khái niệm và trường hợp có liên quan đến yêu cầu mạng.

Thời gian mạng như hiển thị trong Công cụ cho nhà phát triển của Chrome. Các thời gian được mô tả là để xếp hàng yêu cầu, đàm phán kết nối, chính yêu cầu và phản hồi trong các thanh được mã hoá bằng màu.
Hình ảnh minh hoạ một yêu cầu mạng trong bảng điều khiển mạng của Công cụ cho nhà phát triển của Chrome

Vòng đời của một yêu cầu mạng có các giai đoạn riêng biệt, chẳng hạn như tra cứu DNS, thiết lập kết nối, đàm phán TLS và các nguồn độ trễ khác. Những thời gian này được biểu thị dưới dạng DOMHighResTimestamp. Tuỳ thuộc vào trình duyệt của bạn, độ chi tiết của thời gian có thể được giảm đến micrô giây hoặc được làm tròn đến mili giây. Bạn sẽ muốn kiểm tra chi tiết các giai đoạn này cũng như mối liên hệ của chúng với Thời gian điều hướng và Thời gian tài nguyên.

tra cứu DNS

Khi người dùng truy cập vào một URL, Hệ thống tên miền (DNS) sẽ được truy vấn để dịch miền sang địa chỉ IP. Quá trình này có thể mất nhiều thời gian, thậm chí là thời gian mà bạn muốn đo lường tại hiện trường. Navigation Timing (Thời gian điều hướng) và Resource Timing (Thời gian tài nguyên) hiển thị hai khoảng thời gian liên quan đến DNS:

  • domainLookupStart là thời điểm bắt đầu tra cứu DNS.
  • domainLookupEnd là thời điểm kết thúc quá trình tra cứu DNS.

Có thể tính tổng thời gian tra cứu DNS bằng cách lấy chỉ số kết thúc trừ đi chỉ số bắt đầu:

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

Thương lượng kết nối

Một yếu tố khác ảnh hưởng đến hiệu suất tải là quá trình thương lượng kết nối, tức là độ trễ phát sinh khi kết nối với máy chủ web. Nếu có HTTPS, quá trình này cũng sẽ bao gồm thời gian đàm phán TLS. Giai đoạn kết nối bao gồm ba thời điểm:

  • connectStart là thời điểm trình duyệt bắt đầu mở kết nối với máy chủ web.
  • Dấu secureConnectionStart đánh dấu thời điểm ứng dụng bắt đầu thương lượng TLS.
  • connectEnd là thời điểm thiết lập kết nối với máy chủ web.

Việc đo lường tổng thời gian kết nối cũng tương tự như đo lường tổng thời gian tra cứu DNS: bạn trừ thời gian bắt đầu khỏi thời gian kết thúc. Tuy nhiên, có một thuộc tính secureConnectionStart bổ sung có thể là 0 nếu không sử dụng HTTPS hoặc nếu kết nối là liên tục. Nếu muốn đo lường thời gian thương lượng về TLS, bạn cần lưu ý điều đó:

// 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;
}

Khi quá trình tra cứu DNS và thương lượng kết nối kết thúc, thời gian liên quan đến việc tìm nạp tài liệu và các tài nguyên phụ thuộc sẽ bắt đầu có hiệu lực.

Yêu cầu và phản hồi

Hiệu suất tải chịu ảnh hưởng của hai loại yếu tố:

  • Các yếu tố bên ngoài: Đây là những yếu tố như độ trễ và băng thông. Ngoài việc chọn một công ty lưu trữ và có thể là một CDN, chúng tôi (hầu hết) không kiểm soát được các yếu tố này vì người dùng có thể truy cập vào web từ bất kỳ đâu.
  • Các yếu tố nội tại: Đây là những yếu tố như kiến trúc phía máy chủ và phía máy khách, cũng như kích thước tài nguyên và khả năng tối ưu hóa cho những yếu tố đó, vốn nằm trong tầm kiểm soát của chúng tôi.

Cả hai loại yếu tố này đều ảnh hưởng đến hiệu suất tải. Thời gian liên quan đến những yếu tố này rất quan trọng, vì chúng cho biết thời gian cần để tải xuống. Cả Thời gian điều hướng và Thời gian tài nguyên đều mô tả hiệu suất tải với các chỉ số sau:

  • fetchStart đánh dấu thời điểm trình duyệt bắt đầu tìm nạp tài nguyên (Định thời tài nguyên) hoặc tài liệu cho yêu cầu điều hướng (Định thời điều hướng). Yêu cầu này nằm trước yêu cầu thực tế và là thời điểm trình duyệt đang kiểm tra bộ nhớ đệm (ví dụ: HTTP và các thực thể Cache).
  • workerStart đánh dấu thời điểm một yêu cầu bắt đầu được xử lý trong trình xử lý sự kiện fetch của một trình chạy dịch vụ. Thuộc tính này sẽ là 0 khi không có trình chạy dịch vụ nào đang kiểm soát trang hiện tại.
  • requestStart là thời điểm trình duyệt đưa ra yêu cầu.
  • responseStart là thời điểm byte đầu tiên của phản hồi đến.
  • responseEnd là thời điểm byte cuối cùng của phản hồi đến.

Các thời gian này cho phép bạn đo lường nhiều khía cạnh của hiệu suất tải, chẳng hạn như thời gian tìm nạp bộ nhớ đệm trong một worker dịch vụ thời gian tải xuống:

// 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;
}

Bạn cũng có thể đo lường các khía cạnh khác của yêu cầu và độ trễ phản hồi:

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;

Các phép đo khác bạn có thể thực hiện

Thời gian điều hướng và Thời gian tài nguyên hữu ích hơn so với những gì trình bày trong các ví dụ trước. Sau đây là một số tình huống khác về thời gian liên quan mà bạn nên tìm hiểu:

  • Lệnh chuyển hướng trang: Lệnh chuyển hướng là một nguồn gây độ trễ bị bỏ qua, đặc biệt là các chuỗi chuyển hướng. Độ trễ được thêm vào theo một số cách, chẳng hạn như chuyển từ HTTP sang HTTP, cũng như lệnh chuyển hướng 301/không được lưu vào bộ nhớ đệm. Thời gian redirectStart, redirectEndredirectCount rất hữu ích trong việc đánh giá độ trễ chuyển hướng.
  • Huỷ tải tài liệu: Trong các trang chạy mã trong trình xử lý sự kiện unload, trình duyệt phải thực thi mã đó trước khi có thể chuyển đến trang tiếp theo. unloadEventStartunloadEventEnd đo lường việc huỷ tải tài liệu.
  • Xử lý tài liệu: Thời gian xử lý tài liệu có thể không quan trọng trừ khi trang web của bạn gửi tải trọng HTML rất lớn. Nếu đây là trường hợp của bạn, bạn có thể quan tâm đến các dấu thời gian domInteractive, domContentLoadedEventStart, domContentLoadedEventEnddomComplete.

Cách lấy thời gian trong mã

Cho đến nay, tất cả ví dụ trình bày đều sử dụng performance.getEntriesByType, nhưng có những cách khác để truy vấn vùng đệm mục nhập hiệu suất, chẳng hạn như performance.getEntriesByNameperformance.getEntries. Các phương pháp này rất hiệu quả khi chỉ cần phân tích ánh sáng. Tuy nhiên, trong các trường hợp khác, chúng có thể gây ra quá nhiều công việc cho luồng chính bằng cách lặp lại một số lượng lớn mục nhập hoặc thậm chí liên tục thăm dò vùng đệm hiệu suất để tìm các mục nhập mới.

Phương pháp đề xuất để thu thập các mục nhập từ vùng đệm mục nhập hiệu suất là sử dụng PerformanceObserver. PerformanceObserver theo dõi các mục nhập hiệu suất và cung cấp các mục đó khi được thêm vào vùng đệm:

// 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
});

Phương pháp thu thập thời gian này có thể gây khó chịu khi so sánh với việc truy cập trực tiếp vào vùng đệm nhập hiệu suất. Tuy nhiên, bạn nên liên kết luồng chính với tác vụ không phục vụ mục đích quan trọng và dành cho người dùng.

Cách gọi điện về nhà

Sau khi thu thập tất cả thời gian cần thiết, bạn có thể gửi các thời gian đó đến một điểm cuối để phân tích thêm. Có hai cách để thực hiện việc này là sử dụng navigator.sendBeacon hoặc fetch với tuỳ chọn keepalive được đặt. Cả hai phương thức này sẽ gửi yêu cầu đến một điểm cuối được chỉ định theo cách không chặn và yêu cầu sẽ được đưa vào hàng đợi theo cách tồn tại lâu hơn phiên trang hiện tại nếu cần:

// 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);
}

Trong ví dụ này, chuỗi JSON sẽ đến một tải trọng POST mà bạn có thể giải mã, xử lý và lưu trữ trong phần phụ trợ của ứng dụng nếu cần.

Kết luận

Khi đã thu thập được chỉ số, bạn có trách nhiệm tìm cách phân tích dữ liệu của trường đó. Khi phân tích dữ liệu thực địa, bạn cần tuân theo một số quy tắc chung để đảm bảo rằng bạn đang rút ra được những kết luận có ý nghĩa:

  • Tránh sử dụng giá trị trung bình vì giá trị này không thể hiện trải nghiệm của bất kỳ người dùng nào và có thể bị sai lệch do các giá trị ngoại lai.
  • Dựa vào phân vị. Trong tập dữ liệu của các chỉ số hiệu suất dựa trên thời gian, chỉ số càng thấp thì càng tốt. Điều này có nghĩa là khi ưu tiên phân vị thấp, bạn chỉ tập trung vào những trải nghiệm nhanh nhất.
  • Ưu tiên phần dài của các giá trị. Khi ưu tiên các trải nghiệm ở phân vị thứ 75 trở lên, bạn sẽ đặt trọng tâm vào những trải nghiệm có tốc độ chậm nhất.

Hướng dẫn này không phải là tài nguyên đầy đủ về tính năng Điều hướng hoặc Thời gian tải tài nguyên, mà là một điểm xuất phát. Dưới đây là một số tài nguyên bổ sung mà bạn có thể thấy hữu ích:

Với các API này và dữ liệu mà chúng cung cấp, bạn sẽ hiểu rõ hơn về trải nghiệm hiệu suất tải của người dùng thực tế, nhờ đó, bạn sẽ tự tin hơn trong việc chẩn đoán và giải quyết các vấn đề về hiệu suất tải trong thực tế.