Python xóa bộ nhớ trong vòng lặp

Các ngôn ngữ cấp thấp như C, có các nguyên hàm quản lý bộ nhớ thủ công như

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
1 và. Ngược lại, JavaScript tự động cấp phát bộ nhớ khi các đối tượng được tạo và giải phóng bộ nhớ khi chúng không được sử dụng nữa (thu gom rác). Tính tự động này là một nguồn gây nhầm lẫn tiềm ẩn. nó có thể khiến các nhà phát triển có ấn tượng sai lầm rằng họ không cần phải lo lắng về việc quản lý bộ nhớ

Bất kể ngôn ngữ lập trình nào, vòng đời của bộ nhớ hầu như luôn giống nhau

  1. Phân bổ bộ nhớ bạn cần
  2. Sử dụng bộ nhớ được cấp phát (đọc, ghi)
  3. Giải phóng bộ nhớ được cấp phát khi không cần thiết nữa

Phần thứ hai là rõ ràng trong tất cả các ngôn ngữ. Phần đầu tiên và phần cuối cùng rõ ràng trong các ngôn ngữ cấp thấp nhưng chủ yếu là ẩn trong các ngôn ngữ cấp cao như JavaScript

Khởi tạo giá trị

Để không làm phiền lập trình viên với việc cấp phát, JavaScript sẽ tự động cấp phát bộ nhớ khi các giá trị được khai báo ban đầu

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener(
  "click",
  () => {
    someElement.style.backgroundColor = "blue";
  },
  false,
);

Phân bổ thông qua các cuộc gọi chức năng

Một số lệnh gọi hàm dẫn đến phân bổ đối tượng

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element

Một số phương thức phân bổ các giá trị hoặc đối tượng mới

const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.

Sử dụng các giá trị về cơ bản có nghĩa là đọc và ghi trong bộ nhớ được phân bổ. Điều này có thể được thực hiện bằng cách đọc hoặc ghi giá trị của một biến hoặc một thuộc tính đối tượng hoặc thậm chí chuyển một đối số cho một hàm

Phần lớn các vấn đề quản lý bộ nhớ xảy ra ở giai đoạn này. Khía cạnh khó khăn nhất của giai đoạn này là xác định khi nào bộ nhớ được cấp phát không còn cần thiết

Các ngôn ngữ cấp thấp yêu cầu nhà phát triển xác định thủ công tại thời điểm nào trong chương trình, bộ nhớ được cấp phát không còn cần thiết và giải phóng nó

Một số ngôn ngữ cấp cao, chẳng hạn như JavaScript, sử dụng một hình thức quản lý bộ nhớ tự động được gọi là bộ sưu tập rác (GC). Mục đích của bộ thu gom rác là giám sát việc phân bổ bộ nhớ và xác định khi nào một khối bộ nhớ được phân bổ không còn cần thiết nữa và lấy lại nó. Quá trình tự động này là một phép tính gần đúng vì vấn đề chung là xác định xem có cần một phần bộ nhớ cụ thể hay không là không thể giải quyết được

Như đã nêu ở trên, vấn đề chung của việc tự động tìm xem bộ nhớ nào đó "không cần thiết nữa" là không thể giải quyết được. Kết quả là, người thu gom rác thực hiện hạn chế giải pháp cho vấn đề chung. Phần này sẽ giải thích các khái niệm cần thiết để hiểu các thuật toán thu gom rác chính và các hạn chế tương ứng của chúng

Khái niệm chính mà thuật toán thu gom rác dựa vào là khái niệm tham chiếu. Trong bối cảnh quản lý bộ nhớ, một đối tượng được cho là tham chiếu đến một đối tượng khác nếu đối tượng trước có quyền truy cập vào đối tượng sau (ngầm hoặc rõ ràng). Chẳng hạn, một đối tượng JavaScript có tham chiếu đến nguyên mẫu của nó (tham chiếu ngầm) và các giá trị thuộc tính của nó (tham chiếu rõ ràng)

Trong bối cảnh này, khái niệm "đối tượng" được mở rộng thành một thứ gì đó rộng hơn các đối tượng JavaScript thông thường và cũng chứa các phạm vi chức năng (hoặc phạm vi từ vựng toàn cầu)

Đây là thuật toán thu gom rác ngây thơ nhất. Thuật toán này làm giảm vấn đề từ việc xác định xem một đối tượng có còn cần thiết hay không đến việc xác định xem một đối tượng có còn bất kỳ đối tượng nào khác tham chiếu đến nó hay không. Một đối tượng được cho là "rác" hoặc có thể sưu tập được nếu không có tham chiếu nào trỏ đến nó

Ví dụ

let x = {
  a: {
    b: 2,
  },
};
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'x' variable.
// Obviously, none can be garbage-collected.

let y = x;
// The 'y' variable is the second thing that has a reference to the object.

x = 1;
// Now, the object that was originally in 'x' has a unique reference
// embodied by the 'y' variable.

let z = y.a;
// Reference to 'a' property of the object.
// This object now has 2 references: one as a property,
// the other as the 'z' variable.

y = "mozilla";
// The object that was originally in 'x' has now zero
// references to it. It can be garbage-collected.
// However its 'a' property is still referenced by
// the 'z' variable, so it cannot be freed.

z = null;
// The 'a' property of the object originally in x
// has zero references to it. It can be garbage collected.

Có một hạn chế khi nói đến tham chiếu vòng tròn. Trong ví dụ sau, hai đối tượng được tạo với các thuộc tính tham chiếu lẫn nhau, do đó tạo ra một chu trình. Chúng sẽ vượt ra ngoài phạm vi sau khi lệnh gọi hàm hoàn thành. Tại thời điểm đó, chúng trở nên không cần thiết và bộ nhớ đã cấp phát của chúng sẽ được thu hồi. Tuy nhiên, thuật toán đếm tham chiếu sẽ không coi chúng là có thể thu hồi được vì mỗi đối tượng trong số hai đối tượng có ít nhất một tham chiếu trỏ đến chúng, dẫn đến việc không đối tượng nào trong số chúng được đánh dấu để thu gom rác. Tham chiếu vòng tròn là nguyên nhân phổ biến của rò rỉ bộ nhớ

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();

Internet Explorer 6 và 7 được biết là có bộ thu gom rác đếm tham chiếu, đã gây rò rỉ bộ nhớ với các tham chiếu vòng. Không có công cụ hiện đại nào sử dụng tính năng đếm tham chiếu để thu gom rác nữa

Thuật toán này rút gọn định nghĩa "đối tượng không còn cần thiết" thành "đối tượng không thể truy cập được"

Thuật toán này giả định kiến ​​thức về một tập hợp các đối tượng được gọi là gốc. Trong JavaScript, gốc là đối tượng toàn cầu. Theo định kỳ, trình thu gom rác sẽ bắt đầu từ các gốc này, tìm tất cả các đối tượng được tham chiếu từ các gốc này, sau đó là tất cả các đối tượng được tham chiếu từ các gốc này, v.v. Do đó, bắt đầu từ gốc, trình thu gom rác sẽ tìm tất cả các đối tượng có thể truy cập và thu thập tất cả các đối tượng không thể truy cập

Thuật toán này là một cải tiến so với thuật toán trước vì một đối tượng không có tham chiếu nào thực sự không thể truy cập được. Điều ngược lại không đúng như chúng ta đã thấy với các tham chiếu vòng tròn

Hiện tại, tất cả các động cơ hiện đại đều vận chuyển một bộ thu gom rác đánh dấu và quét. Tất cả các cải tiến được thực hiện trong lĩnh vực thu gom rác JavaScript (thu gom rác thế hệ/gia tăng/đồng thời/song song) trong vài năm qua là những cải tiến triển khai của thuật toán này, nhưng không phải là cải tiến đối với chính thuật toán thu gom rác cũng như việc giảm định nghĩa về thời điểm của nó.

Lợi ích trước mắt của phương pháp này là chu kỳ không còn là vấn đề. Trong ví dụ đầu tiên ở trên, sau khi lệnh gọi hàm trả về, hai đối tượng không còn được tham chiếu bởi bất kỳ tài nguyên nào có thể truy cập được từ đối tượng chung. Do đó, bộ thu gom rác sẽ phát hiện chúng không thể truy cập được và bộ nhớ đã cấp phát của chúng sẽ bị thu hồi.

Tuy nhiên, việc không thể kiểm soát thủ công việc thu gom rác vẫn còn. Đôi khi sẽ thuận tiện khi 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 một đối tượng, nó cần phải được làm cho không thể truy cập được một cách rõ ràng. Cũng không thể kích hoạt thu gom rác theo chương trình trong JavaScript — và có thể sẽ không bao giờ nằm ​​trong ngôn ngữ cốt lõi, mặc dù các công cụ có thể hiển thị các API đằng sau các cờ chọn tham gia

Các công cụ JavaScript thường cung cấp các cờ hiển thị mô hình bộ nhớ. Ví dụ, nút. js cung cấp các tùy chọn và công cụ bổ sung hiển thị các cơ chế V8 cơ bản để định cấu hình và gỡ lỗi các vấn đề về bộ nhớ. Cấu hình này có thể không khả dụng trong trình duyệt và thậm chí còn ít hơn đối với các trang web (thông qua tiêu đề HTTP, v.v. )

Số lượng bộ nhớ heap khả dụng tối đa có thể được tăng lên bằng cờ

node --max-old-space-size=6000 index.js

Chúng tôi cũng có thể hiển thị trình thu gom rác để gỡ lỗi các vấn đề về bộ nhớ bằng cách sử dụng cờ và Trình gỡ lỗi Chrome

node --expose-gc --inspect index.js

Mặc dù JavaScript không trực tiếp hiển thị API trình thu gom rác, nhưng ngôn ngữ này cung cấp một số cấu trúc dữ liệu gián tiếp quan sát quá trình thu gom rác và có thể được sử dụng để quản lý việc sử dụng bộ nhớ

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 và
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
4 là các cấu trúc dữ liệu có API phản ánh chặt chẽ các đối tác không yếu của chúng.
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
5 và
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
6.
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 cho phép bạn duy trì tập hợp các cặp khóa-giá trị, trong khi
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
4 cho phép bạn duy trì tập hợp các giá trị duy nhất, cả với tính năng thêm, xóa và truy vấn hiệu suất

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 và
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
4 lấy tên từ khái niệm giá trị được giữ yếu. Nếu
const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.
1 bị giữ yếu bởi
const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.
2, điều đó có nghĩa là mặc dù bạn có thể truy cập giá trị của
const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.
1 qua
const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.
2, nhưng thuật toán đánh dấu và quét sẽ không coi
const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.
1 là có thể truy cập được nếu không có gì khác giữ giá trị đó. Hầu hết các cấu trúc dữ liệu, ngoại trừ những cấu trúc được thảo luận ở đây, đều giữ chặt các đối tượng được truyền vào để bạn có thể truy xuất chúng bất kỳ lúc nào. Các khóa của
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 và
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
4 có thể được thu gom rác (đối với các đối tượng
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3, các giá trị sau đó cũng sẽ đủ điều kiện để thu gom rác) miễn là không có gì khác trong chương trình tham chiếu đến khóa. Điều này được đảm bảo bởi hai đặc điểm

  • const d = new Date(); // allocates a Date object
    
    const e = document.createElement("div"); // allocates a DOM element
    
    3 và
    const d = new Date(); // allocates a Date object
    
    const e = document.createElement("div"); // allocates a DOM element
    
    4 chỉ có thể lưu trữ các đối tượng. Điều này là do chỉ các đối tượng được thu thập rác — các giá trị nguyên thủy luôn có thể bị giả mạo (nghĩa là,
    let x = {
      a: {
        b: 2,
      },
    };
    // 2 objects are created. One is referenced by the other as one of its properties.
    // The other is referenced by virtue of being assigned to the 'x' variable.
    // Obviously, none can be garbage-collected.
    
    let y = x;
    // The 'y' variable is the second thing that has a reference to the object.
    
    x = 1;
    // Now, the object that was originally in 'x' has a unique reference
    // embodied by the 'y' variable.
    
    let z = y.a;
    // Reference to 'a' property of the object.
    // This object now has 2 references: one as a property,
    // the other as the 'z' variable.
    
    y = "mozilla";
    // The object that was originally in 'x' has now zero
    // references to it. It can be garbage-collected.
    // However its 'a' property is still referenced by
    // the 'z' variable, so it cannot be freed.
    
    z = null;
    // The 'a' property of the object originally in x
    // has zero references to it. It can be garbage collected.
    
    1 nhưng
    let x = {
      a: {
        b: 2,
      },
    };
    // 2 objects are created. One is referenced by the other as one of its properties.
    // The other is referenced by virtue of being assigned to the 'x' variable.
    // Obviously, none can be garbage-collected.
    
    let y = x;
    // The 'y' variable is the second thing that has a reference to the object.
    
    x = 1;
    // Now, the object that was originally in 'x' has a unique reference
    // embodied by the 'y' variable.
    
    let z = y.a;
    // Reference to 'a' property of the object.
    // This object now has 2 references: one as a property,
    // the other as the 'z' variable.
    
    y = "mozilla";
    // The object that was originally in 'x' has now zero
    // references to it. It can be garbage-collected.
    // However its 'a' property is still referenced by
    // the 'z' variable, so it cannot be freed.
    
    z = null;
    // The 'a' property of the object originally in x
    // has zero references to it. It can be garbage collected.
    
    2), khiến chúng nằm trong bộ sưu tập mãi mãi
  • const d = new Date(); // allocates a Date object
    
    const e = document.createElement("div"); // allocates a DOM element
    
    3 và
    const d = new Date(); // allocates a Date object
    
    const e = document.createElement("div"); // allocates a DOM element
    
    4 không thể lặp lại. Điều này ngăn bạn sử dụng
    let x = {
      a: {
        b: 2,
      },
    };
    // 2 objects are created. One is referenced by the other as one of its properties.
    // The other is referenced by virtue of being assigned to the 'x' variable.
    // Obviously, none can be garbage-collected.
    
    let y = x;
    // The 'y' variable is the second thing that has a reference to the object.
    
    x = 1;
    // Now, the object that was originally in 'x' has a unique reference
    // embodied by the 'y' variable.
    
    let z = y.a;
    // Reference to 'a' property of the object.
    // This object now has 2 references: one as a property,
    // the other as the 'z' variable.
    
    y = "mozilla";
    // The object that was originally in 'x' has now zero
    // references to it. It can be garbage-collected.
    // However its 'a' property is still referenced by
    // the 'z' variable, so it cannot be freed.
    
    z = null;
    // The 'a' property of the object originally in x
    // has zero references to it. It can be garbage collected.
    
    5 để quan sát sự sống động của các đối tượng hoặc nắm giữ một khóa tùy ý mà nếu không sẽ đủ điều kiện để thu gom rác. (Việc thu gom rác phải càng vô hình càng tốt. )

Trong các giải thích điển hình về

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 và
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
4 (chẳng hạn như giải thích ở trên), người ta thường ngụ ý rằng khóa được thu gom rác trước, đồng thời giải phóng giá trị cho việc thu gom rác. Tuy nhiên, hãy xem xét trường hợp giá trị tham chiếu đến khóa

const wm = new WeakMap();
const key = {};
wm.set(key, { key });
// Now `key` cannot be garbage collected,
// because the value holds a reference to the key,
// and the value is strongly held in the map!

Nếu

let x = {
  a: {
    b: 2,
  },
};
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'x' variable.
// Obviously, none can be garbage-collected.

let y = x;
// The 'y' variable is the second thing that has a reference to the object.

x = 1;
// Now, the object that was originally in 'x' has a unique reference
// embodied by the 'y' variable.

let z = y.a;
// Reference to 'a' property of the object.
// This object now has 2 references: one as a property,
// the other as the 'z' variable.

y = "mozilla";
// The object that was originally in 'x' has now zero
// references to it. It can be garbage-collected.
// However its 'a' property is still referenced by
// the 'z' variable, so it cannot be freed.

z = null;
// The 'a' property of the object originally in x
// has zero references to it. It can be garbage collected.
8 được lưu trữ dưới dạng tham chiếu thực tế, thì nó sẽ tạo tham chiếu tuần hoàn và làm cho cả khóa và giá trị không đủ điều kiện để thu gom rác, ngay cả khi không có tham chiếu nào khác đến
let x = {
  a: {
    b: 2,
  },
};
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'x' variable.
// Obviously, none can be garbage-collected.

let y = x;
// The 'y' variable is the second thing that has a reference to the object.

x = 1;
// Now, the object that was originally in 'x' has a unique reference
// embodied by the 'y' variable.

let z = y.a;
// Reference to 'a' property of the object.
// This object now has 2 references: one as a property,
// the other as the 'z' variable.

y = "mozilla";
// The object that was originally in 'x' has now zero
// references to it. It can be garbage-collected.
// However its 'a' property is still referenced by
// the 'z' variable, so it cannot be freed.

z = null;
// The 'a' property of the object originally in x
// has zero references to it. It can be garbage collected.
8 — bởi vì nếu
let x = {
  a: {
    b: 2,
  },
};
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'x' variable.
// Obviously, none can be garbage-collected.

let y = x;
// The 'y' variable is the second thing that has a reference to the object.

x = 1;
// Now, the object that was originally in 'x' has a unique reference
// embodied by the 'y' variable.

let z = y.a;
// Reference to 'a' property of the object.
// This object now has 2 references: one as a property,
// the other as the 'z' variable.

y = "mozilla";
// The object that was originally in 'x' has now zero
// references to it. It can be garbage-collected.
// However its 'a' property is still referenced by
// the 'z' variable, so it cannot be freed.

z = null;
// The 'a' property of the object originally in x
// has zero references to it. It can be garbage collected.
8 được thu gom rác, điều đó có nghĩa là tại một thời điểm cụ thể nào đó,
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
1 . Để khắc phục điều này, các mục nhập của
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 và
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
4 không phải là tham chiếu thực tế, mà là phù du, một cải tiến đối với cơ chế đánh dấu và quét. Barros và cộng sự. cung cấp một bản tóm tắt tốt về thuật toán (trang 4). Để trích dẫn một đoạn

Ephemerons là một sàng lọc của các cặp yếu trong đó cả khóa và giá trị đều không thể được phân loại là yếu hay mạnh. Khả năng kết nối của khóa xác định khả năng kết nối của giá trị, nhưng khả năng kết nối của giá trị không ảnh hưởng đến khả năng kết nối của khóa. […] khi bộ sưu tập rác cung cấp hỗ trợ cho phù du, nó xảy ra theo ba giai đoạn thay vì hai giai đoạn (đánh dấu và quét)

Là một mô hình tinh thần sơ bộ, hãy nghĩ về một

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 như cách thực hiện sau

Cảnh báo. Đây không phải là một polyfill cũng không phải là bất kỳ nơi nào gần với cách nó được triển khai trong công cụ (liên kết với cơ chế thu gom rác)

class MyWeakMap {
  #marker = Symbol("MyWeakMapData");
  get(key) {
    return key[this.#marker];
  }
  set(key, value) {
    key[this.#marker] = value;
  }
  has(key) {
    return this.#marker in key;
  }
  delete(key) {
    delete key[this.#marker];
  }
}

Như bạn có thể thấy,

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
5 không bao giờ thực sự nắm giữ một bộ chìa khóa. Nó chỉ đơn giản là thêm siêu dữ liệu vào từng đối tượng được truyền vào. Sau đó, đối tượng có thể được thu gom rác thông qua đánh dấu và quét. Do đó, không thể lặp lại các khóa trong
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3, cũng như xóa
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 (vì điều đó cũng phụ thuộc vào kiến ​​thức của toàn bộ bộ sưu tập khóa)

Để biết thêm thông tin về API của họ, hãy xem hướng dẫn về bộ sưu tập có khóa

Ghi chú.

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
8 và
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
9 cung cấp sự xem xét nội tâm trực tiếp vào bộ máy thu gom rác thải. bởi vì ngữ nghĩa thời gian chạy gần như hoàn toàn không được bảo đảm

Tất cả các biến có một đối tượng làm giá trị là các tham chiếu đến đối tượng đó. Tuy nhiên, các tham chiếu như vậy rất mạnh — sự tồn tại của chúng sẽ ngăn người thu gom rác đánh dấu đối tượng là đủ điều kiện để thu thập. Một

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
8 là một tham chiếu yếu đến một đối tượng cho phép đối tượng được thu gom rác, trong khi vẫn giữ được khả năng đọc nội dung của đối tượng trong suốt thời gian tồn tại của nó

Một trường hợp sử dụng cho

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
8 là một hệ thống bộ đệm ánh xạ các URL chuỗi tới các đối tượng lớn. Chúng tôi không thể sử dụng
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 cho mục đích này, bởi vì các đối tượng
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
3 có khóa yếu chứ không phải giá trị của chúng — nếu bạn truy cập một khóa, bạn sẽ luôn nhận được giá trị một cách chắc chắn (vì có quyền truy cập vào khóa nghĩa là nó vẫn còn hoạt động). Ở đây, chúng tôi có thể lấy
node --max-old-space-size=6000 index.js
4 cho một khóa (nếu giá trị tương ứng không còn tồn tại) vì chúng tôi chỉ có thể tính toán lại nó, nhưng chúng tôi không muốn các đối tượng không thể truy cập nằm trong bộ đệm. Trong trường hợp này, chúng ta có thể sử dụng một
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
5 bình thường, nhưng với mỗi giá trị là một
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
8 của đối tượng thay vì giá trị thực của đối tượng

function cached(getter) {
  // A Map from string URLs to WeakRefs of results
  const cache = new Map();
  return async (key) => {
    if (cache.has(key)) {
      return cache.get(key).deref();
    }
    const value = await getter(key);
    cache.set(key, new WeakRef(value));
    return value;
  };
}

const getImage = cached((url) => fetch(url).then((res) => res.blob()));

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
9 cung cấp một cơ chế thậm chí còn mạnh mẽ hơn để quan sát việc thu gom rác. Nó cho phép bạn đăng ký các đối tượng và được thông báo khi chúng được thu gom rác. Ví dụ: đối với hệ thống bộ đệm được minh họa ở trên, ngay cả khi bản thân các đốm màu được tự do thu thập, thì các đối tượng
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
8 chứa chúng sẽ không — và theo thời gian,
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
5 có thể tích lũy rất nhiều mục nhập vô ích. Sử dụng
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
9 cho phép một người thực hiện dọn dẹp trong trường hợp này

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
0

Do các lo ngại về hiệu suất và bảo mật, không có gì đảm bảo khi nào cuộc gọi lại sẽ được gọi hoặc liệu nó có được gọi hay không. Nó chỉ nên được sử dụng để dọn dẹp — và dọn dẹp không quan trọng. Có nhiều cách khác để quản lý tài nguyên xác định hơn, chẳng hạn như

node --expose-gc --inspect index.js
1, sẽ luôn thực thi khối
node --expose-gc --inspect index.js
2.
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
8 và
function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();
9 chỉ tồn tại để tối ưu hóa việc sử dụng bộ nhớ trong các chương trình chạy dài

Python có xóa bộ nhớ sau chức năng không?

Nếu bạn không giải phóng thủ công() bộ nhớ được cấp phát bởi malloc() , nó sẽ không bao giờ được giải phóng. Ngược lại, Python theo dõi các đối tượng và tự động giải phóng bộ nhớ của chúng khi chúng không còn được sử dụng .

MemoryError trong vòng lặp Python là gì?

Lỗi bộ nhớ có nghĩa là trình thông dịch đã hết bộ nhớ để phân bổ cho chương trình Python của bạn . Điều này có thể là do sự cố trong quá trình thiết lập môi trường Python hoặc có thể do bản thân mã tải quá nhiều dữ liệu cùng một lúc.

Bộ nhớ được giải phóng trong Python như thế nào?

Như đã giải thích trước đó, Python xóa các đối tượng không còn được tham chiếu trong chương trình để giải phóng dung lượng bộ nhớ . Quá trình này trong đó Python giải phóng các khối bộ nhớ không còn được sử dụng nữa được gọi là Bộ sưu tập rác.