일반 참조형의 기본 메모리 소비는 얼마나 될까요? [출처] 일반 참조형의 기본 메모리 소비는 얼마나 될까요?|작성자 techshare
http://blog.naver.com/techshare/100143356959
위의 글을 퍼왔습니다.
지난 번 글을 통해서, 배열과 관련된 인스턴스의 메모리를 살펴보는 방법을 알아봤습니다.
.NET Array는 왜 12 bytes 의 기본 메모리를 점유할까? ; http://www.sysnet.pe.kr/2/0/1173
Primitive 타입의 배열은 12 bytes, 기타 배열의 경우에는 Element Type 의 MT 값 - 4 bytes 를 포함해서 16 bytes가 기본소비되는 데요. 그렇다면 일반적인 클래스의 경우에는 얼마나 메모리를 소비할까요?
처음 이 의문이 들었을 때, 저는 간단하게 8 bytes 라고 생각했습니다. 왜냐 하면, ^^ 배열과 비교해서 '요소 수'로 할당된 4 bytes 가 없어지기 때문입니다. 그런데... 그게 아니더군요. ^^
직접 확인을 해볼까요? 예제를 위해, 코드는 다음과 같이 작성하고,
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program pg = new Program();
Thread.Sleep(-1);
}
}
}
windbg 로 확인하면,
0:004> .loadby sos clr0:004> !name2ee ConsoleApplication1!ConsoleApplication1.Program
PDB symbol for clr.dll not loaded
Module: 00292e9c
Assembly: ConsoleApplication1.exe
Token: 02000002
MethodTable: 00293810
EEClass: 00291424
Name: ConsoleApplication1.Program0:004> !dumpheap -mt 00293810
Address MT Size
026cbf90 00293810 12
total 0 objects
Statistics:
MT Count TotalSize Class Name
00293810 1 12 ConsoleApplication1.Program
Total 1 objects0:004> !do 026cbf90
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:Windowssyswow64KERNEL32.dll -
Name: ConsoleApplication1.Program
MethodTable: 00293810
EEClass: 00291424
Size: 12(0xc) bytes
File: D:...ConsoleApplication1.exe
Fields:
None0:004> !dumpclass 00291424
Class Name: ConsoleApplication1.Program
mdToken: 02000002
File: D:...ConsoleApplication1.exe
Parent Class: 72cb3ef8
Module: 00292e9c
Method Table: 00293810
Vtable Slots: 4
Total Method Slots: 5
Class Attributes: 100000
Transparency: Critical
NumInstanceFields: 0
NumStaticFields: 00:004> dd 026cbf90
026cbf90 00293810 00000000 00000000 00000000
026cbfa0 00000000 00000000 00000000 00000000
보시는 바와 같이, Primitive 배열 타입과 동일하게 12 bytes를 소비하고 있습니다. 일관성을 위해서였을까요?
혹시나 싶어서, int (4바이트) 형의 필드를 ConsoleApplication1.Program 에 선언하고,
namespace ConsoleApplication1
{
class Program
{
int test = 0xFF;
static void Main(string[] args)
{
Program pg = new Program();
Thread.Sleep(-1);
}
}
}
다시 메모리 값을 확인해 보면 다음과 같이 나옵니다.
0:004> !dumpheap -mt [Program 타입의 MT 값] Address MT Size 024cbf90 0019381c 12 total 0 objects Statistics: MT Count TotalSize Class Name 0019381c 1 12 ConsoleApplication1.Program Total 1 objects0:004> !dumpmt 0019381c
EEClass: 00191428
Module: 00192e9c
Name: ConsoleApplication1.Program
mdToken: 02000002
File: D:...ConsoleApplication1.exe
BaseSize: 0xc
ComponentSize: 0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 00:004> !dumpclass 00191428
Class Name: ConsoleApplication1.Program
mdToken: 02000002
File: D:...ConsoleApplication1.exe
Parent Class: 72cb3ef8
Module: 00192e9c
Method Table: 0019381c
Vtable Slots: 4
Total Method Slots: 5
Class Attributes: 100000
Transparency: Critical
NumInstanceFields: 1
NumStaticFields: 0
MT Field Offset Type VT Attr Value Name
72fd28f8 4000001 4 System.Int32 1 instance test0:004> dd 024cbf90
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:Windowssyswow64KERNEL32.dll -
024cbf90 0019381c 000000ff 00000000 00000000
024cbfa0 00000000 00000000 00000000 00000000
재미있군요. ^^ 배열 개체의 경우에 요소 수를 표현하는 데 사용되었던 4 bytes 영역에 첫번째 필드가 자리잡고 있습니다. 그렇다면, (상속하는 경우를 제외하고) Class 정의에서 필드 하나를 추가하고/하지 않고는 메모리 크기에 영향이 없다는 의미가 되겠군요. (물론 필드 하나를 더 추가하는 순간부터 메모리가 4 bytes 씩 늘어납니다.)
이로써, 그 동안의 이야기를 정리해 보면 아래와 같습니다.
primitive type 배열: 12 bytes 기타 type 의 배열: 16 bytes 배열이 아닌 일반 참조형 개체: 12 bytes