ã¢ããªã±ãŒã·ã§ã³ãäœæããéã®æãéèŠãªåé¡ã®1ã€ã¯ãã¡ã¢ãªæ¶è²»ãšå¿çæ§ïŒé床ïŒã§ãã
ã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ãäœæ¥ãäºæž¬ã§ããªããã©ãã¯ããã¯ã¹ã§ãããšèããããŠããŸãã
ãŸãã.NETã®GCã¯å®éã«ã¯ã«ã¹ã¿ãã€ãºã§ããªããšèšã£ãŠããŸãã ãŸãã.NET Frameworkã¯ã©ã¹ãšCLRãGCãªã©ã®äž¡æ¹ã®ãœãŒã¹ã³ãŒããèŠãããšãã§ããŸããã
ãããŠãç§ã¯ã©ã®ããã«èšã£ãŠãïŒ
ãã®èšäºã§ã¯ã次ã®ããšãæ€èšããŸãã
- ã¡ã¢ãªå
ã®ãªããžã§ã¯ãã®é
çœ®ãæŽçããæ§é
- CLR 4.5ããã¯ã°ã©ãŠã³ããµãŒããŒGC
- é©åãªã¬ããŒãžã³ã¬ã¯ã·ã§ã³
- .NET 4.0+ãžã®å¹ççãªã¢ããªã±ãŒã·ã§ã³ã¢ããã°ã¬ãŒã
- é©åãªæåã¡ã¢ãªç®¡ç
objectsãªããžã§ã¯ããã¡ã¢ãªã«é
眮ããããã®çµç¹æ§é
CLRãªããžã§ã¯ãã®ãµã€ãºå€æŽã«ã€ããŠæ¢ã«
æžããããšããããŸãã èšäºãå床èªããªãããã«ãèŠç¹ãæãåºããŠã¿ãŸãããã
倿°åç
§åã®å ŽåãCILåœä»€
newobjãŸãã¯ããšãã°CïŒã®
newæŒç®åã䜿çšãããšãåºå®ãµã€ãºå€ãã¹ã¿ãã¯ã«é
眮ãããŸãïŒx86ã®å Žåã¯4ãã€ããDWORDåãªã©ïŒãéåžžã®ããŒãã«äœæããããªããžã§ã¯ãã€ã³ã¹ã¿ã³ã¹ã®ã¢ãã¬ã¹ãå«ãŸããŸãïŒå¿ããªãã§ãã ããïŒãããŒãžããŒãã¯ãSmall Object HeapãšLarge Object Heapã«åããããŸã-詳现ã«ã€ããŠã¯ãGCã®æ®µèœã§åŸè¿°ããŸãïŒã ãã®ãããC ++ã§ã¯ãã®å€ã¯ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒãšåŒã°ãã.NETã®äžçã§ã¯ãªããžã§ã¯ããžã®åç
§ãšåŒã°ããŸãã
ãªã³ã¯ã¯ãã¡ãœããã®å®è¡æã«ã¹ã¿ãã¯äžã«ååšããããã¯ã©ã¹ã®ãã£ãŒã«ãå
ã«ååšããŸãã
ãªã³ã¯ãäœæããã«ããã¥ãŒã ã§ãªããžã§ã¯ããäœæããããšã¯ã§ããŸããã
ãªããžã§ã¯ãã®ãµã€ãºã«é¢ããæšæž¬ããªãã
SOSïŒSon of StrikeïŒ ãGC.TotalMemoryã®æž¬å®å€ãªã©ã䜿çšããŠãã¹ããå®è¡ããŸãã -CLRãœãŒã¹ããŸãã¯ããã
å
±æãœãŒã¹å
±éèšèªã€ã³ãã©ã¹ãã©ã¯ãã£2.0ãèŠãŠãã ãã ãããã¯äžçš®ã®ç ç©¶ãããžã§ã¯ãã§ãã
åã¿ã€ãã«ã¯ç¬èªã®MethodTableããããåãã¿ã€ãã®ãªããžã§ã¯ãã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¯åãMethodTableãåç
§ããŸãã ãã®ããŒãã«ã«ã¯ãåèªäœã«é¢ããæ
å ±ïŒã€ã³ã¿ãŒãã§ã€ã¹ãæœè±¡ã¯ã©ã¹ãªã©ïŒãæ ŒçŽãããŸãã
åãªããžã§ã¯ãã«ã¯ã
SyncTableEntryã¢ãã¬ã¹ïŒsyncblkãšã³ããªïŒãæ ŒçŽãããªããžã§ã¯ãããããŒãšã¡ãœããããŒãã«ãã€ã³ã¿ãŒïŒTypeHandleïŒã®2ã€ã®è¿œå ãã£ãŒã«ããå«ãŸããŸãã
SyncTableEntry -CLRãªããžã§ã¯ããžã®ãªã³ã¯ãšSyncBlockèªäœãžã®ãªã³ã¯ãæ ŒçŽããæ§é ã
SyncBlockã¯ããªããžã§ã¯ãã®ããã·ã¥ã³ãŒããæ ŒçŽããããŒã¿æ§é ã§ãã
ã誰ã«ã§ãããšã¯ãCLRãç¹å®ã®æ°ã®SyncBlockãäºåã«åæåããããšãæå³ããŸãã ããã«ãGetHashCodeïŒïŒãŸãã¯Monitor.EnterïŒïŒãåŒã³åºããšãç°å¢ã¯ãªããžã§ã¯ãã®ããããŒã«å®æããSyncBlockãžã®ãã€ã³ã¿ãŒãæ¿å
¥ããéäžã§ããã·ã¥ã³ãŒããèšç®ããŸãã
ãããè¡ãã«ã¯ã
GetSyncBlockã¡ãœãããåŒã³åºããŸãïŒ
% %\sscli20\clr\src\vm\syncblk.cpp)
ãã¡ã€ã«
% %\sscli20\clr\src\vm\syncblk.cpp)
ã確èªããŸã
% %\sscli20\clr\src\vm\syncblk.cpp)
ã ã¡ãœããã®æ¬äœã§ã¯ã次ã®ã³ãŒããèŠãããšãã§ããŸãã
else if ((bits & BIT_SBLK_IS_HASHCODE) != 0) { DWORD hashCode = bits & MASK_HASHCODE; syncBlock->SetHashCode(hashCode); }
System.Object.GetHashCodeã¡ãœããã¯ã
SyncBlock :: GetHashCodeã¡ãœãããåŒã³åºãããšã«ãããSyncBlockæ§é ã«äŸåããŸãã
CLR 2.0ã®åæsyncblkå€ã¯0ã§ãããCLR 4.0以éã§ã¯å€ã¯-1ã§ãã
Monitor.ExitïŒïŒãåŒã³åºããšãsyncblkã¯åã³-1ã«ãªããŸãã
ãŸããSyncBlocksã®é
åã¯
å¥ã®ã¡ã¢ãªã«æ ŒçŽãã
ãŠããã GCã«ã¯
ã¢ã¯ã»ã¹ã§ããªãããšã«æ³šæããŠãã ããã
ã©ãããŠïŒ ãé¡ãããŸãã
çãã¯ç°¡åã§ã-匱ããªã³ã¯ã CLRã¯ãSyncBlocké
åã«åŒ±ãæžã蟌ã¿ãªã³ã¯ãäœæããŸãã CLRãªããžã§ã¯ããæ¶æ»
ãããšãSyncBlockãæŽæ°ãããŸãã
Monitor.EnterïŒïŒã¡ãœããã®å®è£
ã¯ããã©ãããã©ãŒã ãšJITèªäœã«äŸåããŸãã ãããã£ãŠãSSCLIãœãŒã¹ã®ãã®ã¡ãœããã®ãšã€ãªã¢ã¹ã¯
JIT_MonEnterã§ãã
ãªããžã§ã¯ããã¡ã¢ãªã«é
眮ãããšãããããã¯ãšãã®ãµã€ãºã«æ»ããšããªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ïŒç©ºã®ã¯ã©ã¹ïŒã¯x86ã§å°ãªããšã12ãã€ãå¿
èŠã§ãããx64ã§ã¯ãã§ã«24ãã€ãããããšãæãåºããŠãã ããã
SOSãèµ·åããã«ããã確èªããŸãã
ãã¡ã€ã«
% %\sscli20\clr\src\vm\object.h
#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader)) class Object { protected: MethodTable* m_pMethTab; }; class ObjHeader { private: DWORD m_SyncBlockValue;
CLRãªããžã§ã¯ãã®ãµã€ãºã«é¢ãããã®èšäºã®ã³ã¡ã³ãã§ã蚌æ ãªãã«System.Stringã®ãµã€ãºãèšç®ããããšã®äžæ£ç¢ºãã«ã€ããŠéé£ãããŸããã
ããããç§ã¯æ°åãš...ãœãŒã¹ã³ãŒãããã£ãšä¿¡é ŒããŠããŸãïŒ
.NET 4.0ã®System.Stringã¯ã次ã®ã¡ã³ããŒã§æ§æãããŠããŸãã
- m_firstChar
- m_stringLength
- 空ã®

Emptyãèæ
®ããŸããããªããªãã ããã¯ç©ºã®éçæååã§ãã
m_stringLengthã¯ãæååã®é·ãã瀺ããŸãã
m_firstCharã¯ãUnicodeæåã®é
åã®ã¹ãã¬ãŒãžã®å
é ãžã®
ãã€ã³ã¿ãŒ ïŒ!!!ïŒã§ãããé
åã®æåã®æåã§ã¯ãã
ãŸãã ã
ããã§ã¯éæ³ã¯äœ¿ãããŸãã-CLRã¯ãªãã»ãããèŠã€ããã ãã§ãã
ããã確èªããã«ã¯ãarchiveïŒ
\ sscli20 \ clr \ src \ vm \ object.hã§fileïŒ
ãã©ã«ããŒãå床éããŸã
ãã¡ã€ã«ã®æåã«ãã³ãŒãã«é¢ããã³ã¡ã³ãããããŸãã
ããã¯ãæååããŒã¿ãæ ŒçŽããå
éšæ§é ã§ãã
次ã«ã
StringObjectã¯ã©ã¹ãšãã®GetBufferïŒïŒã¡ãœãããèŠã€ããŸãã
WCHAR* GetBuffer() { LEAF_CONTRACT; _ASSERTE(this); return (WCHAR*)( PTR_HOST_TO_TADDR(this) + offsetof(StringObject, m_Characters) ); }
ããŠããããã¡ïŒæåã®é
åïŒã¯ããªãã»ããã«ãã£ãŠåçŽã«èšç®ãããŸãã
ããããSystem.Stringèªäœã¯ã©ãã§ããïŒ
archiveïŒ
\ sscli20 \ clr \ src \ bcl \ system \ string.csã§fileïŒ
ãã©ã«ããŒãéããŸã
次ã®è¡ã衚瀺ãããŸãã
ãã ããSystem.Stringã¯ããã®äœæ¥ã«ãããŠãã³ã³ã¹ãã©ã¯ã¿ãŒèªäœãšå€ãã®ã¡ãœããïŒPadLeftãªã©ïŒãå®è£
ããCOMStringã«äŸåããŠããŸãã
ãã¬ãŒã ã¯ãŒã¯ã®ã¡ãœããåãšå
éšC ++å®è£
ã®ã¡ãœããåãæ£ããäžèŽãããã«
% %\sscli20\clr\src\vm\ecall.cpp
ãã¡ã€ã«
% %\sscli20\clr\src\vm\ecall.cpp
ã確èªããããšããå§ãããŸã
ããŠãm_firstCharã
ãã€ã³ã¿ãŒã§ããããšãæçµçã«ç¢ºèªããããã«ãããšãã°Joinã¡ãœããã³ãŒãã®äžéšãæ€èšããŠãã ããã
fixed (char* ptr = &text.m_firstChar) { UnSafeCharBuffer unSafeCharBuffer = new UnSafeCharBuffer(ptr, num); unSafeCharBuffer.AppendString(value[startIndex]); for (int j = startIndex + 1; j <= num2; j++) { unSafeCharBuffer.AppendString(separator); unSafeCharBuffer.AppendString(value[j]); } }
èšç®ããããã«ç°ãªã
ããŒãžã§ã³ ïŒãã ãåã
çµæ ïŒãæåãªJon Skeetãå°ããŸãã
å
ã«é²ãåã«ãã¹ã¿ãã¯ã«ã€ããŠæãåºããããšæããŸãã
ã¹ã¿ãã¯ã¯ãã¡ãœãããåŒã³åºããããã³ã«ç°å¢ã«ãã£ãŠäœæãããã³ã³ãããŒã§ãã åŒã³åºããå®äºããããã«å¿
èŠãªãã¹ãŠã®ããŒã¿ïŒããŒã«ã«å€æ°ããã©ã¡ãŒã¿ãŒãªã©ã®ã¢ãã¬ã¹ïŒãä¿åããŸãã
ãããã£ãŠãåŒã³åºãããªãŒã®åŒã³åºãã¯ãã¹ã¿ãã¯ã§æ§æãããFIFOã³ã³ãããŒã§ãã çŸåšã®ã¡ãœããã®åŒã³åºããçµäºãããšãã¹ã¿ãã¯ãã¯ãªã¢ãããŠç Žæ£ããã芪ãã©ã³ãã«å¶åŸ¡ãæ»ããŸãã
äžèšã§æžããããã«ã倿°åç
§åã®å Žåãéåžžã®ããŒãã§äœæããããªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ã®ã¢ãã¬ã¹ãå«ãåºå®ãµã€ãºã®å€ïŒx86ã®å Žåã¯4ãã€ããDWORDåãªã©ïŒãã¹ã¿ãã¯ã«ããã·ã¥ãããŸãã
ããã©ã«ãã§ã¯ããã¯ã·ã³ã°ã«é¢ä¿ããªãããªããã£ãåã®ã€ã³ã¹ã¿ã³ã¹ãã¹ã¿ãã¯ã«é
眮ãããŸãã
ãã ããããã€ãã®æé©åã«ãããJIT-ã¯RAMããã€ãã¹ããŠã倿°ã®å€ãããã»ããµã¬ãžã¹ã¿ã«ããã«é
眮ã§ããŸãã
ãã®ãããªããã»ããµã¬ãžã¹ã¿ã¯ãããã»ããµå
éšã§è¶
é«éRAMã¡ã¢ãªã圢æããã¡ã¢ãªã»ã«ã®ãããã¯ã§ãããããã»ããµèªäœã«ãã£ãŠäœ¿çšãããã»ãšãã©ã®å Žåããã°ã©ããã¢ã¯ã»ã¹ã§ããªãããšãæãåºããŠãã ããã
CPUãã£ãã·ã¥ã倧ããã»ã©ããœãããŠã§ã¢ãã©ãããã©ãŒã ã«é¢ä¿ãªããããé«ãããã©ãŒãã³ã¹ãåŸãããšãã§ããŸãã
âGCããã€ã¹
ãåãã®ããã«ãã¡ã¢ãªç®¡çïŒãªããžã§ã¯ãã®äœæãšç Žæ£ïŒã¯ãã¬ããŒãžã³ã¬ã¯ã¿ïŒå¥åGarbage CollectorïŒGCïŒïŒã«ãã£ãŠåŠçãããŸãã
ã¢ããªã±ãŒã·ã§ã³ãæ©èœããããã«ãCLRã¯ä»®æ³ã¢ãã¬ã¹ç©ºéã®2ã€ã®ã»ã°ã¡ã³ãïŒã¹ã¢ãŒã«ãªããžã§ã¯ãããŒããšã©ãŒãžãªããžã§ã¯ãããŒãïŒãçŽã¡ã«åæåããŸãã
ç°¡åãªã¡ã¢ïŒä»®æ³ã¡ã¢ãªã¯ãç©ççã§ã¯ãªãã¡ã¢ãªã®è«çç衚çŸã§ãã ç©çã¡ã¢ãªã¯ãå¿
èŠãªå Žåã«ã®ã¿å²ãåœãŠãããŸãã ææ°ã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®åããã»ã¹ã«ã¯ãããŒãžããŒã·ã§ã³ãå¯èœãªæå€§ã¢ãã¬ã¹å¯èœãµã€ãºïŒ32ãããOSã®å Žåã¯4GBïŒã®ä»®æ³ã¢ãã¬ã¹ã¹ããŒã¹ãå²ãåœãŠãããŸãïŒx86ãIA-64ãPowerPC-64ãã©ãããã©ãŒã ã®å Žåãæå°ãµã€ãºã¯4KBãSPARC-8KBïŒã ããã«ãããããããã»ã¹ã®ã¢ãã¬ã¹ç©ºéãå¥ã®ããã»ã¹ããåé¢ããããšãå¯èœã«ãªãããã£ã¹ã¯äžã§ã¹ã¯ããã䜿çšããããšãå¯èœã«ãªããŸãã
ã¡ã¢ãªã·ã¹ãã ã«å²ãåœãŠãŠæ»ãããã«ãGCã¯Win32颿°
VirtualAllocããã³
VirtualFreeã䜿çšããŸãã
.NETã®ã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯äžä»£ãè¶
ããŠããŸããã€ãŸãã 管çããŒãïŒãããããªããžã§ã¯ãïŒã¯äžä»£ã«åããããŸãã ãã¹ãŠã®ãªããžã§ã¯ãã¯ãã©ã€ããµã€ã¯ã«ãéããŠè€æ°ã®äžä»£ã«åå²ãããŸãã
ãªããžã§ã¯ãåç
§ã®ãœãŒã¹ã¯ãããããGCã«ãŒãã§ãã
- ã¹ã¿ãã¯
- éçïŒã°ããŒãã«ïŒãªããžã§ã¯ã
- ãã¡ã€ãã©ã€ãºå¯èœãªãªããžã§ã¯ã
- ã¢ã³ãããŒãžãçžäºéçšãªããžã§ã¯ãïŒCOMã«åå ããŠããCLR /ã¢ã³ãããŒãžãã³ãŒã«ïŒ
- ããã»ããµã¬ãžã¹ã¿
- ãªã³ã¯ãæã€ä»ã®CLR
ãã®å Žåãåèšã§3ã€ã®äžä»£ããããŸãã
- äžä»£0 ãã®äžä»£ã®ãªããžã§ã¯ãã®ã©ã€ããµã€ã¯ã«ã¯æçã§ãã éåžžãGen0ã¯ã¡ãœããã®æ¬äœã§äœæãããäžæå€æ°ãæããŸãã
- ãžã§ãã¬ãŒã·ã§ã³1 ã ãã®äžä»£ã®ã©ã€ããµã€ã¯ã«ãçãã§ãã ã©ã€ãã¿ã€ã ãäžéã®ãªããžã§ã¯ãïŒGen0ããGen2ã«ç§»åãããªããžã§ã¯ãïŒãå«ãŸããŸãã
- ãžã§ãã¬ãŒã·ã§ã³2 ã æã寿åœã®é·ããªããžã§ã¯ãã衚ããŸãã ãŸãã85,000ãã€ããè¶
ãããªããžã§ã¯ãã¯èªåçã«ã©ãŒãžãªããžã§ã¯ãããŒãã«åé¡ãããGen2ãšããŠããŒã¯ãããŸãã
åã»ã°ã¡ã³ãã®åæãµã€ãºïŒSOHãLOHïŒã¯ç°ãªããç¹å®ã®ãã·ã³ïŒéåžžã¯ãã¹ã¯ãããçšã«16 MBããµãŒããŒçšã«64 MBïŒã«äŸåããŸãã ããã¯
ä»®æ³ã¡ã¢ãªã§ããããšã«æ³šæããŠãã ãããã¢ããªã±ãŒã·ã§ã³ã¯äžè¬ã«5 MBã®
ç©çã¡ã¢ãªãå æã§ããŸãã
85,000ãã€ããè¶
ãããªããžã§ã¯ãã ãã§ãªããäžéšã®ã¿ã€ãã®é
åãLOHã«å
¥ããŸãã
ãã®ããã10.600èŠçŽ ïŒ85000/8ãã€ãïŒã®ãµã€ãºãæã€System.Doubleã®é
åã¯LOHã«åé¡ãããã¯ãã§ãã ãã ããããã¯ãã§ã«1000+ã®ãµã€ãºã§çºçããŠããŸãã
ãããŒãžããŒãå
ã®ãªããžã§ã¯ãã¯æ¬¡ã
ã«é
眮ãããŸããããã«ããã倿°ã®ãªããžã§ã¯ããåé€ããããšãæçåãçºçããå¯èœæ§ããããŸãã
ãã ãããã®åé¡ã解決ããããã«ãCLRã¯
åžžã« ïŒæåã®ã¡ã¢ãªç®¡çãé€ãïŒSmall Object Heapãæé©åããŸãã
ããã»ã¹ã¯æ¬¡ã®ãšããã§ããçŸåšã®ãªããžã§ã¯ãã空ãã¡ã¢ãªïŒèªåçã«æ¶ããããŒãå
ã®ã¹ããŒã¹ïŒã«ã³ããŒãããŸãã
ãããã£ãŠãæå°ã®ã¡ã¢ãªæ¶è²»ãéæãããŸãããããã«ã¯äžå®ã®ããã»ããµæéãå¿
èŠã§ãã ãã ããããã¯å¿é
ããªãã§ãã ããã Gen0ãGen1ãªããžã§ã¯ãã®å Žåãé
å»¶ã¯ããã
1 msã§ãã
ã©ãŒãžãªããžã§ã¯ãããŒãã¯ã©ãã§ããïŒ æé©åãããããšã¯ãããŸããïŒã»ãšãã©ãããŸããïŒã ããã«ã¯æéãããããã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸãã ãã ããããã¯ãCLRãçç±ããªãã¡ã¢ãªãæ¶è²»ãå§ããŠãããšããæå³ã§ã¯ãããŸããã Full-GCïŒGen0ãGen1ãGen2ïŒã®éãã·ã¹ãã ã¯ãŸã OSã¡ã¢ãªãè¿ããLOHãããã§ã«æ»ãã§ããïŒãŸãã¯SOHãæé©åããïŒãªããžã§ã¯ãããèªèº«ãè§£æŸããŸãã
ãŸããCLRã¯ãããšãã°SOHã®ããã«LOHã«æ°ãããªããžã§ã¯ããæ¬¡ã
ã«é
眮ããã ãã§ãªããFull-GCãåŸ
ããã«ç©ºãã¡ã¢ãªã®å Žæã«ãé
眮ããŸãã
GC.CollectïŒïŒã¡ãœããã®åŒã³åºããé€ããGCã®èµ·åã¯æ±ºå®çã§ã¯ãããŸããã
ãã ãããããäºæž¬ã§ããããããã®åºæºããŸã ãããŸãïŒä»¥äžã«ç€ºãæ¡ä»¶ã¯ããããã®ãã®ã§ãããCLRèªäœãã¢ããªã±ãŒã·ã§ã³ã®åäœã«é©å¿ããããšãèŠããŠããå¿
èŠããããŸããã¬ããŒãžã³ã¬ã¯ã¿ãŒã®çš®é¡ã«ãã£ãŠç°ãªããŸãïŒã
- Gen0 256 KBã«å°éãããš
- Gen1 Generationã2 MBã«éãããšã
- 10 MB Gen2äžä»£ã«å°é
ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã¯ãã·ã¹ãã ã®ã¡ã¢ãªãäžè¶³ãããšãã«ãéå§ãããŸãã CLRã¯ããã®ããã«Win32颿°
CreateMemoryResourceNotificationããã³
QueryMemoryResourceNotificationã䜿çšããŸãã
ã¡ã¢ãªãæäœããéã®ãã1ã€ã®ãã€ã³ãã¯ã管çãããŠããªããªãœãŒã¹ã®äœ¿çšã§ãã
ãªããªã ã¢ã³ãããŒãžãªãœãŒã¹ã«ã¯ããã®å¯¿åœã«é¢ä¿ãªãä»»æã®ãªããžã§ã¯ããå«ããããšãã§ããGCã¯æ±ºå®è«çã§ã¯ãªãããããããã®ç®çã®ããã®ãã¡ã€ãã©ã€ã¶ãŒããããŸãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããšãCLRã¯ãã¡ã€ãã©ã€ã¶ãŒã§åãæ€çŽ¢ããéåžžã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ããããããé€å€ããŸãïŒãã ããããã¯ãªããžã§ã¯ããäžä»£ã«é¢é£ä»ããããŠããªããšããæå³ã§ã¯ãããŸããïŒã
GCãçµäºãããšããã¡ã€ãã©ã€ãºããããªããžã§ã¯ãã¯å¥ã®ã¹ã¬ããã§åŠçãããŸãïŒFinalizeã¡ãœãããåŒã³åºããŸãïŒã
Disposeãã¿ãŒã³ã®å®è£
äŸïŒ
class Foo : IDisposable { private bool _disposed; ~Foo() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) {
次ã«ã.NET Frameworkã§å©çšå¯èœãªGCèªäœãæ€èšããŸãã
.NET 4.0ããåã¯ã2ã€ã®ãµãŒããŒã¢ãŒããšã¯ãŒã¯ã¹ããŒã·ã§ã³ã¢ãŒãã䜿çšå¯èœã§ããã
ã¯ãŒã¯ã¹ããŒã·ã§ã³ã¢ãŒã-GCã¯ã¯ã©ã€ã¢ã³ããã·ã³ã§åäœããããã«æé©åãããŠããŸãã 圌ã¯ããã»ããµãããŸãããŒãããªãããã«ããUIãåããã¢ããªã±ãŒã·ã§ã³ã®é
å»¶ãæå°éã«æããŠäœæ¥ããŸãã ãã©ã¬ã«ãšåæã®2ã€ã®ã¢ãŒãã§äœ¿çšã§ããŸãã
䞊åã¢ãŒãã§ã¯ãGCã¯Gen2äžä»£ã®å¥ã®ã¹ã¬ããã§ïŒéåžžã®åªå
é äœã§ïŒèµ·åãããŸãããäžæçãªäžä»£ã®äœæ¥ã¯ãããã¯ãããŸãïŒæ°ãããªããžã§ã¯ãã®å²ãåœãŠã¯äžå¯èœã§ããã¹ãŠã®ã¹ã¬ãããäžæãããŸãïŒã
ã¢ããªã±ãŒã·ã§ã³ã®ç©ºãã¡ã¢ãªãéåžžã«å€ãïŒ!!!ïŒå ŽåãSOHã¯ã³ã³ãã¯ãã«ãªããŸããïŒGCã¯ã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ã®ããã«ã¡ã¢ãªãç ç²ã«ããŸãïŒã
ãããã£ãŠãã¯ãŒã¯ã¹ããŒã·ã§ã³ã¢ãŒãã¯GUIã¢ããªã±ãŒã·ã§ã³ã«æé©ã§ãã
ããã«ããµãŒããŒåŽGCã䜿çšããå¿
èŠãããå Žåã¯ã次ã®ããã«æå¹ã«ããããšãã§ããŸãã
<configuration> <runtime> <gcServer enabled="true"/> </runtime> </configuration>
æ€èšŒã®ããã«ãã³ãŒãã§GCSettings.IsServerGCããããã£ã䜿çšã§ããŸãã
Workstation Concurrent GCã匷å¶çã«ã·ã£ããããŠã³ããã«ã¯ã次ã®ãã©ã¡ãŒã¿ãŒã䜿çšããŸãã
<configuration> <runtime> <gcConcurrent enabled="false"/> </runtime> </configuration>
ããã©ã«ãã§ã¯ãã¯ãŒã¯ã¹ããŒã·ã§ã³GCã®ãã©ã¬ã«ã¢ãŒããæå¹ã«ãªã£ãŠããŸãã ãã ããããã»ããµãã·ã³ã°ã«ã³ã¢ã®å ŽåãGCã¯èªåçã«åæã¢ãŒãã«ãªããŸãã
ãµãŒããŒGCãæ€èšããŠãã ããã
ãµãŒããŒGCã¯ããããŒãžããŒããã»ã°ã¡ã³ãã«åå²ããŸããã»ã°ã¡ã³ãã®æ°ã¯
è«çããã»ããµã®æ°ã«çããã1ã€ã®ã¹ã¬ããã䜿çšããŠåã»ã°ã¡ã³ããåŠçããŸãã
ç°¡åãªã¡ã¢ïŒè«çããã»ããµã¯å¿
ãããç©çããã»ããµã«å¯Ÿå¿ãããšã¯éããŸããã è€æ°ã®ç©çããã»ããµïŒã€ãŸããè€æ°ã®ãœã±ããïŒãšãã«ãã³ã¢ããã»ããµãåããã·ã¹ãã ã¯ãOSã«å€ãã®è«çããã»ããµãæäŸããŸãããŸããã«ãŒãã«ïŒ!!!ïŒã¯ãè€æ°ã®è«çããã»ããµã«ããããšãã§ããŸãïŒããšãã°ãIntelãã€ããŒã¹ã¬ããã£ã³ã°ãã¯ãããžã䜿çšããå ŽåïŒã
ãŸããäž»ãªéãã®1ã€ã¯ã.NET Framework 3.5 SP1ïŒ3ã€ã®ã¢ãŒãã§æ§æãããïŒã§äœ¿çšå¯èœãª
GCSettings.LatencyModeããããã£ã§ãã
ããã©ã«ãã§ã¯ãWorkstation Concurrent GCã®LatencyModeã¯InteractiveãServer-Batchã«èšå®ãããŠããŸãã
LowLatencyããããŸãããããã䜿çšãããšOutOfMemoryExceptionãçºçããå¯èœæ§ããããŸãã ãã®GCã¢ãŒãã§ã¯ããã«ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã¯ãã¡ã¢ãªè² è·ãé«ãå Žåã«ã®ã¿çºçããŸãã ãŸãããµãŒããŒGCã«å¯ŸããŠæå¹ã«ããããšã¯ã§ããŸããã
ããããšã€ã³ã¿ã©ã¯ãã£ãã®éãã¯äœã§ããïŒ
ãªããªã ãµãŒããŒGCã¯ããããŒãžããŒããè€æ°ã®ã»ã°ã¡ã³ãïŒåã»ã°ã¡ã³ããåå¥ã®è«çããã»ããµã«ãµãŒãã¹ããïŒã«åå²ãã䞊åã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã®å¿
èŠæ§ããªããªããŸãïŒå¥ã®è«çããã»ããµã§å¥ã®ã¹ã¬ãããèµ·åãããå ŽåïŒã ãã®ã¢ãŒãã¯ãgcConcurrentãã©ã¡ãŒã¿ãŒã匷å¶çã«ãªãŒããŒã©ã€ãããŸãã gcConcurrentã¢ãŒããæå¹ã«ãªã£ãŠããå Žåããããã¢ãŒãã§ã¯ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã䞊è¡ããŠè¡ãããªããªããŸãïŒ!!!ïŒã ãããã¯ãã¯ãŒã¯ã¹ããŒã·ã§ã³ã§ã®é䞊åã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãšåçã§ãã ãã®ã¢ãŒãã䜿çšããå Žåã倧éïŒ!!!ïŒã®ããŒã¿ã®åŠçãç¹åŸŽçã§ãã
GCLatencyModeã®å€ã倿ŽãããšãçŸåšå®è¡äžã®ã¹ã¬ããã«åœ±é¿ããããšã«æ³šæããŠãã ãããã€ãŸããã©ã³ã¿ã€ã èªäœãšã¢ã³ãããŒãžã³ãŒãã«åœ±é¿ããŸãã
ãããŠä»¥æ¥ ã¹ã¬ããã¯ããŸããŸãªè«çããã»ããµã§å®è¡ã§ãããããGCã¢ãŒãã®å³æå€æã®ä¿èšŒã¯ãããŸããã
ããããå¥ã®ã¹ã¬ããããã®å€ã倿Žãããå Žåã¯ã©ãã§ãããã ãããŠã100ã®ã¹ã¬ãããããå Žåã¯ã©ããªããŸããïŒ
ãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã«åé¡ãçããŠãããšæããŠããŸããïŒ ç¹ã«CLRã®å Žå-çµå±ã®ãšãããã¢ããªã±ãŒã·ã§ã³ã³ãŒãã§ã¯ãªãç°å¢èªäœã§äŸå€ãã¹ããŒãããå¯èœæ§ããããŸãã
ãã®ãããªå Žåã®ããã«ãå¶çŽä»ãå®è¡é åïŒCERïŒããããŸã-ãã¹ãŠã®äŸå€ïŒåæããã³éåæã®äž¡æ¹ïŒã®åŠçã®ä¿èšŒã
CERãšããŠããŒã¯ãããã³ãŒããããã¯ã§ã¯ãã©ã³ã¿ã€ã ã¯äžéšã®éåæäŸå€ãã¹ããŒã§ããŸããã
ããšãã°ãThread.AbortïŒïŒãåŒã³åºããšããCERã§å®è¡ãããã¹ã¬ããã¯ãCERã§ä¿è·ãããã³ãŒãã®å®è¡ãå®äºãããŸã§äžæãããŸããã
ãŸããCLRã¯åæåäžã«CERãæºåããŠãã¡ã¢ãªãäžè¶³ããŠããŠãåäœãä¿èšŒããŸãã
ã³ãŒãã®å€§ããªã»ã¯ã·ã§ã³ã«ã¯CERã䜿çšããªãããšããå§ãããŸãã ãã®çš®ã®ã³ãŒãã«ã¯ããã¯ã·ã³ã°ãä»®æ³ã¡ãœããã®åŒã³åºãããªãã¬ã¯ã·ã§ã³ã«ããã¡ãœããã®åŒã³åºããMonitor.Enterã®äœ¿çšãªã©ãå€ãã®å¶éããããŸãã
ãããããã®åé¡ãæãäžããŠãLatencyModeã¢ãŒããå®å
šã«åãæ¿ããæ¹æ³ãèŠãŠã¿ãŸãããã
var oldMode = GCSettings.LatencyMode; System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); try { GCSettings.LatencyMode = GCLatencyMode.Batch;
ããŠã.NETã§ã®GCã®äœæ¥ã®äž»èŠéšåã«ã€ããŠã¯æ¢ã«æ€èšããŸããã質åã¯ãããŸãããïŒ
絶察ã«éãïŒ æ°ã«ãªããŸããã§ãããïŒ
ããŒã...æ¬åœã«ã¯ããªãäžä»£ã«æ°ãããªããžã§ã¯ããå²ãåœãŠãããšãã§ããªããšããåé¡ã¯èå³ããããŸããã§ãããïŒ
ãããŠãããã«.NETã³ãã³ãããããŸã-ã¯ã:)
ããã§ãã¯ãŒã¯ã¹ããŒã·ã§ã³ã¢ãŒãçšã®æ°ããããã¯ã°ã©ãŠã³ãGCïŒ.NET 4.5ããã³ãµãŒããŒããéå§ïŒã«ã¢ã¯ã»ã¹ã§ããŸãã
ãã®äœæã®ç®çã¯ãFull-GCãç¹ã«Gen2ã®é
å»¶ãæžããããšã§ããã
ããã¯ã°ã©ãŠã³ãGCã¯ãã³ã³ã«ã¬ã³ãGCãšåãã§ããã1ã€ã®äŸå€ããããŸã-Full-GCã§ã¯ãæ°ãããªããžã§ã¯ãã®å²ãåœãŠã«å¯ŸããŠäžæçãªäžä»£ã¯ãããã¯ãããŸããã
Gen2ãšLOHã®åŠçã¯éåžžã«é«äŸ¡ã§ããããšã«åæããŸãã ãããŠãGen0ãGen1ã®ãããã¯-ã€ãŸã ã¢ããªã±ãŒã·ã§ã³ã®éåžžã®åäœã«ãããé
å»¶ãçºçããå ŽåããããŸãïŒç¹å®ã®ç¶æ³ã§ïŒã
æ°ããGCã§å¯ŸåŠãããå¥ã®åé¡ã¯ã管çããŒãã®ãµã€ãºã«éãããšæ°ãããªããžã§ã¯ããå²ãåœãŠãéã®é
å»¶ã§ãïŒ16 MB-ãã¹ã¯ãããã64-ãµãŒããŒïŒã

çŸåšããã®ç¶æ³ãé²ãããã«ãGen2ã®ããã¯ã°ã©ãŠã³ãã¹ã¬ããã ãã§ãªãããã©ã¢ã°ã©ãŠã³ãã¹ã¬ããïŒã¯ãããã©ã¢ã°ã©ãŠã³ãGCããããŸãïŒã¯äžæçãªäžä»£ã®æ»ãã ãªããžã§ã¯ããããŒã¯ããçŸåšã®äžæçãªäžä»£ãGen2ãšçµã¿åãããŸã.combiningã¯ã³ããŒãããå®äŸ¡ãªæäœã§ãïŒãããããããã¯ã°ã©ãŠã³ãã¹ã¬ããåŠçã«è»¢éããŸããããã«ãããæ°ãããªããžã§ã¯ãã«ã¡ã¢ãªãå²ãåœãŠãããšãã§ããŸãïŒããã¯ã°ã©ãŠã³ãGC Gen0ã§ã¯ãGen1ãGen2ã®GCæäœäžã«ãããã¯ãããªãããšãæãåºããŠãã ããïŒã

é
å»¶æ°ã®åæžã¯ã以äžã®ã°ã©ãã§æ¯èŒã§ããŸãã

âæåã¡ã¢ãªç®¡ç
CLRãç¹ã«CïŒã®æãè峿·±ãçããæ©èœã®1ã€ã¯ãæåã¡ã¢ãªç®¡çã§ãã ãã€ã³ã¿ãŒãæäœããŸãã
äžè¬ã«ãããã¯.NETã®3çªç®ã®ã¿ã€ã-ãã€ã³ã¿ãŒã¿ã€ãã§ãã ããã¯ãä»»æã®å€ã¿ã€ãã®ç¹å®ã®ã€ã³ã¹ã¿ã³ã¹ã®DWORDã¢ãã¬ã¹ã衚ããŸãã ã€ãŸã åç
§ã¿ã€ãã¯å©çšã§ããŸããã
ããããã¢ã³ãããŒãžã³ãŒãã䜿çšããããšãã§ããŸãã
ãã®ãããªç®çã®ããã«ãSystem.Runtime.InteropServices.GCHandleæ§é ãäœæãããŸãã-åºå®ã¢ãã¬ã¹ãæã€ãªããžã§ã¯ãã¯ãã¢ã³ãããŒãžã¡ã¢ãªãããããŒãžãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ããæ©èœãæäŸããŸãã
GCHandleã®å ŽåãCLRã¯AppDomainããšã«åå¥ã®ããŒãã«ã䜿çšããŸãã
GCHandleã¯ãGCHandle.FreeïŒïŒãåŒã³åºãããããAppDomainãã¢ã³ããŒãããããšç Žæ£ãããŸãã
äœæããã«ã¯ãGChandle.AllocïŒïŒã¡ãœããã䜿çšããŸãã
次ã®å²ãåœãŠã¢ãŒãã䜿çšã§ããŸãã
- æ®é
- 匱ã
- 匱ããã©ãã¯ã®åŸ©æŽ»
- ãã³çã
GCHandle-
MSDNã«é¢ãã詳现ã
æåã®ã¡ã¢ãªåŠçãå¿
èŠãªå Žåãå°ããŸããïŒ
ããšãã°ããã€ãã®é
åãã³ããŒããŸãã
static unsafe void Copy(byte[] source, int sourceOffset, byte[] target, int targetOffset, int count) { fixed (byte* pSource = source, pTarget = target) {
, GC SOH? SOH.
( .NET â ). â .
â || .NET 4.0+
, .NET 2.0, .NET 4.0.

[
.NET Framework Versions and Dependencies ]
.NET 1.1, , , 2.0.
.NET 3.5 CLR 2.0, 2.0 + 3.0 + 3.5. , , .. .
.NET 4.0 :
CLR 2.0 CLR 4.0 :
<configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> </configuration>
:
<runtime> <NetFx40_LegacySecurityPolicy enabled="true"/> </runtime>
SEH- , :
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true"/> </runtime> </configuration>
, :
<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup>
, .NET 4.0.
â || FastCall
, JIT â , VC++, â FastCall.
, ECX, EDX 2 .
x64 â RCX, RDX, R8, R9.
?
, - ( , ).
class Program { static void Main(string[] args) { int startIndex = 1; int endIndex = 2; int x = 3; int y = 5; int result = Compute(startIndex, endIndex, x, y); Console.WriteLine(result); } public static int Compute(int startIndex, int endIndex, int x, int y) { int result = 0; for (int i = startIndex; i < endIndex; i++) { result += x * startIndex + y * endIndex; } return result; } }
startIndex endIndex ECX, EDX, (x, y) .
â .
CTRL + D, R
.

CTRL + ALT + D
.

, !
ãæž
èŽããããšãããããŸããïŒ