Thuật toán đánh dấu và quét
Thuật toán Mark and Sweep tìm kiếm các đối tượng 'không thể truy cập được' thay vì các đối tượng 'không còn cần thiết nữa'. Thuật toán này là sự cải tiến của thuật toán đếm tham chiếu.
Thuật toán này thực sự trải qua 3 bước quan trọng.
- Root:Nói chung, root là một biến toàn cục được sử dụng trong mã. Một đối tượng window trong javascript có thể hoạt động như một root. Thuật toán này sử dụng gốc đối tượng toàn cục để tìm xem các đối tượng có thể truy cập được hay không thể truy cập được.
- Thuật toán này sau đó sẽ giám sát mọi gốc và cả con của chúng. Trong khi theo dõi, một số đối tượng có thể truy cập được sẽ được đánh dấu và các đối tượng còn lại không thể truy cập được sẽ không được đánh dấu dựa trên các điều kiện đã cung cấp.
- Các đối tượng không được đánh dấu, có nghĩa là không thể truy cập được sẽ được thu gom.
Đánh dấu giai đoạn
Trong giai đoạn đánh dấu, chúng ta có thể tìm thấy phần tử nào được đánh dấu và phần tử nào chưa được đánh dấu. Giả sử gán một thuộc tính "hello" cho một đối tượng "obj1" như được hiển thị trong Ví dụ-1 đã cho. Đối tượng gốc, toàn cục được sử dụng bởi thuật toán này, có thể truy cập tới obj1 và thuộc tính 'hello' của nó. Vì vậy, nó được đánh dấu ngay bây giờ.
Ví dụ-1
var obj1 = { pro1: "hello" // marked because it can be reached by root. }
Giả sử, hãy để đối tượng này được gán một giá trị null như được hiển thị trong Ví dụ-2. Sau đó, 'null' mới được gán sẽ được đánh dấu và 'thuộc tính hello' đã được gán trước đó sẽ được bỏ đánh dấu. Vì vậy, vào cuối giai đoạn Đánh dấu, chúng ta có thể kết luận rằng đối tượng được gán với 'null' đã được đánh dấu và đối tượng được gán với 'thuộc tính hello' đã được bỏ đánh dấu.
Ví dụ-2
obj1 = null // null will be marked(reachable) and hello will be unmarked(unreachable)
Giai đoạn quét
Như tên cho thấy nó 'quét' các đối tượng không thể truy cập. Trong giai đoạn đánh dấu, chúng tôi đã thấy rằng đối tượng có "thuộc tính hello" không được đánh dấu, khiến nó không thể truy cập được. Vì các đối tượng không thể truy cập sẽ được thu gom rác, đối tượng có 'thuộc tính hello' sẽ được thu gom trong giai đoạn này.
Thuật toán Mark and Sweep còn được gọi là một trình thu gom rác theo dõi vì nó theo dõi toàn bộ tập hợp các đối tượng mà chương trình có thể truy cập trực tiếp hoặc gián tiếp.
Chu kỳ không còn là vấn đề nữa
Trong ví dụ sau, khi lời gọi hàm trả về, hai đối tượng obj1 và obj2 không được tham chiếu bởi thứ gì đó có thể truy cập được ở đó bởi đủ điều kiện để thu gom rác. Vì vậy, bộ thu gom rác sẽ giải phóng bộ nhớ của các đối tượng obj1 và obj2.
Ví dụ
function f() { var obj1 = {}; var obj2 = {}; obj1.p = obj2; // obj1 references obj2 obj2.p = obj1; // obj2 references obj1. This creates a cycle. } f();
Hạn chế
Có một số thời điểm rất thuận tiện để quyết định thủ công khi nào và bộ nhớ nào được giải phóng. Để giải phóng bộ nhớ của đối tượng, nó phải được thực hiện rõ ràng là không thể truy cập được. Hiện tại không thể thực hiện quy trình kích hoạt thu gom rác trong JavaScript một cách rõ ràng.