Ghi lại ảnh chụp nhanh của vùng nhớ khối xếp

Meggin Kearney
Meggin Kearney
Sofia Emelianova
Sofia Emelianova

Tìm hiểu cách ghi lại ảnh chụp nhanh vùng nhớ khối xếp bằng Memory > Hồ sơ > Tổng quan nhanh về vùng nhớ khối xếp và tìm lỗi rò rỉ bộ nhớ.

Trình phân tích vùng nhớ khối xếp hiển thị mức phân bổ bộ nhớ theo các đối tượng JavaScript trên trang của bạn và các nút DOM có liên quan. Hãy sử dụng thư viện này để chụp nhanh ảnh chụp nhanh của vùng nhớ khối xếp JS, phân tích biểu đồ bộ nhớ, so sánh bản tổng quan nhanh và tìm lỗi rò rỉ bộ nhớ. Để biết thêm thông tin, hãy xem bài viết Đối tượng giữ lại cây.

Chụp nhanh

Cách chụp ảnh nhanh vùng nhớ khối xếp:

  1. Trên trang bạn muốn lập hồ sơ, hãy mở Công cụ cho nhà phát triển rồi chuyển đến bảng điều khiển Bộ nhớ.
  2. Chọn loại hồ sơ Bản tổng quan nhanh về vùng nhớ khối xếp, sau đó chọn một thực thể máy ảo JavaScript rồi nhấp vào Lấy bản tổng quan nhanh.

Một loại hồ sơ và thực thể máy ảo JavaScript đã chọn.

Khi bảng điều khiển Memory (Bộ nhớ) tải và phân tích cú pháp ảnh chụp nhanh, bảng điều khiển này sẽ hiển thị tổng kích thước của các đối tượng JavaScript có thể truy cập bên dưới tiêu đề ảnh chụp nhanh trong phần HEAP SNAPSHOTS (ẢNH CHỤP NHANH VÙNG NHỚ KÉP).

Tổng kích thước của các đối tượng có thể truy cập.

Ảnh chụp nhanh chỉ hiển thị các đối tượng từ biểu đồ bộ nhớ có thể truy cập được từ đối tượng chung. Việc chụp ảnh nhanh luôn bắt đầu với việc thu gom rác.

Ảnh chụp nhanh của các đối tượng Item phân tán.

Xoá ảnh chụp nhanh

Để xoá tất cả ảnh chụp nhanh, hãy nhấp vào Xoá tất cả trang doanh nghiệp:

Xoá tất cả hồ sơ.

Xem ảnh chụp nhanh

Để kiểm tra ảnh chụp nhanh từ nhiều góc độ cho nhiều mục đích, hãy chọn một trong các chế độ xem trong trình đơn thả xuống ở trên cùng:

Xem Nội dung Mục đích
Tóm tắt Các đối tượng được nhóm theo tên hàm khởi tạo. Hãy sử dụng tính năng này để săn tìm các đối tượng và mức sử dụng bộ nhớ của chúng dựa trên kiểu. Hữu ích cho việc theo dõi rò rỉ DOM.
So sánh Sự khác biệt giữa hai ảnh chụp nhanh. Sử dụng hàm này để so sánh hai (hoặc nhiều) ảnh chụp nhanh, trước và sau khi thực hiện một thao tác. Xác nhận sự hiện diện và nguyên nhân gây rò rỉ bộ nhớ bằng cách kiểm tra delta trong bộ nhớ đã giải phóng và số lượng tham chiếu.
Vùng chứa Nội dung của vùng nhớ khối xếp Mang đến một cái nhìn rõ ràng hơn về cấu trúc đối tượng và giúp phân tích các đối tượng được tham chiếu trong không gian tên chung (cửa sổ) để tìm những gì khiến chúng tồn tại. Hãy sử dụng tính năng này để phân tích các điểm đóng và phân tích đối tượng của bạn ở cấp độ thấp.
Số liệu thống kê Biểu đồ hình tròn về phân bổ bộ nhớ Xem kích thước thực tế của các phần bộ nhớ được phân bổ cho mã, chuỗi, mảng JS, mảng đã nhập và đối tượng hệ thống.

Chế độ xem Tóm tắt được chọn trong trình đơn thả xuống ở trên cùng.

Chế độ xem tóm tắt

Ban đầu, một ảnh chụp nhanh của vùng nhớ khối xếp sẽ mở trong chế độ xem Tóm tắt, trong đó liệt kê các Hàm khởi tạo trong một cột. Bạn có thể mở rộng hàm khởi tạo để xem các đối tượng mà hàm khởi tạo tạo bản sao.

Chế độ xem Tóm tắt với một hàm khởi tạo được mở rộng.

Để lọc ra những hàm khởi tạo không liên quan, hãy nhập tên mà bạn muốn kiểm tra trong Class filter (Bộ lọc lớp) ở đầu chế độ xem Tóm tắt.

Những con số bên cạnh tên hàm khởi tạo cho biết tổng số đối tượng được tạo bằng hàm khởi tạo. Chế độ xem Tóm tắt cũng hiển thị các cột sau:

  • Khoảng cách cho biết khoảng cách đến gốc bằng cách sử dụng đường dẫn đơn giản ngắn nhất của các nút.
  • Kích thước của đối tượng cho biết tổng kích thước của tất cả các đối tượng do một hàm khởi tạo nhất định tạo ra. Kích thước của đối tượng là kích thước bộ nhớ do chính đối tượng lưu giữ. Nhìn chung, các mảng và chuỗi có kích thước nông lớn hơn. Hãy xem thêm bài viết Kích thước đối tượng.
  • Kích thước được giữ lại cho biết kích thước được giữ lại tối đa trong cùng một nhóm đối tượng. Dung lượng được giữ lại là dung lượng bộ nhớ mà bạn có thể giải phóng bằng cách xoá một đối tượng và làm cho các phần phụ thuộc của đối tượng đó không còn truy cập được. Hãy xem thêm bài viết Kích thước đối tượng.

Khi bạn mở rộng một hàm khởi tạo, chế độ xem Summary (Tóm tắt) sẽ hiển thị tất cả các thực thể của hàm khởi tạo đó. Mỗi thực thể sẽ có bảng chi tiết về kích thước nông và kích thước được giữ lại của thực thể trong các cột tương ứng. Số sau ký tự @ là mã nhận dạng duy nhất của đối tượng. Công cụ này cho phép bạn so sánh ảnh chụp nhanh của vùng nhớ khối xếp theo từng đối tượng.

Bộ lọc hàm khởi tạo

Chế độ xem Tóm tắt cho phép bạn lọc các hàm khởi tạo dựa trên các trường hợp phổ biến có sử dụng bộ nhớ không hiệu quả.

Để sử dụng các bộ lọc này, hãy chọn một trong các tùy chọn sau từ trình đơn thả xuống ở ngoài cùng bên phải trong thanh tác vụ:

  • Tất cả đối tượng: mọi đối tượng được chụp bằng ảnh chụp nhanh hiện tại. Đặt theo mặc định.
  • Các đối tượng được phân bổ trước ảnh chụp nhanh 1: các đối tượng được tạo và vẫn còn trong bộ nhớ trước khi chụp ảnh chụp nhanh đầu tiên.
  • Đối tượng được phân bổ giữa Bản tổng quan nhanh 1 và Bản tổng quan nhanh 2: xem sự khác biệt về các đối tượng giữa bản tổng quan nhanh gần đây nhất và bản tổng quan nhanh trước đó. Mỗi ảnh chụp nhanh mới sẽ thêm một giá trị gia tăng của bộ lọc này vào danh sách thả xuống.
  • Chuỗi bị trùng lặp: các giá trị chuỗi đã được lưu trữ nhiều lần trong bộ nhớ.
  • Các đối tượng được các nút đã tách giữ lại: các đối tượng được duy trì hoạt động vì một nút DOM đã tách tham chiếu đến các đối tượng đó.
  • Đối tượng mà bảng điều khiển Công cụ cho nhà phát triển giữ lại: các đối tượng được giữ lại trong bộ nhớ vì chúng được đánh giá hoặc tương tác thông qua bảng điều khiển Công cụ cho nhà phát triển.

Các mục đặc biệt trong phần Tóm tắt

Ngoài việc nhóm theo hàm khởi tạo, chế độ xem Tóm tắt cũng nhóm các đối tượng theo:

  • Các hàm tích hợp sẵn như Array hoặc Object.
  • Các phần tử HTML được nhóm theo thẻ của chúng, ví dụ: <div>, <a>, <img>, v.v.
  • Các hàm mà bạn đã xác định trong mã của mình.
  • Các danh mục đặc biệt không dựa trên hàm khởi tạo.

Mục nhập hàm khởi tạo.

(array)

Danh mục này bao gồm nhiều đối tượng nội bộ giống mảng không tương ứng trực tiếp với các đối tượng hiển thị trong JavaScript.

Ví dụ: nội dung của các đối tượng Array JavaScript được lưu trữ trong đối tượng nội bộ phụ có tên là (object elements)[], để cho phép đổi kích thước dễ dàng hơn. Tương tự, các thuộc tính có tên trong đối tượng JavaScript thường được lưu trữ trong đối tượng nội bộ phụ có tên là (object properties)[]. Các đối tượng này cũng được liệt kê trong danh mục (array).

(compiled code)

Danh mục này bao gồm dữ liệu nội bộ mà V8 cần để có thể chạy các hàm do JavaScript hoặc WebAssembly xác định. Mỗi hàm có thể được biểu thị theo nhiều cách, từ nhỏ và chậm đến lớn và nhanh.

V8 tự động quản lý việc sử dụng bộ nhớ trong danh mục này. Nếu một hàm chạy nhiều lần, V8 sẽ sử dụng nhiều bộ nhớ hơn cho hàm đó để hàm có thể chạy nhanh hơn. Nếu một hàm không chạy trong một khoảng thời gian, V8 có thể xoá dữ liệu nội bộ của hàm đó.

(concatenated string)

Khi nối hai chuỗi, chẳng hạn như với toán tử + của JavaScript, V8 có thể chọn biểu thị kết quả nội bộ dưới dạng "chuỗi nối" còn gọi là cấu trúc dữ liệu Rope.

Thay vì sao chép tất cả ký tự của 2 chuỗi nguồn vào một chuỗi mới, V8 phân bổ một đối tượng nhỏ có các trường nội bộ có tên là firstsecond trỏ đến 2 chuỗi nguồn. Việc này giúp V8 tiết kiệm thời gian và bộ nhớ. Về khía cạnh mã JavaScript, đây chỉ là các chuỗi thông thường và hoạt động giống như mọi chuỗi khác.

InternalNode

Danh mục này thể hiện các đối tượng được phân bổ bên ngoài V8, chẳng hạn như đối tượng C++ do lệnh Blink xác định.

Để xem tên lớp C++, hãy sử dụng Chrome for Testing và thực hiện như sau:

  1. Mở DevTools rồi bật Settings (Cài đặt) > Experiments (Thử nghiệm) > Show option to expose internals in heap snapshots (Hiện tuỳ chọn để hiển thị nội dung bên trong trong ảnh chụp nhanh vùng nhớ khối xếp).
  2. Mở bảng điều khiển Memory (Bộ nhớ), chọn (Tổng quan nhanh về vùng nhớ khối xếp) rồi bật Hiển thị nội dung bên trong (bao gồm cả thông tin chi tiết bổ sung về quá trình triển khai).
  3. Tái hiện vấn đề đã khiến InternalNode giữ lại nhiều bộ nhớ.
  4. Chụp nhanh vùng nhớ khối xếp. Trong ảnh chụp nhanh này, các đối tượng có tên lớp C++ thay vì InternalNode.
(object shape)

Như đã mô tả trong phần Thuộc tính nhanh trong V8, V8 theo dõi các lớp bị ẩn (hoặc hình dạng) để có thể biểu thị hiệu quả nhiều đối tượng có cùng thuộc tính theo cùng một thứ tự. Danh mục này chứa các lớp ẩn đó, được gọi là system / Map (không liên quan đến JavaScript Map) và dữ liệu liên quan.

(sliced string)

Khi V8 cần lấy một chuỗi con, chẳng hạn như khi mã JavaScript gọi String.prototype.substring(), V8 có thể chọn phân bổ đối tượng chuỗi được cắt lát thay vì sao chép tất cả ký tự có liên quan từ chuỗi ban đầu. Đối tượng mới này chứa con trỏ đến chuỗi gốc và mô tả phạm vi ký tự trong chuỗi gốc cần sử dụng.

Về khía cạnh mã JavaScript, đây chỉ là các chuỗi thông thường và hoạt động giống như mọi chuỗi khác. Nếu một chuỗi bị cắt vẫn giữ nhiều bộ nhớ, thì chương trình này có thể đã kích hoạt Vấn đề 2869 và có thể hưởng lợi từ việc thực hiện các bước có chủ ý để "làm phẳng" chuỗi được cắt lát.

system / Context

Các đối tượng nội bộ thuộc loại system / Context chứa các biến cục bộ từ một hàm đóng – một phạm vi JavaScript mà hàm lồng nhau có thể truy cập.

Mỗi thực thể hàm đều chứa một con trỏ nội bộ đến Context mà hàm thực thi để có thể truy cập vào các biến đó. Mặc dù các đối tượng Context không hiển thị trực tiếp qua JavaScript, nhưng bạn có quyền kiểm soát trực tiếp các đối tượng đó.

(system)

Danh mục này chứa nhiều đối tượng nội bộ (chưa) được phân loại theo cách có ý nghĩa hơn.

Chế độ xem so sánh

Chế độ xem So sánh cho phép bạn tìm thấy các đối tượng bị rò rỉ bằng cách so sánh nhiều ảnh chụp nhanh với nhau. Ví dụ: khi thực hiện một thao tác và đảo ngược thao tác đó, chẳng hạn như mở và đóng tài liệu, bạn không nên để lại đối tượng thừa.

Cách xác minh một thao tác nhất định không gây ra rò rỉ thông tin:

  1. Chụp nhanh vùng nhớ khối xếp trước khi thực hiện một thao tác.
  2. Thực hiện một thao tác. Điều đó nghĩa là tương tác với trang theo cách nào đó mà bạn cho rằng có thể gây ra rò rỉ.
  3. Thực hiện một thao tác đảo ngược. Tức là thực hiện tương tác ngược lại và lặp lại vài lần.
  4. Chụp ảnh chụp nhanh vùng nhớ khối xếp thứ hai và thay đổi chế độ xem thành So sánh, so sánh ảnh chụp nhanh này với Ảnh chụp nhanh 1.

Chế độ xem So sánh cho thấy sự khác biệt giữa hai bản tổng quan nhanh. Khi mở rộng một tổng mục nhập, các thực thể đối tượng đã thêm và đã xoá được hiển thị:

So sánh với Ảnh chụp nhanh 1.

Chế độ xem toà nhà

Chế độ xem Vùng chứa là "chế độ xem từ trên cao" trong cấu trúc đối tượng của ứng dụng. Công cụ này cho phép bạn xem bên trong các hàm đóng, quan sát các đối tượng nội bộ của máy ảo cùng tạo thành các đối tượng JavaScript, đồng thời nắm được mức sử dụng bộ nhớ mà ứng dụng của bạn sử dụng ở cấp rất thấp.

Thành phần hiển thị này cung cấp một số điểm truy cập:

  • Đối tượng DOMWindow. Đối tượng toàn cầu cho mã JavaScript.
  • Gốc GC. R gốc GC mà trình thu gom rác của máy ảo sử dụng. Các thư mục gốc GC có thể bao gồm bản đồ đối tượng tích hợp, bảng ký hiệu, ngăn xếp luồng máy ảo, bộ nhớ đệm biên dịch, phạm vi xử lý và tay cầm toàn cục.
  • Đối tượng gốc. Đối tượng trình duyệt "được đẩy" bên trong máy ảo JavaScript để cho phép tự động hoá, ví dụ: nút DOM và quy tắc CSS.

Khung hiển thị Vùng chứa.

Phần Phần giữ lại

Phần Keepers (Phần giữ lại) ở cuối bảng điều khiển Memory (Bộ nhớ) hiện các đối tượng trỏ đến đối tượng đã chọn trong khung hiển thị. Bảng điều khiển Memory (Bộ nhớ) sẽ cập nhật phần Keepers (Trình giữ lại) khi bạn chọn một đối tượng khác trong bất kỳ khung hiển thị nào, ngoại trừ Thống kê (Thống kê).

Phần Giữ lại.

Trong ví dụ này, chuỗi đã chọn được thuộc tính x của một thực thể Item giữ lại.

Bỏ qua trình lưu giữ

Bạn có thể ẩn các phương thức lưu giữ để phát hiện những đối tượng khác có thể giữ lại đối tượng đã chọn. Với tuỳ chọn này, trước tiên bạn không cần phải xoá trình lưu giữ này khỏi mã rồi chụp lại ảnh chụp nhanh của vùng nhớ khối xếp.

Tuỳ chọn &quot;Bỏ qua khoản phí giữ chân này&quot; trong trình đơn thả xuống.

Để ẩn trình lưu giữ, hãy nhấp chuột phải và chọn Bỏ qua trình lưu giữ này. Những thành phần lưu giữ bị bỏ qua được đánh dấu là ignored trong cột Khoảng cách. Để dừng bỏ qua tất cả các trình lưu giữ, hãy nhấp vào Khôi phục các trình lưu giữ bị bỏ qua trong thanh tác vụ ở trên cùng.

Tìm một đối tượng cụ thể

Để tìm một đối tượng trong vùng nhớ khối xếp đã thu thập, bạn có thể tìm kiếm bằng tổ hợp phím Ctrl + F rồi nhập mã đối tượng.

Đặt tên cho các hàm để phân biệt các bao đóng

Việc này rất hữu ích khi đặt tên cho các hàm để bạn có thể phân biệt giữa các bao đóng trong bản tổng quan nhanh.

Ví dụ: mã sau đây không sử dụng hàm được đặt tên:

function createLargeClosure() {
  var largeStr = new Array(1000000).join('x');

  var lC = function() { // this is NOT a named function
    return largeStr;
  };

  return lC;
}

Trong khi ví dụ này là:

function createLargeClosure() {
  var largeStr = new Array(1000000).join('x');

  var lC = function lC() { // this IS a named function
    return largeStr;
  };

  return lC;
}

Hàm được đặt tên trong một phần đóng.

Phát hiện rò rỉ DOM

Trình phân tích vùng nhớ khối xếp có khả năng phản ánh các phần phụ thuộc hai chiều giữa đối tượng gốc của trình duyệt (nút DOM và quy tắc CSS) và đối tượng JavaScript. Điều này giúp phát hiện các sự cố rò rỉ vô hình xảy ra do các cây con DOM tách rời bị quên trôi nổi xung quanh.

Tình trạng rò rỉ DOM có thể nghiêm trọng hơn bạn nghĩ. Hãy xem ví dụ sau đây. Khi nào rác #tree được thu thập?

  var select = document.querySelector;
  var treeRef = select("#tree");
  var leafRef = select("#leaf");
  var body = select("body");

  body.removeChild(treeRef);

  //#tree can't be GC yet due to treeRef
  treeRef = null;

  //#tree can't be GC yet due to indirect
  //reference from leafRef

  leafRef = null;
  //#NOW #tree can be garbage collected

#leaf duy trì tham chiếu đến phần tử mẹ (parentNode) và đệ quy lên đến #tree, vì vậy chỉ khi leafRef bị rỗng là cây toàn bộ trong #tree một ứng viên cho GC.

Cây con DOM