Tìm kích thước của bộ nhớ được phân bổ cho ngăn xếp.
Các biến trong JavaScript [và hầu hết các ngôn ngữ lập trình khác] được lưu trữ ở hai nơi: Stack và Heap. Một ngăn xếp thường là một khu vực liên tục của bộ nhớ phân bổ bối cảnh cục bộ cho mỗi hàm thực thi. Heap là một khu vực lớn hơn nhiều lưu trữ mọi thứ được phân bổ động. Sự tách biệt này rất hữu ích để làm cho việc thực hiện an toàn hơn từ tham nhũng [ngăn xếp được bảo vệ nhiều hơn] và nhanh hơn [không cần thu thập rác động của khung ngăn xếp, phân bổ khung hình mới nhanh].
Một ví dụ về ngăn xếp điển hình
1 | function foo[] { var a = 1; } |
xếp chồng khi thực hiện được tạm dừng bên trong
function foo[] { var a = 1; }3
function bar[] { var b = 2; foo[]; }
bar[];
start of the stack
---------------------------
bar local frame
* a couple of OS pointers
* local variable b [2]
* place for returned value
* pointer to next frame
---------------------------
foo local frame
* a couple of OS pointers
* local variable a [1]
* place for returned value
Ngay cả khi một hàm tự gọi mình là đệ quy, mỗi khung có bản sao riêng của tất cả các biến cục bộ.
Khi một hàm kết thúc thực thi, khung của nó được xóa khỏi ngăn xếp, giải phóng bộ nhớ được phân bổ bởi tất cả các biến cục bộ. Đây là lý do tại sao ngay cả trong các ngôn ngữ như C hoặc C ++, bạn không bao giờ phải lo lắng về việc giải phóng các biến cục bộ.
Kích thước ngăn xếp
Chúng ta có thể thử tính toán kích thước của ngăn xếp. Nếu một hàm đệ quy phân bổ quá nhiều khung hình trên ngăn xếp, môi trường JavaScript ném một ngoại lệ
function foo[] { var a = 1; }4. Dưới nút 0.11.10 x64 Chương trình đệ quy sau đây có thể báo cáo số lần một hàm nhỏ thực hiện trước khi chết
function bar[] { var b = 2; foo[]; }
bar[];
1 | var counter = 0; |
Hãy tăng kích thước của mỗi khung bằng cách có một biến cục bộ
1 | var counter = 0; |
Một số trong JavaScript chiếm 8 byte, điều này cho phép chúng tôi tính toán kích thước ngăn xếp tối đa và kích thước của mỗi khung
N - size of single stack frame
20961 * N = 17967 * [N + 8]
[20961 - 17967] * N = 17967 * 8
2994 * N = 143736
N = 143736 / 2994 = 48 bytes = 6 numbers
Total stack size = 20961 * 48 = 1006128 < 1MB
Không có bất kỳ biến cục bộ nào, mỗi cuộc gọi hàm chiếm 48 byte trong quá trình thực thi và bạn bị giới hạn dưới 1MB cho tất cả các khung chức năng cục bộ.
Chúng tôi có thể xác nhận kích thước ngăn xếp bằng cách thêm biến cục bộ thứ hai
1 | var counter = 0; |
Một số trong JavaScript chiếm 8 byte, điều này cho phép chúng tôi tính toán kích thước ngăn xếp tối đa và kích thước của mỗi khung
function foo[] { var a = 1; }0
function bar[] { var b = 2; foo[]; }
bar[];
Không có bất kỳ biến cục bộ nào, mỗi cuộc gọi hàm chiếm 48 byte trong quá trình thực thi và bạn bị giới hạn dưới 1MB cho tất cả các khung chức năng cục bộ.
Chúng tôi có thể xác nhận kích thước ngăn xếp bằng cách thêm biến cục bộ thứ hai
var counter = 0;
try {
function foo[] {
var local = 1, local2 = true;
counter += 1;
foo[];
}
foo[];
} catch[e] {
console.error[e];
console.log['counter =', counter];
}
[RangeError: Maximum call stack size exceeded]
counter = 15721
Sử dụng tổng kích thước ngăn xếp trước đó và chia cho bộ đếm
Mỗi biến Boolean và số mất 8 byte bộ nhớ. | Biến Heap |
Chỉ các loại nguyên thủy được truyền theo giá trị [số, boolean, tham chiếu đến objec] được lưu trữ trên ngăn xếp. Mọi thứ khác được phân bổ động từ nhóm bộ nhớ được chia sẻ được gọi là Heap. Trong JavaScript, bạn không phải lo lắng về việc giải quyết các vật thể bên trong đống, người thu gom rác giải phóng chúng bất cứ khi nào không ai tham khảo chúng. Tất nhiên, việc tạo ra một số lượng lớn các đối tượng mất phí hiệu suất của nó [ai đó cần giữ tất cả các sổ sách kế toán] cộng với phân mảnh bộ nhớ.