Máy thu gom rác hoạt động như thế nào?

Bộ thu gom rác (GC) là một trình quản lý bộ nhớ. Nhiều ngôn ngữ lập trình có GC tích hợp sẵn. Tính năng này tự động phân bổ và phân bổ bộ nhớ trong một chương trình. Nó giải phóng bộ nhớ bị ràng buộc, không sử dụng làm chậm ứng dụng của bạn.
Cái hay của GC là nó giải phóng bộ nhớ thay cho bạn mà bạn không cần phải làm gì cả. Do đó, bạn có thể coi đây là một tính năng thiết yếu mà bạn mong đợi mọi ngôn ngữ lập trình đều có. Đáng buồn thay, đây không phải là trường hợp; ngay cả một ngôn ngữ phổ biến như C cũng có thể thiếu GC.
Mục Lục
Phân bổ bộ nhớ hoạt động như thế nào?
Khi bạn chạy một chương trình bằng bất kỳ ngôn ngữ lập trình nào, hệ điều hành của bạn sẽ dự trữ một ngăn xếp dữ liệu trong bộ nhớ cho chương trình đó. Chương trình này sở hữu và chiếm giữ ngăn xếp dữ liệu này cho đến khi nó hoàn thành việc thực thi. Nếu chương trình của bạn cần nhiều bộ nhớ hơn những gì hiện có, nó có thể tự động phân bổ nhiều bộ nhớ hơn từ đống bộ nhớ của hệ điều hành.
Trong lập trình, một biến đại diện cho một vị trí bộ nhớ. Vì vậy, khi bạn khai báo một biến mới, ngôn ngữ lập trình sẽ phân bổ không gian trong bộ nhớ cho biến này. Biến bây giờ sẽ có một địa chỉ bộ nhớ. Cho đến khi bạn gán một giá trị cho biến này, nó sẽ vẫn chưa được khởi tạo và nó có thể chứa một số giá trị rác.
Nếu một ngôn ngữ lập trình cho phép bạn khai báo một biến mà không cần khởi tạo nó, thì đó là một biến động. Điều này có nghĩa là giá trị bạn gán cho biến có thể thay đổi theo thời gian. Tuy nhiên, vị trí bộ nhớ của biến sẽ được giữ nguyên cho đến khi bạn định vị nó.
Phân bổ bộ nhớ hoạt động như thế nào?
Cấp phát bộ nhớ là một quá trình tương tự đối với tất cả các ngôn ngữ lập trình. Nhưng phương pháp phân bổ bộ nhớ tương ứng có xu hướng khác nhau. Có hai loại phương pháp phân bổ bộ nhớ; thủ công và tự động. GC thực hiện phân bổ giao dịch tự động.
Phân bổ bộ nhớ mà không có bộ thu gom rác
Ngôn ngữ lập trình C không sử dụng GC để phân bổ bộ nhớ. Do đó, lập trình viên C phải cấp phát và phân bổ bộ nhớ theo cách thủ công. C cho phép cấp phát bộ nhớ động khi bạn không biết, tại thời điểm biên dịch, bạn sẽ sử dụng bao nhiêu bộ nhớ tại thời điểm chạy.
Thư viện chuẩn (stdlib.h) chứa các chức năng mà C sử dụng để quản lý cấp phát bộ nhớ động. Các chức năng này bao gồm:
- malloc (): cấp phát một kích thước cụ thể của bộ nhớ và trả về một con trỏ đến bộ nhớ đó. Nếu không có đủ bộ nhớ trong nhóm bộ nhớ của hệ điều hành, nó sẽ trả về null.
- free (): phân bổ một khối bộ nhớ cụ thể và trả nó về nhóm bộ nhớ của hệ điều hành.
Ví dụ về chương trình C
#include <stdio.h>
#include <stdlib.h>int main()
{
int *ptr;
int j;
ptr = (int *) malloc(200 * sizeof(int));
for (j = 0; j < 200; j++)
{
ptr[j] = j;
printf("%dt",ptr[j]);
}
free(ptr);
return 0;
}
Đoạn mã trên phân bổ bộ nhớ để lưu trữ 200 giá trị số nguyên bằng cách sử dụng malloc () hàm số. Nó sử dụng một con trỏ để truy cập vị trí bộ nhớ này và lưu trữ 200 giá trị số nguyên trong đó. Con trỏ cũng in dữ liệu được lưu trữ tại vị trí bộ nhớ vào bảng điều khiển. Cuối cùng, chương trình sẽ phân bổ bộ nhớ được cấp phát trước đó bằng cách sử dụng tự do() hàm số.
Phân bổ bộ nhớ với bộ thu gom rác
Một số ngôn ngữ lập trình phổ biến sử dụng GC để quản lý bộ nhớ. Điều này làm cho cuộc sống của các lập trình viên sử dụng các ngôn ngữ này dễ dàng hơn nhiều. C # và Java là hai ngôn ngữ lập trình sử dụng GC.
C # GC
Trong ngôn ngữ lập trình C #, GC quản lý việc cấp phát và phân bổ địa chỉ bộ nhớ. Do đó, một lập trình viên C # không cần phải lo lắng về việc phân bổ một đối tượng sau khi nó hoàn thành mục đích của nó.
C # GC khởi tạo một nhóm bộ nhớ, được gọi là heap được quản lý, cho mọi quy trình (hoặc chương trình) mới. Nó gọi là VirtualAlloc () chức năng cấp phát bộ nhớ và VirtualFree () chức năng để phân bổ nó. Phần tốt nhất là tất cả điều này xảy ra ở chế độ nền mà không cần bạn, lập trình viên.
C # GC có một công cụ tối ưu hóa, công cụ này sử dụng để quyết định khi nào cần phân bổ bộ nhớ. Công cụ tối ưu hóa kiểm tra gốc ứng dụng để xác định đối tượng nào không còn được sử dụng. Nó thực hiện điều này bằng cách tạo một biểu đồ kéo dài từ gốc của ứng dụng đến các đối tượng được kết nối. Gốc này bao gồm các trường tĩnh, biến cục bộ, v.v. Bất kỳ đối tượng nào không được kết nối với gốc ứng dụng đều là rác.
Công cụ tối ưu hóa GC không chỉ thu thập bộ nhớ của riêng nó. Đầu tiên phải có một yêu cầu cấp phát bộ nhớ mới. Nếu hệ thống có ít bộ nhớ khả dụng, thì công cụ tối ưu hóa GC sẽ phát huy tác dụng.
Java GC
Trong Java, GC cũng quản lý việc cấp phát và phân bổ các địa chỉ bộ nhớ. Tuy nhiên, Java hiện có bốn loại trình thu gom rác được hỗ trợ khác nhau:
- Rác-Đầu tiên (G1)
- Nối tiếp
- Song song
- Bộ thu gom rác Z (ZGC)
Bộ thu gom rác G1 là GC mặc định của Java kể từ khi phát hành Bộ phát triển Java (JDK) 9. Java tổ chức dữ liệu trong các đối tượng và lưu trữ các đối tượng này trong một đống có kích thước cố định. Bộ thu gom rác G1 chia đống thành các vùng có kích thước bằng nhau. Sau đó, nó chia các vùng đống này thành hai phần; thế hệ trẻ và già.
Mỗi khi bạn tạo một đối tượng mới, việc phân bổ không gian cho đối tượng này sẽ xảy ra trong thế hệ trẻ. Sử dụng quy trình lão hóa, bộ thu gom rác G1 sao chép các đối tượng trong vùng trẻ sang vùng cũ. Nó cũng sao chép các đối tượng đã có trong vùng cũ sang vùng cũ hơn.
Sau đó, bộ thu gom rác G1 thực hiện hầu hết việc phân bổ bộ nhớ của nó trong thế hệ trẻ, đôi khi mạo hiểm với phần thế hệ cũ.
Lợi ích của việc có một người thu gom rác là gì?
Lợi ích của việc có một bộ thu gom rác là nó ngăn bạn nghĩ đến việc quản lý bộ nhớ trong khi viết mã của mình. Điều này giúp bạn có thời gian để tập trung vào các khía cạnh quan trọng khác của ứng dụng của mình. Tuy nhiên, một số lợi ích khác đáng được làm nổi bật.
Việc lấy lại các đối tượng không sử dụng và giải phóng bộ nhớ cung cấp khả năng thực thi ứng dụng sạch hơn. Nếu chương trình của bạn giải phóng bộ nhớ càng sớm càng tốt, nó sẽ có dung lượng bộ nhớ nhỏ hơn và có thể chạy hiệu quả hơn.
Việc thu gom rác làm giảm các lỗi liên quan đến quản lý bộ nhớ như rò rỉ và lỗi con trỏ. Điều này là do quá trình không còn phụ thuộc vào lập trình viên và khả năng viết mã chính xác của họ.