2009-10-04 31 views
7

Tôi đã sử dụng SortedList() trong một lớp lưu trữ khoảng 15-100K dữ liệu.Sử dụng bộ nhớ, SortedList vs Danh sách sự cố

Gần đây các yêu cầu của tôi đã thay đổi, dữ liệu không được lưu trữ như được sắp xếp nữa nên tôi chuyển sang Danh sách().

Tuy nhiên trong trường hợp này, tôi nhận thấy rằng Danh sách() tiêu thụ khoảng 20% ​​+ bộ nhớ nhiều hơn.

9K mục:

  • SortedList: 105MB
  • liệt kê: 125MB

15K mục:

  • SortedList: 115MB
  • Danh sách: 140MB

Trong môi trường tôi phát triển, bộ nhớ khá quan trọng. Thay vì List() những gì tôi có thể sử dụng để tránh tiêu thụ bộ nhớ thêm này và vẫn có một danh sách không được sắp xếp?

P.S. Tôi sử dụng một HashSet (Of String) để cung cấp kiểm tra duy nhất trong khi sử dụng List (Of) để mô phỏng SortedList.ContainsKey() mặc dù tôi không nghĩ rằng nó có thể mang lại chi phí bộ nhớ như vậy.

P.S. 2: Ứng dụng của tôi đã có khoảng 80 MB cấp phát bộ nhớ cơ sở trong khi khởi động. Vì vậy, con số sẽ được sửa như 105-80 = 25, 125-80 = 45 và vân vân

KẾT QUẢ

Cảm ơn tất cả các câu trả lời, kết quả cuối cùng là:

  • Bạn nên đặt dung lượng chính xác để tiết kiệm bộ nhớ
  • Hashset rất xấu về bộ nhớ và tiêu thụ nhiều hơn mong đợi. Đây là vấn đề. Somehow SortedList() quản lý để sử dụng ít bộ nhớ hơn cho một chức năng tương tự.

Một số Bencmarks: 500 ký tự, 250000 chèn

Danh sách (STRING) (50000)

274 ​​ms - 226 MB

SortedList (Tất String, Chuỗi) (50000)

34868 ms - 230 Mb

Hashset

420 ms - 232 MB

điển (HÀNH String, Object)

486 ms - 234 MB

Mặc dù khi tôi thay đổi giảm đếm đến 25, sau đó:

Hashset cho 600.000 lặp 300 Mb nơi Danh sách() là 286 Mb

Cũng về việc sử dụng bộ nhớ Hashset: http://blog.mischel.com/2008/04/09/hashset-limitations/ điển (Tất chuỗi, đối tượng) không phải là tốt hơn nhiều hoặc trong thử nghiệm của tôi.

+4

Bạn lấy các giá trị đó từ đâu? –

+0

Từ ứng dụng thử nghiệm của tôi, mặc dù bộ nhớ nên bộ nhớ - bộ nhớ cơ sở của ứng dụng (đó là khoảng 80MB). –

+2

Từ Trình quản lý Tác vụ (hoặc tương tự)? Hãy thử sử dụng một profiler (như CLRProfiler: http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda). Dữ liệu bộ nhớ từ Task Manager phụ thuộc vào hành vi thu gom rác thải. –

Trả lời

3

A List<T> với 9k mục sẽ có dung lượng từ 9k đến 18k, vì vậy chi phí cho các mục đó sẽ từ 36 đến 72 kilobyte (gấp đôi trên hệ thống 64 bit).

Rõ ràng 72 kB thậm chí không gần với sự khác biệt 20 MB mà bạn thấy, do đó việc sử dụng bộ nhớ của chính danh sách không thể là nguyên nhân.Escpecially xem xét rằng danh sách được sắp xếp cũng phải giữ một tham chiếu đến từng đối tượng, do đó việc sử dụng bộ nhớ nên giống nhau.

Vì vậy, có một cái gì đó khác bằng cách sử dụng bộ nhớ, hoặc bạn không nhìn vào việc sử dụng bộ nhớ thực tế của ứng dụng. Nếu bạn đang tìm trong trình quản lý tác vụ, bạn không nhìn thấy dung lượng bộ nhớ được sử dụng, chỉ có bao nhiêu trình quản lý bộ nhớ đã cấp phát.

2

Nếu bạn đã có một bộ sưu tập của HashSet, tôi không chắc chắn tại sao bạn cần danh sách, nhưng nếu bạn đang tìm một vùng chứa đảm bảo tính duy nhất và chức năng ContainsKey(), tại sao không phải là một từ điển chung?

Bất kể quyết định của bạn về các câu hỏi ở trên, việc sử dụng một cái gì đó như Trình quản lý tác vụ chỉ là quá không chính xác để đưa ra quyết định về mức tiêu thụ bộ nhớ trong .NET. Nếu bạn chưa làm như vậy, hãy dùng thử phiên bản SciTech's .NET Memory Profiler hoặc ANTS Profiler và chạy ứng dụng của bạn. Chụp nhanh sử dụng bộ nhớ của bạn ngay trước khi tải lên bộ của bạn và chỉ sau khi so sánh. Bạn có thể thực hiện việc này với một số loại bộ sưu tập để đo mức sử dụng bộ nhớ tương đối của từng loại theo cách chính xác cao.

+1

+1 để đề xuất sử dụng profiler để có được dữ liệu chính xác. –

9

Bạn có preallocating khả năng List<T> không?

thí nghiệm nhỏ mà tôi đã làm:

chương trình này có ~ 640MB

List<int> list = new List<int>(0); 

for (int i = 0; i < 100000000; i++) 
{ 
    list.Add(i); 
} 

chương trình này có ~ 320MB

List<int> list = new List<int>(100000000); 

for (int i = 0; i < 100000000; i++) 
{ 
    list.Add(i); 
} 
+5

+1 Đây là một quan sát tuyệt vời bởi vì một danh sách preallocated sẽ lấy một khối liền kề của RAM cùng một lúc nếu nó có thể và giảm chi phí phát sinh do phân mảnh bộ nhớ. –

+0

Điểm rất hay, tôi sẽ thử ngay bây giờ. Không cùng một vấn đề tồn tại đối với SortedList()? –

+0

Tất cả các thùng chứa có thuộc tính "dung lượng" cần được đặt để đạt hiệu suất tối ưu. –

1

HashSets (& hashtables) sử dụng nhiều bộ nhớ! Nhiều hơn một danh sách/danh sách được sắp xếp đơn giản

+0

Một từ điển sử dụng bộ nhớ nhiều gấp đôi nội bộ như một Danh sách (50% nhiều hơn trên một hệ thống 64 bit), do đó, sự khác biệt không phải là lớn. – Guffa

+0

Vâng, nó không chính xác 50%. Hashtables không bao giờ 100% đầy đủ, chúng được tái kích thước khi chúng đạt 70%. Danh sách chỉ được thay đổi kích thước khi chúng hoàn toàn đầy. – Lotfi

0

Kiểm tra Bộ sưu tập nguồn theo Wintellect, tương đương .NET cho bộ sưu tập loại STL. Tôi tin rằng loại Set nên cung cấp cho bạn các chức năng bạn cần (tính độc đáo) nhưng bạn phải làm các tiêu chuẩn để so sánh. Chỉ cần 2 xu của tôi.

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