Đá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 Thời gian tài nguyên và Điều hướng để đánh giá hiệu suất tải trong trường.

Nếu đã 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 sẽ biết những công cụ đó thuận tiện như thế nào trong việc điều chỉnh hiệu suất. Bạn có thể nhanh chóng đo lường tác động của tính nă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à thử nghiệm tổng hợp sẽ tạo ra dữ liệu phòng thí nghiệm chứ không phải dữ liệu thực tế.

Thử nghiệm tổng hợp vốn không kém, 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. Việc này yêu cầu dữ liệu trường mà bạn có thể thu thập từ API Thời gian điều hướng và Thời gian tài nguyên.

Các API giúp bạn đánh giá hiệu suất tải trong trường

Thời gian điều hướng và Thời gian tài nguyên là hai API tương tự nhau, có sự trùng lặp đáng kể, đo lường hai điều riêng biệt:

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

Các API này hiển thị dữ liệu trong vùng đệm mục hiệu suất. Bạn có thể truy cập 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 hiệu suất. 'navigation''resource' truy xuất thời gian cho API Thời gian điều hướng và API Thời gian tài nguyên tương ứng.

Lượng thông tin mà các API này cung cấp có thể quá lớn, nhưng chúng là yếu tố then chốt để đo lường hiệu suất tải tại hiện trường, vì bạn có thể thu thập các 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.

Thời gian tồn tại và thời gian của yêu cầu mạng

Việc thu thập và phân tích thời gian điều hướng và thời gian tài nguyên giống như khảo cổ học ở chỗ bạn đang xây dựng lại cuộc sống thoáng qua của một yêu cầu mạng sau khi thực tế. Đôi khi, việc 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 sẽ giúp ích, thì các công cụ cho nhà phát triển của trình duyệt có thể giúp ích cho bạn.

Sơ đồ về thời gian mạng như minh hoạ trong Công cụ cho nhà phát triển của Chrome. Thời gian được mô tả là dành cho việc đưa yêu cầu vào hàng đợi, thương lượng kết nối, bản thân yêu cầu và phản hồi trong thanh có mã màu.
Hình ảnh trực quan về 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

Thời gian hoạt động 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, thương lượng TLS, v.v. Các dấu thời gian này được biểu thị dưới dạng DOMHighResTimestamp. Tuỳ vào trình duyệt của bạn, độ chi tiết của thời gian có thể giảm xuống đến micrô giây hoặc làm tròn lên đến mili giây. Hãy cùng tìm hiểu chi tiết các giai đoạn này và 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) được truy vấn để chuyển đổi miền thành một đị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 sẽ muốn đo lường trong thực tế. Thời gian điều hướng và Thời gian tài nguyên hiển thị 2 dấu thời gian liên quan đến DNS:

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

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

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

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

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

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

Việc đo tổng thời gian kết nối tương tự như đo 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 khác có thể là 0 nếu bạn không sử dụng HTTPS hoặc nếu kết nối liên tục. Nếu muốn đo lường thời gian thương lượng 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;
}

Sau 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à tài nguyên phụ thuộc sẽ được áp dụng.

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: Đó 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à CDN, họ (hầu hết) nằm ngoài tầm kiểm soát của chúng tôi, vì người dùng có thể truy cập web từ bất cứ đâu.
  • Các yếu tố nội tại: Đó là những yếu tố như kiến trúc phía máy chủ và máy khách, cũng như kích thước tài nguyên và khả năng tối ưu hoá cho những yếu tố đó 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 các yếu tố này rất quan trọng, vì chúng mô tả thời gian tài nguyên 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 (Thời gian tài nguyên) hoặc tài liệu cho yêu cầu điều hướng (Thời gian điều hướng). Việc này diễn ra trước yêu cầu thực tế và là thời điểm trình duyệt kiểm tra bộ nhớ đệm (ví dụ: các phiên bản HTTP và 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ụ. Đây sẽ là 0 khi không có trình chạy dịch vụ nào kiểm soát trang hiện tại.
  • requestStart là khi trình duyệt đưa ra yêu cầu.
  • responseStart là khi byte đầu tiên của phản hồi đến.
  • responseEnd là khi byte cuối cùng của phản hồi đến.

Các dấu 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ư tra cứu bộ nhớ đệm trong một trình chạy 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 độ trễ yêu cầu/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 cho nhiều việc hơn so với những gì các ví dụ ở trên nêu ra. Sau đây là một số tình huống khác có thời gian liên quan mà bạn nên tìm hiểu:

  • Chuyển hướng trang: Chuyển hướng là một nguyên nhân có thể gây ra độ trễ gia tăng mà bạn có thể 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ư bước chuyển HTTP-to-HTTPs, cũng như chuyển hướng 302/uncache. Thời gian redirectStart, redirectEndredirectCount rất hữu ích trong việc đánh giá độ trễ của lệnh chuyển hướng.
  • Huỷ tải tài liệu: Trên 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 hoạt động 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 phải là yếu tố quyết định trừ khi trang web của bạn gửi các phần tải HTML rất lớn. Nếu điều này đúng với tình huống của bạn, bạn có thể quan tâm đến dấu thời gian domInteractive, domContentLoadedEventStart, domContentLoadedEventEnddomComplete.

Thời gian tiếp nhận trong mã xử lý ứng dụng

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 hiệu suất, chẳng hạn như performance.getEntriesByNameperformance.getEntries. Các phương pháp này hiệu quả khi bạn chỉ cần phân tích nhẹ. Tuy nhiên, trong các trường hợp khác, chúng có thể khiến luồng chính phải thực hiện quá nhiều thao tác bằng cách lặp lại trên 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.

Bạn nên sử dụng PerformanceObserver để thu thập các mục nhập từ vùng đệm mục nhập hiệu suất. PerformanceObserver theo dõi các mục nhập hiệu suất và cung cấp các mục này 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ể tạo ra sự bất tiện khi so với việc truy cập trực tiếp vào vùng đệm mục nhập hiệu suất. Tuy nhiên, bạn nên kết hợp luồng chính với các tác vụ không phục vụ mục đích quan trọng và dành cho người dùng.

Đang gửi tin nhắn đến nhà

Sau khi thu thập tất cả dấu thời gian cần thiết, bạn có thể gửi chúng đế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 đều 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 xếp vào hàng đợi theo cách kéo dài hơn phiên trang hiện tại nếu cần:

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

// The endpoint to transmit the encoded data to
const endpoint = '/analytics';

// Check for fetch keepalive support
if ('keepalive' in Request.prototype) {
  fetch(endpoint, {
    method: 'POST',
    body: data,
    keepalive: true,
    headers: {
      'Content-Type': 'application/json'
    }
  });
} else if ('sendBeacon' in navigator) {
  // Use sendBeacon as a fallback
  navigator.sendBeacon(endpoint, data);
}

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

Kết thúc

Sau khi thu thập các chỉ số, bạn có thể tìm hiểu 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 thủ một số quy tắc chung để đảm bảo rút ra kết luận có ý nghĩa:

  • Tránh số liệu trung bình, vì các giá trị này không đại diện cho bất kỳ trải nghiệm nào của một người dùng và có thể bị các điểm ngoại lai làm lệch đi.
  • Dựa vào phân vị. Trong tập dữ liệu về chỉ số hiệu suất dựa trên thời gian, giá trị 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ỉ chú ý đến trải nghiệm nhanh nhất.
  • Ưu tiên đuôi dài của các giá trị. Khi bạn ưu tiên các trải nghiệm ở phân vị thứ 75 trở lên, tức là bạn đang tập trung 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 toàn diện về Điều hướng hoặc Thời gian tài nguyên, mà là điểm bắt đầu. Dưới đây là một số tài nguyên khác có thể giúp ích cho bạn:

Với các API này và dữ liệu mà chúng cung cấp, bạn sẽ dễ dàng hơn để hiểu rõ hơn trải nghiệm của người dùng thực về hiệu suất tải, nhờ đó, bạn có thể 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 tại hiện trường.