Python Memory Management and Tips Transcripts
Chapter: Efficient data structures
Lecture: Data with cycles
0:00 Alright, let's write some code and create some cycles.
0:03 Now we sort of saw that in the GC section before,
0:05 but I want to start from scratch
0:07 so we have some nice, clean examples to work with,
0:09 and I'm gonna create another person class here that's similar,
0:12 but not the same as what we had before.
0:15 I'm just gonna paste this because we kind of did do this before.
0:19 Over here, we've got our person class.
0:21 It's created, it has a name.
0:24 It also auto generates its
0:25 id, and it has a list of friends.
0:27 It has this class method that will just auto-increment the
0:31 id, like 1, 2, 3 and so on,
0:33 and then finally, this class will tell you if it was cleaned up. This will
0:37 tell you that, yes, the cycle has been broken and the thing got cleaned
0:41 up, or, you know what? It didn't.
0:43 So, this is off to a good start.
0:45 The other thing that I'm gonna create is something to play with it.
0:48 I'll just call it "app_cycles" following my pattern that we're going to run things that are
0:52 named "app" and just trigger so I can hit the hockey to make it run and do our
0:56 fmain live template and boom,
0:58 we've got something to start from.
1:00 So what I wanna do is creates two people, have a person, and the name will
1:04 be Michael and a second person whose name is Sarah.
1:12 Okay, we got are two people here.
1:14 Now I want to let you play with it in different ways.
1:17 Sometimes they'll have cycles, sometimes they won't.
1:20 So I'm gonna ask a question.
1:21 I'll say if we'll ask the user "do you want cycles?"
1:28 We'll do like a "[y/n]?"
1:30 We'll say "If that is equal to yes,
1:35 then we're going to create some friends"
1:36 You know, we'll do that friend thing.
1:38 So p1, that's Michael, append p2,
1:42 and then we'll do the reverse like so.
1:45 So if they say yes, that's going to create a cycle.
1:48 And then we're going to zero them out here, like that
1:55 and we'll print out "program closing,
1:59 kthxbye". PyCharm thinks it's misspelled,
2:04 but no, no, K,
2:05 thanks, bye. That's a good thing.
2:06 And let's just flush it so we can
2:09 see stuff right away. Well,
2:12 let's go ahead and run this and we'll see if we have the cycle, this we've
2:15 kind of already looked at, but we're about to do something new here.
2:18 So we're going to see that if we do create the cycle,
2:21 this will not clean it up.
2:23 So the goodbye people, they're deleted will happen after this.
2:26 But if we say no, then they'll be cleaned up right here,
2:29 Yeah? let's do that. Did we will create a cycle?
2:32 Let's say no, and person was cleaned up.
2:35 Michael and Sarah. K, thanks,
2:37 bye. But this time, if we say yes,
2:39 the garbage collector does not have enough container object allocations.
2:43 Remember it needs 700 and we've done 2.
2:46 So that's not enough, so it's not going to trigger any sort of GC.
2:49 So the program exits and then basically as it goes out the door,
2:53 it does its final cleanup here.
2:55 Okay, so this is pretty interesting,
2:58 but I'd like the program itself to know if the cycle is detected. Now,
3:02 previously, we use that memutil thing that could tell us how many references were
3:06 pointing at a thing. But I want to introduce you to another idea that we
3:10 can play with. We could use the other one,
3:13 but I think we'll learn something here as well.
3:15 So I'm gonna create this thing called a "weak reference" and we can go and just
3:18 say "we're gonna create a weakref" by importing the library and we'll say "refer to
3:24 p1". What's gonna happen here is this is gonna retain something that maybe can
3:30 point to the object. But it can only point the object if it hasn't been
3:33 cleaned up. So previously we could say,
3:37 Well, "there was this thing out in memory and it created a cycle and it
3:41 didn't get cleaned up, but we only know that it used to be there".
3:45 You can't say "let me access it as if it were still alive" or revive it
3:49 In a sense, this weak reference will let us do that. So we'll do
3:53 the same here, and down at the bottom,
3:56 we'll do, I guess we'll say the things already closing or whatever,
4:00 but then we'll say "if we want to check
4:03 is this thing still around?" The way you do that with a weak reference is
4:06 You invoke it and it'll return p1 if it can,
4:10 if it's still around, otherwise it will return none. we'll say "if either these come
4:14 back with an object, we'll print..." This, we'll say, if either of them are alive,
4:36 we're gonna say "that's a cycle because nothing else points at it",
4:39 and we'll let people know, otherwise,
4:40 "no cycles found". So let's run it just one more time with our cool weak reference.
4:43 So, no. So they were cleaned up when we set them to none.
4:48 K, thanks, bye. No cycles found.
4:51 Let's run this again. Yes.
4:53 Create the cycle. Ah, cycles
4:55 found, cycles found. And then those things got cleaned up.
5:00 Here we are in this situation where we have these person classes,
5:04 they have friends. Most importantly,
5:06 we have these two things and they need to know about each other,
5:09 right? Michael needs to know about Sarah.
5:12 Sarah needs to know about Michael.
5:14 You might think, Well, that's just the way it is.
5:18 Is there any other possible data structure or mechanism we could use that's not going to
5:23 create a cycle? Remember, these things are going to survive a while.
5:26 If there's going many of them,
5:27 they're going to get promoted into Gen 1
5:29 and then to Gen 2, and when those things get inspected,
5:32 it's going to be expensive. They're gonna hang on around in memory longer than they
5:35 otherwise should. remember, Gen 1 is 10 times less likely
5:40 and Gen 2 is 100 times less likely to be even inspected. So avoiding creating the cycle
5:46 in the first place may be a really good idea.
5:48 Alright, So how do we do that?
5:50 How do we create this?
5:51 Well, the stage is set. In the next demo
5:53 we're going to go and use a slightly different data structure that will have the same
5:58 accomplishment. Like you could say,
6:00 a friend of Michael is Sarah, and vice versa without creating cycles.