Transcript Some Common Memory Problems
5 Misconceptions about .NET Memory Management Wednesday June 1 st 2011 Clive Tong and Andrew Hunter
www.red-gate.com/memoryprofiler
Your presenters
Developer, .NET Reflector Developer, ANTS Memory Profiler www.red-gate.com/memoryprofiler
The webinar
• Clive: 5 misconceptions about .NET memory management (30 mins) • Andrew: Q&A session for any questions to do with .NET memory • $50 Amazon voucher for the best answer to Clive’s question.
• Please type questions into your GoToWebinar chat box www.red-gate.com/memoryprofiler
Some Misconceptions About Memory Management in .NET
Clive Tong Red Gate Software www.red-gate.com/memoryprofiler
Five misconceptions
1 A garbage collector collects garbage 2 Doing lots of gen0 collections is bad 3 Performance counters are great for understanding what is happening 4 .NET doesn’t leak memory 5 All objects are treated the same www.red-gate.com/memoryprofiler
1) The Garbage Collectors Collect Garbage • The focus is really on the non-garbage • Most (young) objects die young • Designed to collect dead items without processing them individually • Note this is for generation 0 www.red-gate.com/memoryprofiler
A simple mutator
} { var collect = new List(); while(true) collect.Add(new A()); new A(); new A(); www.red-gate.com/memoryprofiler
Allocation in generation 0
Generation 0 After one iteration of the while loop As we go into the fourth iteration www.red-gate.com/memoryprofiler
Promote
No space, so copy
gen0 gen1 www.red-gate.com/memoryprofiler
Fix-up
gen0 gen1 www.red-gate.com/memoryprofiler
And recycle
gen0 gen1 www.red-gate.com/memoryprofiler
Observations
• Trick is that objects are allowed to move • Need to get to a safe point when pointers can be fixed • Additionally this allows quick allocation www.red-gate.com/memoryprofiler
Fast allocation
0:000> u 002c2020 mov mov eax,dword ptr [ecx+4] edx,dword ptr fs:[0E40h] add eax,dword ptr [edx+48h] cmp ja eax,dword ptr [edx+4Ch] 002c203b mov dword ptr [edx+48h],eax sub eax,dword ptr [ecx+4] mov dword ptr [eax],ecx ret 002c203b: jmp clr!JIT_NewFast (5cbded01) www.red-gate.com/memoryprofiler
Solution
• Avoid locking too frequently by having thread specific allocation buffers Thread 1 allocation buffer Thread 2 allocation buffer www.red-gate.com/memoryprofiler
And there is one other trick
• Use generations to focus attention – 0,1,2 • Need to track object references 0:000> u 5cbc2fb0 clr!JIT_WriteBarrierEAX: mov cmp dword ptr [edx],eax eax,271100Ch jb shr nop cmp jne ret clr!JIT_WriteBarrierEAX+0x17 (5cbc2fc7) edx,0Ah byte ptr [edx+0BD63E0h],0FFh clr!JIT_WriteBarrierEAX+0x1a (5cbc2fca) clr!JIT_WriteBarrierEAX+0x18: nop nop mov byte ptr [edx+0BD63E0h],0FFh ret www.red-gate.com/memoryprofiler
2) Lots of gen0 collections is bad
• We have covered this already • Time proportional to live data • Though with (fixed) overheads • Worse case double allocation www.red-gate.com/memoryprofiler
3) Performance counters are accurate
• Quick demonstration www.red-gate.com/memoryprofiler
Periodic measurements
• It’s important to remember that these are updated when a collection happens • No collection means the counter is stuck • The average value can be misleading www.red-gate.com/memoryprofiler
{ class Program static void Main(string[] args) { var accumulator = new List
www.red-gate.com/memoryprofiler
www.red-gate.com/memoryprofiler
www.red-gate.com/memoryprofiler
www.red-gate.com/memoryprofiler
www.red-gate.com/memoryprofiler
www.red-gate.com/memoryprofiler
4) .NET doesn’t leak
• It’s a question of definition • Old definition -Forgot to de-allocate after use -Lost the final pointer to some memory -Forgot your responsibilities www.red-gate.com/memoryprofiler
New definition
• Premature release was often fatal • Those days are gone (*) • The runtime is ultra-cautious • It’s difficult to have an effective cost model (*) except when you aggressively dispose www.red-gate.com/memoryprofiler
What makes things live longer?
• Runtime • User • Library • Compiler www.red-gate.com/memoryprofiler
Runtime
• Type of build • Having a debugger attached • Heuristics choosing when to collect higher generations • Finalizers www.red-gate.com/memoryprofiler
User
• Event handlers • Assigning temporary values to fields • Value only needed on some code paths www.red-gate.com/memoryprofiler
Library
• Caches without a lifetime policy • Data binding www.red-gate.com/memoryprofiler
• Closures
Compiler
www.red-gate.com/memoryprofiler
Closures
{ class Program private static Func
www.red-gate.com/memoryprofiler
5) All objects are created equal
• Copying takes a while • Need a better way to handle large objects • Resort to standard mark-and-sweep • No compact at the moment www.red-gate.com/memoryprofiler
Before
No copying during collection
After www.red-gate.com/memoryprofiler
Some observations
• No movement, so no fix-ups • Potential parallelism • But potential fragmentation • Only do when gen2 is collected • Temporary large objects don’t fit model • All blocks are touched www.red-gate.com/memoryprofiler
The problem of fragmentation
Before collection After collection Allocate block of this size: Next allocation www.red-gate.com/memoryprofiler
Conclusion
• There’s a lot going on inside your process heap • The only way to really understand what is going on is to use tools to visualize things www.red-gate.com/memoryprofiler
Q&A Session
• Please type your questions into the GoToWebinar box • We will read out your questions for Andrew to answer www.red-gate.com/memoryprofiler
Thank you!
• A recording of this webinar will be emailed to you tomorrow • Do get in touch!
www.red-gate.com/memoryprofiler