본문 바로가기

.NET/Debugging

일반 참조형의 기본 메모리 소비는 얼마나 될까요? [출처] 일반 참조형의 기본 메모리 소비는 얼마나 될까요?|작성자 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 clr

0: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.Program

0: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 objects

0:004> !do 026cbf90 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\syswow64\KERNEL32.dll - 
Name:        ConsoleApplication1.Program
MethodTable: 00293810
EEClass:     00291424
Size:        12(0xc) bytes
File:        D:\...\ConsoleApplication1.exe
Fields:
None

0: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:     0

0: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 objects

0: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: 0

0: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           test

0:004> dd 024cbf90 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\syswow64\KERNEL32.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