Việc sử dụng bảng băm trong bộ sưu tập rác sẽ giải quyết vấn đề thế giới về đánh dấu và quét?


13

Trong thuật toán thu gom rác nhỏ gọn, bạn phải dừng lại khi di chuyển các đối tượng vì biểu đồ tham chiếu trở nên không nhất quán và bạn phải thay thế các giá trị của tất cả các tham chiếu trỏ đến đối tượng.

Nhưng điều gì sẽ xảy ra nếu bạn có một bảng băm với ID đối tượng là khóa và con trỏ làm giá trị và các tham chiếu sẽ trỏ đến ID đã nói thay vì địa chỉ đối tượng ... thì việc sửa tham chiếu sẽ chỉ yêu cầu thay đổi một giá trị và chỉ cần tạm dừng nếu đối tượng được cố gắng ghi vào trong khi sao chép ...

Có một sai lầm trong dòng suy nghĩ của tôi?

Câu trả lời:


19

Cập nhật tài liệu tham khảo không phải là điều duy nhất yêu cầu tạm dừng. Các thuật toán tiêu chuẩn thường được nhóm theo "quét đánh dấu" đều cho rằng toàn bộ biểu đồ đối tượng vẫn không thay đổi trong khi nó được đánh dấu. Xử lý chính xác các sửa đổi (các đối tượng mới được tạo, các tham chiếu đã thay đổi) đòi hỏi các thuật toán thay thế khá phức tạp, giống như thuật toán ba màu. Thuật ngữ ô là "thu gom rác đồng thời".

Nhưng có, cập nhật tài liệu tham khảo sau khi nén cũng cần tạm dừng. Và có, sử dụng chỉ định (ví dụ: thông qua ID đối tượng liên tục và bảng băm để con trỏ thực) có thể làm giảm đáng kể việc tạm dừng. Thậm chí có thể làm cho phần này không bị khóa nếu muốn. Sẽ vẫn khó khăn để có được quyền như bất kỳ đồng thời bộ nhớ chia sẻ cấp thấp nào, nhưng không có lý do cơ bản nào nó sẽ không hoạt động.

Tuy nhiên , nó sẽ có nhược điểm nghiêm trọng. Bên cạnh việc thêm không gian ( ít nhất hai từ bổ sung cho tất cả các đối tượng), nó làm cho mỗi dereference nhiều tốn kém hơn. Ngay cả một cái gì đó đơn giản như nhận được một thuộc tính bây giờ liên quan đến tìm kiếm bảng băm đầy đủ. Tôi ước tính hiệu suất đạt được còn tệ hơn so với theo dõi gia tăng.


Chà, hôm nay chúng ta có rất nhiều bộ nhớ nên chúng ta có thể nói rằng bảng 50 Mb và hàm băm có thể là modulo đơn giản nên chỉ có một hướng dẫn ...
mrpyo

3
@mrpyo lấy kích thước của bảng băm, thao tác modulo, tính quy định từ bảng băm bù để có được con trỏ đối tượng thực tế, tính chính xác cho chính đối tượng. Cộng với có thể một số đăng ký xáo trộn. Chúng tôi kết thúc với hơn 4 hướng dẫn. Ngoài ra, lược đồ này có vấn đề liên quan đến địa phương bộ nhớ: Bây giờ, cả bảng băm và dữ liệu phải phù hợp với bộ đệm.
amon

@mrpyo Bạn cần một mục (ID đối tượng -> địa chỉ hiện tại) cho mỗi đối tượng, phải không? Và bất kể hàm băm rẻ như thế nào, bạn sẽ có va chạm và cần giải quyết chúng. Cũng những gì amon nói.

@amon chỉ là vấn đề thời gian trước khi CPU có bộ nhớ cache từ 50 MB trở lên :)
Móż

1
@ Vào thời điểm đó, chúng ta có thể đặt 50 MiB bóng bán dẫn trên chip và vẫn có độ trễ đủ thấp để nó hoạt động như bộ đệm L1 hoặc L2 (bộ nhớ cache L3 có kích thước lên tới 15 MiB, nhưng thường là AFAIK ngoài chip độ trễ kém hơn L1 và L2), theo đó chúng ta sẽ có số lượng lớn bộ nhớ chính (và dữ liệu để đưa vào đó). Bảng không thể có kích thước cố định, nó phải phát triển theo đống.

19

Tất cả các vấn đề trong khoa học máy tính có thể được giải quyết bằng một cấp độ khác của cảm ứng ngoại trừ vấn đề có quá nhiều lớp không xác định

Cách tiếp cận của bạn không giải quyết ngay vấn đề thu gom rác mà chỉ đưa nó lên một cấp. Và với giá nào! Bây giờ, mọi truy cập bộ nhớ đều đi qua một sự bổ sung con trỏ khác. Chúng tôi không thể lưu trữ vị trí kết quả, vì có thể nó đã được di chuyển trong khi đó, chúng tôi phải luôn đi qua ID đối tượng. Trong hầu hết các hệ thống, sự gián tiếp này không được chấp nhận và việc dừng thế giới được cho là có tổng chi phí thời gian chạy thấp hơn.

Tôi nói đề xuất của bạn chỉ di chuyển vấn đề, không giải quyết nó. Vấn đề xoay quanh việc tái sử dụng ID đối tượng. ID đối tượng hiện tương đương với con trỏ của chúng tôi và chỉ có một lượng địa chỉ hữu hạn. Có thể hiểu được (đặc biệt trên hệ thống 32 bit) rằng trong suốt thời gian tồn tại của chương trình của bạn, nhiều hơn các đối tượng INT_MAX sẽ được tạo, ví dụ như trong một vòng lặp như

while (true) {
    Object garbage = new Object();
}

Nếu chúng ta chỉ tăng ID đối tượng cho từng đối tượng, chúng ta sẽ hết ID tại một số điểm. Do đó, chúng tôi phải tìm ra ID nào vẫn đang được sử dụng và miễn phí để có thể lấy lại được. Nghe có vẻ quen? Bây giờ chúng tôi đã trở lại tại một hình vuông.


Người ta có thể sử dụng ID chỉ là 'đủ lớn' để nói bignums 256 bit? Tôi không nói rằng ý tưởng này là tốt về tổng thể, nhưng bạn gần như chắc chắn có thể sử dụng IDS.
Vality

@Vality thực tế là có - theo như chúng ta có thể thấy điều đó sẽ xoay quanh vấn đề tái sử dụng ID. Nhưng đây chỉ là một 640 640 khác nên đủ cho bất kỳ ai tranh luận và không thực sự giải quyết được vấn đề. Một khía cạnh thảm khốc hơn là kích thước của tất cả các đối tượng (và bảng băm) sẽ phải tăng lên để phù hợp với các con trỏ giả quá khổ này và trong quá trình truy cập băm, chúng ta cần so sánh bigint này với các ID khác có thể sẽ hog nhiều thanh ghi và thực hiện nhiều hướng dẫn để hoàn thành (trên 64 bit: tải 8 ×, so sánh 4 ×, 3 × và tăng 5 × so với số nguyên gốc).
amon

Vâng, bạn sẽ hết ID sau một thời gian và sẽ cần phải thay đổi tất cả chúng cần phải tạm dừng. Nhưng có lẽ nó sẽ là một sự kiện hiếm hoi ...
mrpyo

@amon Rất nhiều người đồng ý, tất cả những điểm rất tốt ở đó, tốt hơn hết là có một hệ thống bền vững thực sự tôi đồng ý. Điều này sẽ chậm một cách khó chịu bất cứ điều gì bạn làm như vậy dù sao chỉ là thú vị trong lý thuyết. Cá nhân tôi dù sao tôi cũng không phải là người hâm mộ thu gom rác lớn: P
Vality

@amon: có nhiều mã trên thế giới hơn là điều này sẽ sai khi bạn bọc ID 64 bit (584 năm nano giây và có thể bạn có thể sắp xếp phân bổ bộ nhớ để mất 1ns, đặc biệt nếu bạn không truy cập bộ đếm toàn cầu mà phun ra ID!). Nhưng chắc chắn, nếu bạn không cần phải dựa vào điều đó thì bạn không cần.
Steve Jessop

12

Không có lỗi trong dòng suy nghĩ của bạn, bạn vừa mô tả một cái gì đó rất gần với cách trình thu gom rác Java ban đầu hoạt động

Máy ảo Java ban đầu [6] và một số máy ảo Smalltalk sử dụng các con trỏ gián tiếp, được gọi là các thẻ điều khiển trong [6], để chỉ các đối tượng. Tay cầm cho phép dễ dàng di chuyển các đối tượng trong quá trình thu gom rác, vì với các tay cầm, có một con trỏ trực tiếp đến từng đối tượng: một đối tượng trong tay cầm của nó. Tất cả các tham chiếu khác đến đối tượng gián tiếp thông qua han-dle. Trong các hệ thống bộ nhớ dựa trên tay cầm như vậy, trong khi các địa chỉ đối tượng thay đổi theo thời gian tồn tại của các đối tượng và do đó không thể được sử dụng để băm, địa chỉ xử lý không đổi.

Băm không gian và thời gian hiệu quả của các đối tượng thu gom rác

Trong triển khai hiện tại của Máy ảo Java, một tham chiếu đến một cá thể lớp là một con trỏ tới một tay cầm mà chính nó là một cặp con trỏ: một đến một bảng chứa các phương thức của đối tượng và một con trỏ tới đối tượng Class đại diện cho loại đối tượng và loại khác cho bộ nhớ được phân bổ từ vùng heap Java cho dữ liệu đối tượng.

Đặc tả máy ảo Java (1997)

Vì vậy, nó hoạt động, nó đã được thử, và sự kém hiệu quả của nó đã dẫn đến sự phát triển của các hệ thống quét và đánh dấu thế hệ.


Có lẽ những tay cầm này không phải là khóa trong một hashtable (như trong câu hỏi), mặc dù vậy? Không cần, chỉ là một cấu trúc chứa một con trỏ. Sau đó, các tay cầm đều có cùng kích thước để chúng có thể được phân bổ ra khỏi bộ cấp phát heap. Mà bản chất của nó không cần nén bên trong vì nó không bị phân mảnh. Bạn có thể thương tiếc sự bất lực của các khối lớn được sử dụng bởi người cấp phát đó, để họ được di dời. Điều này có thể được giải quyết bằng một mức độ gián tiếp khác ;-)
Steve Jessop

@SteveJessop có, không có hashtable trong triển khai gc, mặc dù giá trị của tay cầm cũng là giá trị được trả về bởiObject.getHashCode()
Pete Kirkham
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.