2010-09-24 42 views
9

Đúng là các bộ sưu tập chung thực hiện tốt hơn các bộ sưu tập không chung chung cho các loại giá trị. (ví dụ: Danh sách so với ArrayList).Các loại giá trị được lưu trữ ở đâu (C#) Bộ sưu tập chung

Nhưng tại sao điều đó, khác với bước giải boxing? Các đối tượng kiểu giá trị được lưu trữ khi nào được thêm vào bộ sưu tập? Trong các bộ sưu tập không chung chung, chúng sẽ được đóng hộp và lưu trữ trên heap, những gì là khác nhau trong generics?

+0

Đối với cùng một số nguyên, sizeof (Danh sách ) ~ = sizeof (int []) ~ = 1/2 sizeof (ArrayList trên x86) ~ = 1/3 sizeof (ArrayList trên x86-64). Ngoài ra địa phương của dữ liệu hút trên ArrayList do boxing và nó sản xuất cao hơn phân mảnh bộ nhớ cần thiết. –

Trả lời

1

An ArrayList là một mảng tham chiếu cục bộ đối với các đối tượng được lưu trữ trong heap.

Danh sách chung loại tham chiếu là một mảng tham chiếu cục bộ đối với các đối tượng được lưu trữ trong vùng lưu trữ.

Danh sách chung các loại giá trị là một mảng địa phương của các loại giá trị đó.

Có hai vùng bộ nhớ, hầu hết các tham chiếu đều gọi là "Ngăn xếp" và "Heap". Hầu hết những người sử dụng các điều khoản đó không có ý tưởng tại sao. ("The Stack" có thể là một ngăn xếp, nhưng The Heap gần như chắc chắn không phải là một đống). Tôi thích các cụm từ "Over Here" và "Over There". Khi được đóng hộp, dữ liệu kiểu giá trị được lưu trữ "Over There". Khi được lưu trữ trong một mảng (có lẽ bên trong một Danh sách chung), dữ liệu kiểu giá trị được lưu trữ "Trên đây". "Ở đây" là tốt hơn.

+0

"Ở đây" - "ở đằng kia" ??? Gì???? Và "mảng cục bộ" là gì? Câu trả lời này là khó hiểu hơn bất cứ điều gì. –

+0

@ 0xA3: Mảng cục bộ là mảng được lưu trữ trong "Ngăn xếp". Liệu nó có khai sáng nhiều hơn theo cách đó? –

+2

OK, sau đó tuyên bố của bạn là không chính xác (nếu bạn có nghĩa là ngăn xếp theo nghĩa thường được sử dụng).Cả hai 'ArrayList' và' Danh sách 'sử dụng một System.Array như lưu trữ nội bộ mà là một loại tài liệu tham khảo và được lưu trữ" trên đó ". –

11

Trong generics, chẳng hạn như List<T>, chúng vẫn được lưu trữ trên heap. Sự khác biệt là, trong nội bộ, một List<int> làm cho một mảng duy nhất của số nguyên, và có thể lưu trữ các số trực tiếp. Với ArrayList, bạn sẽ lưu trữ một mảng các tham chiếu đến các giá trị số nguyên được đóng hộp.

0

Có một số lý do bên cạnh quyền anh và unboxing, bao gồm bộ nhớ đệm và cách chúng được liệt kê để thực hiện công việc của họ. Hãy xem this post, especially the comments.

0

Lợi ích hiệu suất trong generics thường chỉ liên quan đến các loại giá trị được sử dụng với generics so với các loại giá trị được lưu trữ trong tương đương không chung chung.

Điều này là do với các loại giá trị generics không cần phải được đúc thành đối tượng và được lưu trữ trên heap (đóng hộp). Trong thực tế, họ có thể vẫn còn trên stack đó là performant hơn.

http://msdn.microsoft.com/en-us/library/ms172181.aspx

8

Các chi tiết thi hành có liên quan là việc lưu trữ cơ bản cho một List<T> là một T []. Vì vậy, đối với một List<int> các giá trị sẽ được lưu trữ trong một int []. Các số nguyên được lưu trữ trong một bộ nhớ tiếp giáp, được phân bổ từ đống rác thu thập được.

Điều gì làm cho nó quá nhanh không chỉ là các số nguyên không được đóng hộp, nó là một int [] hoạt động rất tốt với bộ nhớ cache CPU. Khi bạn đọc phần tử đầu tiên, về cơ bản bạn có 15 bản miễn phí tiếp theo mà không phải đọc bộ nhớ RAM chậm hoặc bộ đệm thứ cấp. Điều này hoạt động gần như không tốt cho một int đóng hộp bởi vì nó là quá lớn và tham khảo thêm có thể có địa phương bộ nhớ cache nghèo. Tuy nhiên, các nhà sưu tập rác thực sự giúp đỡ để lấy sting ra khỏi chi phí đó bằng cách nén đống.

+0

Ah, câu trả lời duy nhất nói rõ ràng rằng 'Danh sách 'trên thực tế sử dụng một mảng làm cửa hàng sao lưu (và cũng được đặt quá). Một 'List ' chỉ đơn giản là một trình bao bọc cho một mảng bổ sung thêm sự hỗ trợ để thay đổi kích thước, và trên thực tế hầu như tất cả các loại bộ sưu tập đều đi xuống các mảng, ngoại trừ các bộ sưu tập đặc biệt như 'LinkedList '. –

+0

Vì vậy, một 'ArrayList' có một hit hiệu suất gấp đôi. Trước tiên, bạn phải dereference giá trị từ mảng để có được đối tượng (kiểu giá trị đóng hộp), và sau đó bạn phải unbox nó. –

+0

Nhưng nếu cửa hàng sao lưu cho 'ArrayList' là' object [] ', thì trước tiên bạn phải tra cứu mục trong mảng, cung cấp cho bạn tham chiếu đến đối tượng chứa int. Bạn phải dereference rằng để có được các đối tượng, sau đó bạn phải unbox nó. So sánh điều đó với 'List', tất cả những gì bạn phải làm là lấy mục từ cửa hàng sao lưu' int [] '. –

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