2008-11-27 43 views
51

Tôi đang cố gắng tìm hiểu xem có bao nhiêu bộ nhớ mà đối tượng của tôi thực hiện để xem có bao nhiêu bộ nhớ kết thúc trên Heap đối tượng lớn (bất kỳ thứ gì vượt quá 85.000 byte). Nó đơn giản như thêm 4 cho một int, 8 cho một dài, 4 (hoặc 8 nếu bạn đang ở trên 64 bit) cho bất kỳ loại tài liệu tham khảo vv cho mỗi đối tượng, hoặc có overheads cho các phương pháp, tài sản, v.v ...Tìm hiểu kích thước của đối tượng .net

+0

Câu hỏi liên quan: [sizeof Tương đương với các loại tham chiếu] (http://stackoverflow.com/questions/26570/sizeof-equivalent-for-reference-types) –

+0

Xem câu hỏi này, [Lấy kích cỡ của một trường theo byte với C#] [1], và đặc biệt [Jon Skeets trả lời] [2] Về cơ bản, nó không * đơn giản như ... * [1]: http://stackoverflow.com/questions/207592/getting-the -size-of-a-field-in-byte-với-c [2]: http://stackoverflow.com/questions/207592/getting-the-size-of-a-field-in-bytes-with -C# 207605 –

Trả lời

47

Đừng quên rằng kích thước của một đối tượng thực tế không bao gồm kích thước của bất kỳ đối tượng nào mà nó tham chiếu.

Những thứ duy nhất có khả năng kết thúc trên đống đối tượng lớn là mảng và chuỗi - các đối tượng khác có xu hướng tương đối nhỏ trong bản thân. Ngay cả một đối tượng có (nói) 10 biến kiểu tham chiếu (4 byte mỗi ngày x86) và 10 GUID (16 byte mỗi) chỉ chiếm khoảng 208 byte (có một chút chi phí cho tham chiếu kiểu và khối đồng bộ). Tương tự như vậy khi nghĩ về kích thước của một mảng, đừng quên rằng nếu kiểu phần tử là một kiểu tham chiếu, thì nó chỉ là kích thước của tài liệu tham khảo đếm cho chính mảng đó. Nói cách khác, ngay cả khi bạn có một mảng với 20.000 phần tử, kích thước của đối tượng mảng tự nó sẽ chỉ hơn 80K (trên x86) ngay cả khi nó tham chiếu nhiều dữ liệu hơn.

4

Trừ khi đó là một loại valuetype lớn hoặc loại cá thể (nghĩa là hàng nghìn trường), loại duy nhất bạn cần phải lo lắng là mảng lớn hoặc chuỗi. Tất nhiên, để tìm ra kích thước của một mảng, bạn cần phải biết kích thước phần tử.

.NET (hiện tại) sắp xếp các loại theo cách tương tự như trình biên dịch gốc sắp xếp các loại. loại cơ bản có sự sắp xếp, tự nhiên mà thường là tròn-up sức mạnh không thể thiếu của hai gần gũi nhất với kích thước của chúng:

Single, Int32, UInt32 - 4 
IntPtr, UIntPtr, pointers, references - 4 on 32-bit, 8 on 64-bit 
Double, Int64, UInt64 - 8 
Char, Int16, UInt16 - 2 
Byte, SByte   - 1 

Khi lắp ráp một kiểu, trình biên dịch sẽ đảm bảo rằng tất cả các lĩnh vực của bất kỳ loại nhất định có khởi đầu của họ bù đắp trong vòng thể hiện được liên kết với một đường viền khớp với loại đó - giả sử rằng bố cục rõ ràng không được sử dụng.

Các loại do người dùng tự xác định có căn chỉnh, được tính là căn chỉnh cao nhất của bất kỳ loại trường nào của chúng. Kích thước của loại được mở rộng nếu cần thiết để làm cho kích thước của loại được căn chỉnh quá.

Nhưng tất nhiên, tất cả các loại tham chiếu vẫn chỉ IntPtr. Kích thước và kích thước, vì vậy kích thước của loại tham chiếu sẽ không ảnh hưởng đến mảng thuộc loại đó. Lưu ý rằng CLR có thể chọn, theo quyết định của riêng mình, đối với các loại bố cục khác với mô tả ở trên, có thể để tăng vị trí bộ nhớ cache hoặc giảm đệm theo yêu cầu.

9

Bạn đang tham gia vào vùng gỡ lỗi .NET nâng cao. Bắt đầu với John Robins debugging books.

Sử dụng WinDBG với Sos.dll (một phần của phân phối .NET) và Sosex.dll tiện ích mở rộng. Với những công cụ này, bạn có thể thực sự thấy những gì đang xảy ra khi ứng dụng của bạn đang chạy. Bạn sẽ tìm thấy câu trả lời cho các câu hỏi được đề cập ở trên của bạn.

(Một gợi ý khác sẽ được cài đặt Shared Source CLI 2.0, aka Rotor 2, để xem những gì đang xảy ra dưới mui xe..)

9

Nếu bạn có thể - Serialize nó!

Dim myObjectSize As Long 

Dim ms As New IO.MemoryStream 
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter() 
bf.Serialize(ms, myObject) 
myObjectSize = ms.Position 
+0

Thật không may nếu bạn serialize một đối tượng thì bạn cũng serialize tất cả các đối tượng mà nó đề cập đến –

+2

+1 vì đây là những gì tôi thực sự muốn tìm hiểu (không chỉ kích thước của tài liệu tham khảo) – alldayremix

+1

@MatthewSteeples, một đối tượng không có các thành phần của nó đối tượng trống, vì vậy nếu bạn muốn "kích thước" của vùng chứa, nó phải bao gồm kích thước của các bộ sưu tập. – serhio

34

Vui lòng làm theo các bước sau để lấy kích thước của đối tượng.

1) chuyển đến Visual Studio (2010) Thuộc tính dự án -> Tab Debug -> Bật gỡ lỗi mã không được quản lý.

2) chuyển đến menu Visual Studio Debug -> Tùy chọn và cài đặt -> Gỡ lỗi -> Ký hiệu.

3) Có cho phép Microsoft Symbol Server, để mặc định. (Biểu tượng có thể bắt đầu tải về)

4) Thiết lập các điểm break trong mã của bạn, hãy bắt đầu gỡ lỗi (F5).

5) Mở Debug -> Windows -> Cửa sổ ngay lập tức.

6) nhập .load sos.dll (Con Strike)

7) nhập! DumpHeap kiểu MyClass (đối tượng bạn muốn tìm kích thước)

8) từ đặt ra xác định vị trí địa chỉ của đối tượng tức là (00a8197c)

địa chỉ MT Kích 00a8197c 00955124 36

9) Tiếp theo,! ObjSize 00a8197c

10) Có bạn đi -> sizeof (00a8197c) = 12 (0x48) byte (MyClass) phương pháp

+6

Không biết bạn có thể sử dụng sos.dll trong studio trực quan. Thực sự hữu ích, cảm ơn. Cũng có thể hữu ích để lưu ý rằng sos.dll sẽ không tải nếu ứng dụng ở chế độ 64 bit. Xem http://stackoverflow.com/a/3548129/442078 – Will

+0

Hãy chắc chắn rằng bạn hiểu "nhược điểm" của '! ObjSize'. Nó sẽ tính toán các chu kỳ trong đồ thị đối tượng của bạn. Ví dụ: nếu bạn có từ điển, với các giá trị tham chiếu chính từ điển, mỗi giá trị sẽ có "ObjSize" của toàn bộ từ điển. –

5

Gomes của đơn giản:

  1. đi đến Visual Studio (2010) Project Properties -> tab Debug - > Bật gỡ lỗi mã không được quản lý.

  2. Đặt điểm ngắt trong mã của bạn, bắt đầu gỡ lỗi (F5).

  3. Mở Debug -> Windows -> Cửa sổ ngay lập tức.

  4. nhập .load sos

  5. nhập (thay thế myObject với tên của đối tượng của bạn)

? String.Format ("{0: x}", Integer.Parse (System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject (System.Runtime.InteropServices.GCHandle.Alloc (myObject) .GetHandleValue()). ToString().) - 4)

      6. Sử dụng kết quả như tham số của!ObjSize

see: SOS.DLL, object Address and Visual Studio debugger Introduction

Ví dụ (chúng tôi đang tìm kiếm đối tượng có tên tbl):

.load sos 
extension C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll loaded 
? string.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc(tbl).GetHandleValue()).ToString())-4) 
"27ccb18" 
!ObjSize 27ccb18 
PDB symbol for clr.dll not loaded 
sizeof(027ccb18) =  154504 ( 0x25b88) bytes (System.Data.DataTable) 
0

Là một ước tính (năm 2017), bạn có thể gỡ lỗi vào ứng dụng của bạn, thiết lập một breakpoint trước từ điển của bạn phát trực tiếp, sử dụng "Ảnh chụp sử dụng bộ nhớ" (Tab: Sử dụng bộ nhớ trong Công cụ chẩn đoán), điền từ điển của bạn và nhận một ảnh chụp nhanh khác - không chính xác đặt một cử chỉ tốt.

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