Python for the .NET developer Transcripts
Chapter: Memory management in Python
Lecture: Memory management in .NET

Login or purchase this course to watch this video and the rest of the course contents.
0:00 Let's begin with a high-level overview
0:02 of how memory management and the garbage collector works
0:05 in C# and really in .NET.
0:08 As I said at the onset
0:09 there's no explicit memory management necessary
0:12 for the most part in .NET and C#.
0:16 There's an unsafe mode where you can work with pointers
0:18 and pin references and things like that
0:21 but that keyword is extremely rare in the language
0:24 and people almost never use it.
0:25 So let's just assume explicit memory management
0:28 not really a thing, we're just going to let
0:30 the garbage collector manage memory for us.
0:32 Now, one of the really important distinctions in .NET
0:35 is between the different types of variables
0:38 or values you can store.
0:41 Data is broken into two categories.
0:43 Most things are reference types
0:45 they're allocated on the heap
0:47 they're dynamically allocated
0:49 their references can be passed around
0:52 they can be allocated one place
0:53 and be kept alive by another.
0:55 On the other side we have value types.
0:58 These are mostly like numbers and booleans and stuff
1:01 these are passed by value, they're allocated on the stack
1:05 and they're not kept alive
1:06 they're not even subject to garbage collection at all.
1:09 So value types on the stack, reference types on the heap.
1:13 When a function returns, the stack is destroyed
1:16 the value types are gone.
1:17 So you don't really have to think about
1:18 this idea of value types
1:20 for this memory management story, right?
1:22 It's like, it's a different thing.
1:24 So we're only focused on the reference types.
1:27 Now, .NET has a garbage collector
1:29 it's going to run when memory pressure is high.
1:32 Well, what defines memory pressure?
1:33 Mostly it's when the generation 0 gets full, right?
1:38 It just going to keep allocating at generation 0.
1:40 Generation 0 is small, it's like 16 megabytes
1:43 or something, potentially even smaller
1:44 I don't exactly remember the exact numbers
1:46 and they change a little bit over time, I suspect.
1:49 But, when enough allocations have happened
1:52 it's going to run depending on how it's run previously
1:55 how much memory pressure there is
1:57 it might do a small collection, like Gen 0
1:58 or it might do a full collection, a Gen 2 collection.
2:01 When there's enough memory pressure
2:03 then the garbage collector decides
2:05 it's time to kick in, go do it's thing
2:07 and it's going to run one of these collections.
2:09 The algorithm that uses
2:11 what's called a mark-and-sweep algorithm.
2:13 So the garbage collector doesn't actually go around
2:15 and collect garbage.
2:16 What it does is it goes around and find objects
2:18 that are still around and then it assumes stuff
2:21 that is in the gaps that must have been garbage
2:24 so we're going to forget about it.
2:25 But it doesn't actually track the garbage
2:26 it actually only tracks the live things.
2:29 As I indicated before there's actually three generations
2:31 Gen 0, 1 and 2.
2:33 And as objects survive, a collection they get promoted
2:36 from like 0 to 1 and 1 to 2 and so on.
2:39 There's a few edge cases that don't quite follow that rule
2:41 like large objects and so on.
2:43 In general, things start out in a probably trash
2:47 bin called Gen 0, and then once they survive that
2:50 they go to Gen 1 and Gen 2
2:52 and there's fewer collections as you get up
2:54 in the higher bits.
2:55 There's a lot more memory that has to be looked at
2:57 in order to do a Gen 2 collection than say a Gen 0.
3:00 A really important part
3:01 of garbage collection type of algorithms
3:04 is that memory management
3:05 and memory clean up is non-deterministic.
3:08 That means I could run almost the same program
3:11 multiple times and under very slight variations
3:14 it might actually behave differently, right?
3:16 There might be different pauses based on
3:19 maybe you go to a different size of input
3:21 but to the same algorithm.
3:23 Timing and order of when these garbage collections happen
3:26 is non-deterministic, usually you don't care
3:29 usually they're fast, but certain circumstances
3:32 where you're doing real-time type programing
3:34 or something like that
3:35 this potentially could cause some trouble.
3:38 Finally, a very nice feature of .NET's garbage collector
3:42 is that it compacts memory.
3:45 So, I've allocated a bunch of objects.
3:47 They're likely, if they're allocated at the same time
3:49 to be related to each other.
3:50 And the stuff that was potentially allocated
3:52 in between them
3:53 when it becomes garbage the memory is actually moved
3:56 and squished down like an accordion back together
3:59 and the stuff that was allocated and survived
4:02 next to each other is even closer potentially
4:04 than it was before. This can help a lot with memory fragmentation
4:07 and it's a pretty cool feature of .NET.
4:09 So, hopefully this gives you a good sense of .NET's
4:12 memory management story
4:14 this is generally how things work over there.