1. Trang chủ
  2. » Luận Văn - Báo Cáo

tiểu luận môn Nguyên lý các ngôn ngữ lập trình. Đề tài tìm hiểu Các kỹ thuật dọn rác nhớ

16 951 8

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 16
Dung lượng 1,79 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Đây là một tiến trình đặc biệt có nhiệm vụ duyệt qua các vùng nhớ đã được cấp phát và kiểm tra xem vùng nhớ nào không còn được sử dụng nữa không còn tham chiếu tới nó nữa thì sẽ thực hiệ

Trang 1

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG



BÀI TẬP LỚN

Môn: NGUYÊN LÝ CÁC NGÔN NGỮ LẬP TRÌNH

Giáo viên hướng dẫn: TS Nguyễn Hữu Đức

Học viên thực hiện: Nguyễn Văn Chiến CB121349

Trang 2

MỤC LỤC

1 Tổng Quan Về Dọn Rác Nhớ (Garbage Collection) 2

1.1 Khái niệm Garbage Collection 2

1.2 Chức năng Garbage Collection 2

1.3 Ưu điểm của Garbage Collection 2

1.4 Nhược điểm của Garbage Collection 3

2 Các Kỹ Thuật Dọn Rác Nhớ (Garbage Collection Techniques) 4

2.1 Reference Counting collection 4

2.2 Mark-Sweep collection 5

2.3 Mark-Compact collection 7

2.4 Copying collection 11

2.5 Non-Copy Implicit collection 13

3 Kết Luận 14

4 Tài Liệu Tham Khảo 15

Trang 3

1 Tổng Quan Về Dọn Rác Nhớ (Garbage Collection)

Trong NET (cũng như Java) có một khái niệm là Bộ dọn rác (Garbage Collector) Đây là một tiến trình đặc biệt có nhiệm vụ duyệt qua các vùng nhớ

đã được cấp phát và kiểm tra xem vùng nhớ nào không còn được sử dụng nữa (không còn tham chiếu tới nó nữa) thì sẽ thực hiện thu hồi một cách tự động để

có thể cấp phát cho các yêu cầu tiếp theo

Việc xây dựng một game hay ứng dụng mà không quan tâm đến loại bỏ các đối tượng không còn cần thiết sẽ gây ra một số vấn đề rất lớn, chương trình

sẽ ngốn tài nguyên của hệ thống (Ram, CPU), dẫn đến việc chương trình sẽ chạy chậm chạp, nặng nề, gây treo hoặc thậm chí là bắt người dùng phải khởi động lại máy tính

1.1 Khái niệm Garbage Collection

Garbage Collection (GC) là một quá trình chạy ngầm để giải phóng vùng nhớ được cấp phát cho các đối tượng mà ứng dụng không còn sử dụng các đối tượng này nữa

1.2 Chức năng Garbage Collection

- Tự động khôi phục bộ nhớ;

- Chức năng của GC là tìm những đối tượng dữ liệu không còn sử dụng nữa và giải phóng chúng bởi chương trình đang chạy

Dưới đây là ví dụ về hoạt động của Garbage Collection

1 var a:Object = {foo:"bar"} // tạo object foo có giá trị là bar, sau đó đặt

1 tham chiếu a:

2 var b:Object = a; // sao chép tham chiếu sang b

3 delete(a); // xóa tham chiếu a

4 trace(b.foo); // khi thực hiện trace, kết quả là "bar" -> kết luận là object foo vẫn tồn tại

Như vậy vẫn còn 1 tham chiếu đến object foo, và để GC được thực hiện,

ta phải đảm bảo không còn tham chiếu nào đến foo nữa

5 delete(b);

Sau khi thực hiện dòng lệnh 5, foo sẽ không còn tham chiếu nào nên lúc này GC sẽ giải phóng foo

Trang 4

1.3 Ưu điểm của Garbage Collection

- Giúp lập trình viên không phải xử lý giải phóng bộ nhớ khi lập trình (vốn gây ra lỗi trên các ngôn ngữ không sử dụng Garbage Collector), giảm thiểu Memory leaks

- Bảo đảm tính toàn vẹn của chương trình, GC cũng là một phần quan trọng trong khả năng bảo mật và tính an toàn

1.4 Nhược điểm của Garbage Collection :

- Ảnh hưởng tới hiệu năng chương trình do JVM phải theo dõi các đối tượng khi đang được tham chiếu trong quá trình thực thi mã, sau đó phải finalize và giải phóng các đối tượng

Trang 5

2 Các Kỹ Thuật Dọn Rác Nhớ (Garbage Collection Techniques)

2.1 Reference Counting Collection

Reference Counting là cách đơn giản nhất để theo dõi xem đối tượng còn tham chiếu nào đang hoạt động hay không

Mỗi đối tượng kết hợp với 1 biến đếm số tham chiếu đến nó Mỗi khi có

1 tham chiếu đến đối tượng được tạo, biến đếm tham chiếu sẽ tăng lên 1, nếu tổng số tham chiếu = 0 thì Garbage Collector hoạt động và đối tượng sẽ bị xóa

Hiệu quả của RC.

Khi một con trỏ được tạo, biến đếm tham chiếu của đối tượng mà nó trỏ đến phải được điều chỉnh Nếu giá trị của biến con trỏ được chuyển từ con trỏ này đến con trỏ khác(phép gán), thì hai biến RC của cả hai con trỏ phải được cập nhật, một biến RC của 1 đối tượng sẽ tăng còn biến kia sẽ giảm Sau đó phải kiểm tra RC=0 hay không Những biến ngăn xếp mà có thời gian sống ngắn

sẽ phải chịu chi phí lớn cho mô hình RC Trong trường hợp này biến đếm tham chiếu được tăng lên và giảm trở lại nhanh chóng

Phần lớn chi phí có thể tối ưu bằng cách sử dụng biến cục bộ Tham chiếu từ biến cục bộ không cần giữ lại Chúng ta chỉ cần điều chỉnh RC trong heap Tuy nhiên chúng ta không thể bỏ qua hoàn toàn các con trỏ trong stack

Vì vậy stack được quét trước khi đối tượng được giải phóng và chỉ khi RC của con trỏ=0 thì nó được giải phóng Hạn chế cập nhật RC của đối với con trỏ trong stack sẽ giảm đáng kể chi phí của RC

Recap RC thì không phù hợp với những ứng dụng cần performance cao Khá phổ biến trong những ứng dụng không sử dụng cấu trúc vòng Hầu hết file

hệ thống sử dụng RC to quản lý file hoặc disk blocks

Kỹ thuật Reference Counting là cách phổ biến nhất nhưng nó vẫn có một

số nhược điểm, và có một số trường hợp dù ta đã xóa đối tượng nhưng số tham chiếu đến đối tượng đó vẫn lớn hơn 1 và Garbage Collector sẽ không bao giờ hoạt động

Ví dụ dưới đây 2 đối tượng sẽ tham chiếu chéo lẫn nhau và chúng sẽ không bao giờ bị xóa thật sự

Trang 6

var a:Object = {}

var b:Object = {foo:a};

a.foo = b;

delete(a);

delete(b);

Reference Counting Collection là một phương pháp đơn giản và không chiếm tài nguyên CPU, tuy nhiên phương pháp này không thể áp dụng cho các tham chiếu vòng (Circular Reference) như ví dụ dưới đây

1 var a:Object = {}

2 var b:Object = {foo:a}; // tạo một tham chiếu b thứ hai - trỏ đến tham chiếu thứ nhất a

3 a.foo = b; // cho tham chiếu a trỏ vào b

4.

5 delete(a); // xóa tham chiếu a

6 delete(b); // xóa tham chiếu b

Trong trường hợp trên, dù cả a và b đều đã bị xóa và chẳng còn cách nào truy cập được 2 objects trên, nhưng số lượng tham chiếu vẫn là 1 vì chúng tham chiếu qua lại lẫn nhau Trường hợp này sẽ phức tạp hơn nếu ta có 1 danh sách vòng ( ví dụ: a->b, b->c, c->a …)

RC thất bại khi giải phóng cấu trúc vòng nguyên nhân từ việc xác định rác Cấu trúc vòng không hiếm trong các chương trình ngày nay: Cây; Cấu trúc

dữ liệu vòng

2.2 Mark-Sweep collection

Kỹ thuật Mark-Sweep giải quyết vấn đề cấu trúc vòng của RC

Phân biệt đối tượng sống từ rác ( Mark phase )

- Thực hiện bằng đánh dấu: Nó bắt đầu tại nút gốc root set và duyệt qua

đồ thị các con trỏ có thể đến được

- Đánh dấu những đối tượng đi qua

Trang 7

Thu hồi vùng nhớ rác ( Sweep phase).

Sau Mark phase, bộ nhớ sẽ được kiểm tra kỹ lưỡng để tìm ra những đối tượng không được đánh dấu (rác) và thu hồi chúng

Dùng 1 bit làm mark-bit

1 : đánh dấu; 0 : không đánh dấu

Ví dụ:

Hình 1.

Trang 8

Hình 2.

Thuật toán cơ bản:

New(A)=

If free_list is empty

mark_sweep()

if free_list is empty

(“out-of-memory”)

pointer = allocate(A)

return (pointer)

Mark(Obj)=

If mark_bit(Obj) == unmarked for C in Children(Obj)

mark(C)

mark_sweep()=

for Ptr in Roots mark(Ptr) sweep()

sweep()=

p = Heap_bottom while (p<Heap_top) if(mark_bit(p) == unmarked) then free(p)

else mark_bit(p) = unmarked: p=p+size(p)

Tính chất của Mark - Sweet:

- Về việc phân mảnh: Khó cấp phát những đối tượng lớn Vài đối tượng nhỏ có thể lấy nhiều khoảng trống kế tiếp

- Về chi phí: Tỉ lệ với kích thước heap, gồm cả đối tượng sống và rác

- Về Locality of reference: Không di chuyển đối tượng Đối tượng được đặt lẫn lộn là nguyên nhân nhiều page swaps (thông thường thì những đối tượng trong cluster thường được active cùng lúc)

2.3 Mark-Compact collection

Trang 9

Kỹ thuật Mark-Compact giải quyết vấn đề phân mảnh và cấp phát của

Mark-Sweep

Bộ dọn rác sẽ duyệt qua đồ thị con trỏ và thực hiện sao chép từng đối tượng sống sau bước này

Kết quả là một vùng trống liên tục tiếp theo Đối tượng sống ở một phía

và rác ở cũng như vùng trống ở một phía

Những đối tượng rác được nén về cuối bộ nhớ

Tiến trình sẽ trải qua một số bước trên bộ nhớ:

- Một để tính vị trí mới của đối tượng (địa chỉ)

- Cập nhật con các con trỏ và di chuyển các đối tượng

- Thuật toán này chậm hơn đáng kể so với Mark-Sweep

2 thuật toán ví dụ về Mark-Compact:

- Two-finger Alg– cho những đối tượng có cùng kích thước

- Lisp 2 Alg

Thứ tự của đối tượng

Hình 3.

Arbitrary – thứ tự không được bảo vệ (tùy ý)

Linearizing – đối tượng trỏ đến đối tượng khác được di chuyển về vị trí

kề (tuyến tính)

Trang 10

Sliding –các đối tượng được trượt về cuối heap giữ nguyên thứ tự cấp phát

Thuật toán Two Finger [Edwards 1974]

Thuật toán đơn giản:

- Thiết kế cho những đối tượng cùng kích thước

- Thứ tự của đối tượng sau thuật toán là tùy ý(arbitrary)

- 2 phần chính: nén và cập nhật các con trỏ

Phần I: Nén (Compact)

Sử dụng 2 con trỏ: con trỏ thứ nhất là free: Duyệt từ cuối heap để tìm những đối tượng rỗng (free/empty objects) Con trỏ thứ 2 là live: Duyệt từ đầu heap tìm những đối tượng sống (live objects) Khi con trỏ free tìm được một free spot và con trỏ live tìm được một đối tượng sống, đối tượng được di chuyển đến free spot Khi một đối tượng được di chuyển, con trỏ sẽ trỏ đến ô nhớ ở bên trái ô nhớ cũ

Dưới đây là ví dụ về two finger

Hình 4.

Phần II: Fix Pointers

Trang 11

Duyệt qua các đối tượng sống trong heap.

- Duyệt thông qua các con trỏ

- Nếu con trỏ trỏ đến vùng khu vực rỗng, fix nó ứng với con trỏ chuyển tiếp đến đối tượng đích Compacted area free area

Hình 5.

Tính chất của Two finger:

- Đơn giản

- Tương đối nhanh: chỉ 2 lần duyệt

- Không đòi hỏi thêm khoảng trống

- Đối tượng phải có kích thước bằng nhau

- Thứ tự đối tượng output là tùy ý

- Điều này làm giảm hiệu quả chương trình! Do đó không được sử dụng ngày nay

Thuật toán Lisp2

- Cải tiến: Sử dụng cho những biến khác kích thước, giữ đúng thứ tự

- Đòi hỏi thêm pointer field cho mỗi đối tượng

Hình 6.

Thuật toán Lisp2

- Pass1: Tính toán địa chỉ Giữa địa chỉ mới trong object field mới được thêm vào

Trang 12

- Pass2: Cập nhật con trỏ.

- Pass3: 2 con trỏ (free và live) chạy từ cuối Live objects được di chuyển đến free space giữ đúng thứ tự gốc

Hình 7.

Lisp 2 – Tính chất :

- Tương đối đơng giản

- Không phụ thuộc kích thước đối tượng

- Thứ tự các đối tượng được bảo vệ

- Chậm: 3 passes Cần thêm khoảng trống – một con trỏ trên một đối tượng

2.4 Copying collection

Kỹ thuật này giống kỹ thuật Mark-Compact, thuật toán di chuyển tất cả live objects vào một khu vực, phần còn lại của heap được giải phóng

Có một vài schemes cho copying GC, “Stop and-Copy” GC là một ví dụ

Stop-and-Copy Collector

Bộ nhớ heap được chia làm 2 phần

- Khi chương trình đang chạy yêu cầu cấp phát mà không còn đủ vùng nhớ chưa sử dụng

- Chương trình sẽ dừng và copying GC được gọi để thu hồi khoảng trống

Trang 13

Hình 8.

Cheney breath-first copying

Hình 9.

Thuật toán:

Init()=

Tospace=Heap_bottom

space_size=Heap_size/2

top_of_space=Tospace+space_size

fromspace=top_of_space+1

free=Tospace

New(n)=

if free+n>top_of_space Collect()

if free+n>top_of_space abort”Memoryexhausted” new-object=free

free=free+n return(new-object)

Collect()=

from-space,to-space=

to-space,from-space//swap

scan=free=Tospace

Copy(P)=

ifforwarded(P) returnforwarding_address(P) else

Trang 14

forRinRoots

R=copy(R)

whilescan<free

forPinchildren(scan)

*p=copy(P)

scan=scan+size(scan)

addr=free mem-copy(P,free) free=free+size(P) forwarding_address(P)=addr return(addr)

Efficiency of Copying Collection

-Thứ tự đối tượng là tùy ý

- Công việc hoàn thành phụ thuộc số lượng đối tượng sống

- Để giảm tần suất của GC, cần cấp phát semispaces lớn

- Không thực tế nếu không đủ RAM và paging xuất hiện

2.5 Non-Copy Implicit collection

Kỹ thuật này cần thêm 2 trường con trỏ và một trường màu cho mỗi đối tượng Những trường này phục vụ cho việc liên kết giữa các vùng nhớ trong một danh sách liên kết đôi Trường màu xác định đối tượng thuộc về tập live objects hay tập rác

Duyệt tất cả các đối tượng trong vùng nhớ heap Các đối tượng live object sẽ linking đến tập toset, và màu chuyển sang màu khác Sau khi di chuyển các live object từ fromset sang thì các object còn lại trong fromset là garbage và có thể sử dụng như một free list Sau đó tập hợp fromset sẽ hoán đổi thành toset (giống như fromspace và tospace trong copying collector)

Trong hầu hết trường hợp thì chi phí nhỏ hơn copying collector nhưng trong vài trường hợp thì chi phí phân mảnh có thể quá nặng

Trang 15

3 Kết Luận

Qua phần trình bày trên ta thấy, có 5 kỹ thuật dọn rác nhớ và mỗi kỹ thuật đều có những ưu nhược điểm khác nhau

Nhờ các kỹ thuật dọn rác nhớ mà các lập trình viên không phải xử lý giải phóng bộ nhớ khi lập trình (vốn gây ra lỗi trên các ngôn ngữ không sử dụng Garbage Collector), giảm thiểu Memory leaks Bảo đảm tính toàn vẹn của chương trình, GC cũng là một phần quan trọng trong khả năng bảo mật và tính

an toàn

Bên cạnh ưu điểm kể trên thì, garbage collection sẽ dẫn đến một số hạn chế như ảnh hưởng tới hiệu năng chương trình do JVM phải theo dõi các đối tượng khi đang được tham chiếu trong quá trình thực thi mã, sau đó phải finalize và giải phóng các đối tượng không còn tham chiếu trực tiếp

Trang 16

4 Tài liệu tham khảo.

[1] http://www.slideshare.net/khuonganpt/basic-garbage-collection-techniques-vi

[2] http://www.ibm.com/developerworks/vn/library/j-nativememory-linux/ index.html

[3] http://chienuit.wordpress.com/2010/10/04/qu%E1%BA%A3n-l-b%E1%BB

%99-nh%E1%BB%9B-trong-net-garbage-collection/

[4] http://cgi.di.uoa.gr/~smaragd/521-10/gc.pdf

Ngày đăng: 17/04/2016, 21:22

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w