Exploring .NET memory management - JetBrains webinar

46
Exploring .NET's Memory Management webinar hosted by JetBrains dotMemory team Presented by Maarten Balliauw - @maartenballiauw

Transcript of Exploring .NET memory management - JetBrains webinar

Page 1: Exploring .NET memory management - JetBrains webinar

Exploring .NET's Memory Managementwebinar hosted by JetBrains dotMemory team

Presented by Maarten Balliauw - @maartenballiauw

Page 2: Exploring .NET memory management - JetBrains webinar

Who am I? Maarten Balliauw Antwerp, Belgium Developer Advocate, JetBrains Focus on web ASP.NET MVC, Azure, SignalR, ... Former MVP Azure & ASPInsider Big passion: Azure http://blog.maartenballiauw.be @maartenballiauw

Page 3: Exploring .NET memory management - JetBrains webinar

Agenda Garbage Collector Helping the GC Allocations & hidden allocations Strings Exploring the heap

Page 4: Exploring .NET memory management - JetBrains webinar

Garbage Collector

Page 5: Exploring .NET memory management - JetBrains webinar

.NET runtime Manages execution of programs Just-in-time compilation: Intermediate Language (IL) ->machine

code Type safety Exception handling Security Thread management Memory management Garbage collection (GC)

Page 6: Exploring .NET memory management - JetBrains webinar

Memory management and GC Virtually unlimited memory for our applications Big chunk of memory pre-allocated Runtime manages allocation in that chunk Garbage Collector (GC) reclaims unused memory, making it available again

Page 7: Exploring .NET memory management - JetBrains webinar

.NET memory management 101 Memory allocation Objects allocated in “managed heap” (big chunk of memory) Allocating memory is fast, it’s just adding a pointer Some unmanaged memory is also consumed (not GC-ed) .NET CLR, Dynamic libraries, Graphics buffer, …

Memory release or “Garbage Collection” (GC) Generations Large Object Heap

Page 8: Exploring .NET memory management - JetBrains webinar

.NET memory management 101 Memory allocation Memory release or “Garbage Collection” (GC) GC releases objects no longer in use by examining application roots GC builds a graph of all the objects that are reachable from these roots Object unreachable? Remove object, release memory, compact heap Takes time to scan all objects! Generations Large Object Heap

Page 9: Exploring .NET memory management - JetBrains webinar

.NET memory management 101 Memory allocation Memory release or “Garbage Collection” (GC) Generations

Large Object Heap

Generation 0 Generation 1 Generation 2Short-lived objects (e.g. Local variables)

In-between objects Long-lived objects (e.g. App’s main form)

Page 10: Exploring .NET memory management - JetBrains webinar

.NET memory management 101 Memory allocation Memory release or “Garbage Collection” (GC) Generations Large Object Heap (LOH) Special segment for large objects (>85KB) Collected only during full garbage collection Not compacted (by default) Fragmentation can cause OutOfMemoryException

Page 11: Exploring .NET memory management - JetBrains webinar

The .NET garbage collector When does it run? Vague… But usually: Out of memory condition – when the system fails to allocate or re-allocate

memory After some significant allocation – if X memory is allocated since previous GC Failure of allocating some native resources – internal to .NET Profiler – when triggered from profiler API Forced – when calling methods on System.GC Application moves to background GC is not guaranteed to run http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx http://blogs.msdn.com/b/abhinaba/archive/2008/04/29/when-does-the-net-compact-framework-garbage-collector-run.aspx

Seal of Geekyness!Here’s the GC source code.

Page 12: Exploring .NET memory management - JetBrains webinar

The .NET garbage collector Runs very often for gen0 Short-lived objects, few references, fast to clean Local variable Web request/response Higher generation Usually more references, slower to clean GC pauses the running application to do its thing Usually short, except when not… Background GC (enabled by default) Concurrent with application threads May still introduce short locks/pauses, usually just for one thread

Page 13: Exploring .NET memory management - JetBrains webinar

Helping the GC, avoid pauses Optimize allocations (but don’t do premature optimization – measure!)

Don’t allocate at all Make use of IDisposable / using statement Clean up references, giving the GC an easy job Finalizers Beware! Moved to finalizer queue -> always gen++ Weak references Allow the GC to collect these objects, no need for checks

Page 14: Exploring .NET memory management - JetBrains webinar

Helping the GCDEMOhttps://github.com/maartenba/memory-demos

Page 15: Exploring .NET memory management - JetBrains webinar

Allocations

Page 16: Exploring .NET memory management - JetBrains webinar

When is memory allocated? Not for value types (int, bool, struct, decimal, enum, float, byte, long, …)

Allocated on stack, not on heap Not managed by garbage collector For reference types When you new When you ""

Page 17: Exploring .NET memory management - JetBrains webinar

Hidden allocations! Boxing! Put and int in a box Take an int out of a box

Lambda’s/closures Allocate compiler-generated

DisplayClass to capture state Params arrays And more!

int i = 42;

// boxing - wraps the value type in an "object box"// (allocating a System.Object)object o = i;

// unboxing - unpacking the "object box" into an int again// (CPU effort to unwrap)int j = (int)o;

Page 18: Exploring .NET memory management - JetBrains webinar

How to find them? Experience Intermediate Language (IL) Profiler “Heap allocations viewer” ReSharper Heap Allocations Viewer plugin  Roslyn’s Heap Allocation Analyzer

Don’t do premature optimization – measure!

Page 19: Exploring .NET memory management - JetBrains webinar

Hidden allocationsDEMOhttps://github.com/maartenba/memory-demos

ReSharper Heap Allocations Viewer plugin Roslyn’s Heap Allocation Analyzer

Page 20: Exploring .NET memory management - JetBrains webinar

Don’t optimize what should not be optimized.

Page 21: Exploring .NET memory management - JetBrains webinar

Measure! We know when allocations are done... ...but perhaps these don’t matter.

Measure! How frequently are we allocating? How frequently are we collecting? What generation do we end up on? Are our allocations introducing pauses?

www.jetbrains.com/dotmemory (and www.jetbrains.com/dottrace)

Page 22: Exploring .NET memory management - JetBrains webinar

Always Be MeasuringDEMOhttps://github.com/maartenba/memory-demos

Page 23: Exploring .NET memory management - JetBrains webinar

Object pools / object re-use If it make sense, re-use objects Fewer allocations, fewer objects for the GC to scan Fewer memory traffic that can trigger a full GC Object pooling - object pool pattern Create a pool of objects that can be cleaned and re-used https://www.codeproject.com/articles/20848/c-object-pooling “Optimize ASP.NET Core” -

https://github.com/aspnet/AspLabs/issues/3

Page 24: Exploring .NET memory management - JetBrains webinar

Garbage Collector & Allocations GC is optimized for high memory traffic in short-lived objects Use that knowledge! Don’t fear allocations! Don’t optimize what should not be optimized… GC is the concept that makes .NET / C# tick – use it! Know when allocations happen GC is awesome Gen2 collection that stop the world not so much… Measure!

Page 25: Exploring .NET memory management - JetBrains webinar

Strings

Page 26: Exploring .NET memory management - JetBrains webinar

Strings are objects .NET tries to make them look like a value type, but they are a reference type

Read-only collection of char Length property A bunch of operator overloading Allocated on the managed heapvar a = new string('-', 25);

var b = "Hello, World!";

var c = httpClient.GetStringAsync("http://blog.maartenballiauw.be");

Page 27: Exploring .NET memory management - JetBrains webinar

Measuring string allocationsDEMOhttps://github.com/maartenba/memory-demos

Page 28: Exploring .NET memory management - JetBrains webinar

String duplicates Any .NET application has them (System.Globalization duplicates quite a few)

Are they bad? .NET GC is fast for short-lived objects, so meh. Don’t waste memory with string duplicates on gen2 (but: it’s okay to have strings there)

Page 29: Exploring .NET memory management - JetBrains webinar

String literals Are all strings on the heap? Are all strings duplicated?

var a = "Hello, World!";var b = "Hello, World!";

Console.WriteLine(a == b);Console.WriteLine(Object.ReferenceEquals(a, b));

Prints true twice. So “Hello World” only in memory once?

Page 30: Exploring .NET memory management - JetBrains webinar

Portable Executable (PE) #UserStringsDEMOhttps://github.com/maartenba/memory-demos

Page 31: Exploring .NET memory management - JetBrains webinar

String literals in #US Compile-time optimization Store literals only once in PE header metadata stream ECMA-335 standard, section II.24.2.4

Reference literals (IL: ldstr)var a = Console.ReadLine();var b = Console.ReadLine();

Console.WriteLine(a == b);Console.WriteLine(Object.ReferenceEquals(a, b)); String interning to the rescue!

Page 32: Exploring .NET memory management - JetBrains webinar

String interning Store (and read) strings from the intern pool Simply call String.Intern when “allocating” or reading the string Scans intern pool and returns reference

var url = string.Intern("http://blog.maartenballiauw.be");

var stringList = new List<string>();for (int i = 0; i < 1000000; i++){ stringList.Add(url);}

Page 33: Exploring .NET memory management - JetBrains webinar

String interning caveats Why are not all strings interned by default? CPU vs. memory Not on the heap but on intern pool No GC on intern pool – all strings in memory for AppDomain lifetime! Rule of thumb Lot of long-lived, few unique -> interning good Lot of long-lived, many unique -> no benefit, memory growth Lot of short-lived -> trust the GC Measure!

Page 34: Exploring .NET memory management - JetBrains webinar

Exploring the heapfor fun and profit

Page 35: Exploring .NET memory management - JetBrains webinar

How would you do it... Build a managed type system, store in memory, CPU/memory friendly

Probably: Store type info (what’s in there, what’s the offset of fieldN, …) Store field data (just data) Store method pointers (“who you gonna call?”) Inheritance information

Page 36: Exploring .NET memory management - JetBrains webinar

Stuff on the Stack

Page 37: Exploring .NET memory management - JetBrains webinar

Stuff on the Managed Heap

(scroll down for more...)

Page 38: Exploring .NET memory management - JetBrains webinar

IT is just mapping mappings. Pointer to an “instance” Instance Pointer to Runtime Type Information (RTTI) Field values (which can be pointers in turn) RunTime Type Information Interface addresses Instance method addresses Static method addresses …

Page 39: Exploring .NET memory management - JetBrains webinar

Theory is nice... Microsoft.Diagnostics.Runtime (ClrMD)

“ClrMD is a set of advanced APIs for programmatically inspecting a crash dump of a .NET program much in the same way that the SOS Debugging Extensions (SOS) do. This allows you to write automated crash analysis for your applications as well as automate many common debugger tasks. In addition to reading crash dumps ClrMD also allows supports attaching to live processes.”

Maarten’s definition: “LINQ-to-heap”

Page 40: Exploring .NET memory management - JetBrains webinar

ClrMD introductionDEMOhttps://github.com/maartenba/memory-demos

Page 41: Exploring .NET memory management - JetBrains webinar

String duplicatesDEMOhttps://github.com/maartenba/memory-demos

Page 42: Exploring .NET memory management - JetBrains webinar

“Path to root”(why is my object kept in memory)DEMOhttps://github.com/maartenba/memory-demos

Page 43: Exploring .NET memory management - JetBrains webinar

Conclusion

Page 44: Exploring .NET memory management - JetBrains webinar

Conclusion Garbage Collector (GC) optimized for high memory traffic + short-lived objects

Don’t fear allocations! But beware of gen2 “stop the world” String interning when lot of long-lived, few unique Don’t optimize what should not be optimized… Measure! Using a profiler/memory analysis tool ClrMD to automate inspections dotMemory Unit to profile unit tests

Blog series: https://blog.maartenballiauw.be

Page 45: Exploring .NET memory management - JetBrains webinar

More Information• Learn more about dotMemory at

www.jetbrains.com/dotMemory• Send feedback to Twitter

@maartenballiauw & @dotmemory• Recording will be available at

www.youtube.com/JetBrainsTV• Follow us on Twitter @dotmemory

& blog blog.jetbrains.com/dotnet/

Page 46: Exploring .NET memory management - JetBrains webinar

Thanks for joining us!

See more screencasts and webinars at www.youtube.com/JetBrainsTV