2011-12-02 28 views
8

TDictionary<TKey,TValue> sử dụng một mảng nội bộ được tăng lên gấp đôi nếu nó là đầy đủ:Làm cách nào để tránh hết bộ nhớ bằng TDictionary ngày càng tăng?

newCap := Length(FItems) * 2; 
if newCap = 0 then 
    newCap := 4; 
Rehash(newCap); 

này hoạt động tốt với số lượng trung bình các mặt hàng, nhưng nếu người ta được đến giới hạn trên nó là rất đáng tiếc, bởi vì nó có thể ném một EOutOfMemory ngoại trừ ngay cả khi có gần một nửa bộ nhớ vẫn có sẵn.

Có cách nào ảnh hưởng đến hành vi này không? Các lớp thu thập khác đối phó với kịch bản này như thế nào?

+1

Tôi nghĩ giả định cơ bản là bạn không tiêu tốn một nửa toàn bộ tài nguyên có sẵn của bạn trong một cá thể 'TDictionary' duy nhất. Nó không được thiết kế để sử dụng như vậy. –

+0

Vì vậy, đó sẽ là một "không, nó là không thể"? – jpfollenius

+3

Khi bạn đã tiêu thụ được một nửa bộ nhớ, bạn làm cách nào để phân bổ lại. Giả sử bạn muốn thêm 10% khác. Bạn phải phân bổ một khối mới, lớn hơn 10% so với hiện tại. Sau đó sao chép từ cũ sang mới. Sau đó deallocate cũ. Điều đó sẽ không thành công. Nghe có vẻ kỳ lạ với tôi rằng một thùng chứa duy nhất có thể tiêu thụ hơn một nửa tài nguyên của bạn. –

Trả lời

9

Bạn cần hiểu cách hoạt động của từ điển. Từ điển chứa danh sách "nhóm băm" nơi các mục bạn chèn được đặt. Đó là một số hữu hạn, vì vậy một khi bạn điền vào nó, bạn cần phải phân bổ nhiều xô hơn, không có cách nào xung quanh nó. Vì việc gán các đối tượng vào các nhóm dựa trên kết quả của hàm băm, bạn không thể chỉ thêm các thùng vào cuối mảng và đặt các công cụ trong đó, bạn cần phân bổ lại toàn bộ danh sách các khối, tái băm tất cả mọi thứ và đặt nó trong (mới) tương ứng xô.

Với hành vi này, cách duy nhất để làm cho từ điển không cấp lại sau khi đã đầy đủ để đảm bảo nó không bao giờ bị đầy. Nếu bạn biết số lượng các mục bạn sẽ chèn vào trong từ điển, hãy chuyển nó thành một tham số cho hàm khởi tạo và bạn sẽ hoàn thành, không còn thêm các từ điển.

Nếu bạn không thể làm điều đó (bạn không biết số lượng các mục bạn sẽ có trong từ điển), bạn sẽ cần phải xem xét lại những gì khiến bạn chọn TDictionary ở vị trí đầu tiên và chọn cấu trúc dữ liệu cung cấp sự thỏa hiệp tốt hơn cho thuật toán cụ thể của bạn. Ví dụ bạn có thể sử dụng cây tìm kiếm nhị phân, vì chúng làm cân bằng bằng cách xoay thông tin trong các nút hiện có, không cần phân bổ lại bao giờ.

+0

+1 Cảm ơn! Những gì tôi nghĩ là một số cách để thay đổi yếu tố tăng trưởng, để tôi có thể tính toán nó theo cách cho phép tôi sử dụng bộ nhớ có sẵn. Tôi sẽ nhìn vào cây tìm kiếm nhị phân! – jpfollenius

+0

Thay đổi yếu tố tăng trưởng sẽ không mua cho bạn nhiều, nếu bạn đã đến mức mà bạn không còn có thể phân bổ lại nữa. Bạn sẽ chỉ đến đó chậm hơn, bởi vì bạn sẽ làm nhiều phân bổ lại trên đường đi. Và nhờ vào phân mảnh không gian địa chỉ, bạn có thể đến đó chậm hơn và có ít mục được thêm vào. –

Các vấn đề liên quan