Python for the .NET developer Transcripts
Chapter: Memory management in Python
Lecture: Cycles and GC in Python demo
0:00 We saw how reference accounting worked
0:02 and that is beautiful if there are no cycles
0:05 that get abandoned.
0:06 Well, let's go and create some cycles and see what happens.
0:10 Alright, first of all I'm going to disable
0:11 the garbage collector because I want to
0:13 see that the cycles are a problem.
0:16 So we're going to create actually two doomed objects.
0:19 And remember, the dooms, they can take their friends so
0:22 this v2 is a friend of v1
0:27 but let's also reverse it
0:28 v1 has some friends, one of them is v2.
0:33 So, v1 points at v2 because of this
0:36 and v2 points at v1 because of that.
0:39 That will create the cycle right there.
0:42 Now, we'll go down here and we'll have a link to
0:45 both of these and let's change this to gc
0:49 and we'll put two counts in here. So, we'll do that in v2.
0:56 Let's also put the "Here's the End of the Method".
1:00 Now, nowhere in this method yet are
1:02 we actually dereferencing these objects.
1:05 Of course, we should get to the end of the method
1:07 and then potentially these things might get cleaned up.
1:10 We'll see. Go ahead and run it again, actually, let's up a
1:15 little bit more space so it's super obvious over here.
1:24 So, down here, notice we created doomed at 76.
1:29 We created doomed at forty and we asked and
1:32 they both have two references.
1:34 What are those two references? Well, it's the two
1:36 objects, the two variables, that we're looking at.
1:40 Here. Here. v1 and v2, these two are each adding a reference
1:46 but, then this one pointing back to v1 is
1:50 adding a second to v1 and this one pointing back
1:53 to v2 is adding a second to v2.
1:55 So, they each have two as we saw right there.
1:59 And notice we get all the way to the end of the method
2:02 then this cleans up. Let's add one more thing here
2:05 maybe in main. Let's print. Program Ending.
2:11 Just so you can see actually this is full on shutdown of
2:15 Python that's actually cleaning up these objects.
2:17 So, there nothing about the garbage collecting that is
2:19 actually happening here. Let's go and do a little bit
2:22 more here. Let's actually empty these things out.
2:26 So remember, before the reason these levels went down is
2:29 we actually... Well, let's stop pointing at those objects.
2:33 Let's see if that still works. So, v1 equals None.
2:38 And what the heck, let's do v2 equals none as well.
2:45 Put step two. That is going to lower the reference count
2:48 but it's going to go from two to one for each of them.
2:50 It's not going to be enough to get them to clean up.
2:54 Method ending. Boom! That's it.
2:57 It went from two, two to one, one.
3:00 That's not enough to get it to clean up.
3:02 Well, let's turn the garbage collector on
3:04 as in stop disabling it. I'll explicitly enable it.
3:08 Normally, you don't have to but just encase we were playing
3:10 with it above and it's disabled, let's just be really clear.
3:14 Well, that didn't do anything, right?
3:17 What happened? Unlike reference counting the gc is
3:20 not deterministic, it runs when it needs to run.
3:23 In order to see the gc signals we actually have to force it.
3:27 Just like you would have to do in .net
3:29 we'd have to say gc.collect. So, we can do the same here
3:32 to trigger that non deterministic clean up.
3:35 Then again, almost all the time we do not have cycles
3:38 reference counting is all we need
3:40 it'll clean everything up.
3:42 But when we don't, we can have this gc.
3:44 So, let's go down here and well put a print 3.
3:48 What goes before three, is a gc Collect.
3:54 That should go look for all the cycles and find this one.
3:56 It should clean them up. You should see doomed
3:58 the two doomed objects explaining their death
4:01 or predicting their death. And here you have it.
4:04 Alright, so we create that object. It's 2.
4:07 And then we dereference the variable that is one and
4:08 we still have one, one for the cycle.
4:11 But, then we call gc.collect, which goes and says
4:14 Here's the cycle, we're going to clean it up
4:16 let's detach that and start killing them off.
4:18 That's these two lines right here. And after the gc run
4:21 now it's zero, before the end of the method.
4:25 The first example we looked at reference counting
4:28 none of this was necessary. Reference counting
4:30 completely solved it, but once you get these cycles
4:33 that's the problem with reference counting.
4:34 Here we have Python's backup garbage collector kicking in
4:39 we kicked it to kick in, but it would kick in
4:42 on it's own eventually to clean up these cycles and
4:46 it works like a charm.
4:48 That's memory management in Python. In some ways it's a lot
4:51 simpler than .net with the reference counting and in others
4:54 with these cycles it's actually quite familiar.