Auto-generated transcript Hey guys, welcome back to the memory management in Go video series. This is the part 2 of this series and this is also the final part of the series. We're going to talk about how the Go garbage collector actually works, what sort of algorithms it uses, how it specifically how it manages the memory inside your Go program. So without further ado let's get started. Now I'm going to put a bunch of fancy words on the screen over here. Golang uses a... first of all it uses a non-generational garbage collector. I'll explain what all of these terms mean. It's also concurrent and it's tricolor and uses a mark-and-sweep algorithm. So that's a lot of words. Let's discuss every single one of them and see what each of these means. So these are basically the properties of the Go garbage collector. This is the basically the kind of garbage collector that Go uses. First of all let's talk about the non-generational part. So there's basically two kinds of garbage collectors. There's a generational garbage collector and there's also a non what the hell was that non-generational garbage collector and the only difference in between both of these is that the generational garbage collector is going to divide your variables into two generations two parts the young and the old generations so let me type that out as well over here it's going to divide your variables into young and old generations and what does that mean exactly well basically the generational hypothesis the generational theory in garbage collection is that the young variables the variables that you declare right now are going to be deleted much faster than old variables that have been stored that have been used in the program for a long time so basically it's something like this if i go in the main function over here if i call this first function or not even this if i declare a function over here and just say something like i don't know um init database right this is going to declare a database and return that to me let's just say the database is just a db variable and it's just a string who cares right and it just returns that to us over here like this right and it's just going to return that db okay so this is obviously not a real database but i'm just trying to give you guys an example if we have a program over here we obviously need to have a database connector over here as well right so i'm going to say init db and store the database over here right and this database variable is probably going to be used throughout the program right every time we want to fetch some data or we want to store or update some data we need to use this database variable right so this is a old variable this is probably going to be used for a very long time in the program probably until the program ends right so the go compiler is going to put this or not the go compiler because go does not use a generational garbage collector but the generational garbage collectors are going to consider this an old variable because it is surviving for a very long time throughout the execution of the program. Similarly, or not similarly, but basically if we have something like an add function over here and this just takes two integers and returns the result, let's say sum equals x plus y and then return sum. There we go. this is a young variable this is not going to be an old variable because this some variable will be removed as soon as we return over here right it's not it's not it's not going to be used anymore after we execute this function and we return the result so this is a young variable and the generational hypothesis basically just says that the young variables the variables that are declared right now they're going to be cleared a lot faster whereas the old variables they're going to stay there for a very long time. They're going to keep getting used for a very long time. So the generational hypothesis, once it divides variables into young and old generations, next it's just going to query both of these generations and see which variables are still being used, right? And if one of the variables is not being used, it's going to clear them, right? It's going to delete the unused variables and free up that memory. Now, the point of dividing into young and old generations is this. As I said, the generational hypothesis considers that the young generation will clear up variables much faster. So, it's going to query young generation more than the old generation, right? So, for instance, let's say it's going to query the young generation every one second. It's going to query the old generation every 20 seconds, right? There's a difference over there and obviously I'm using example intervals over there example values but the idea is it going to query the young generation much more than the old generation right if a generational garbage collector sees this DB variable and it sees that this is being used throughout the program and it not being unused right then it going to consider it an old variable it's not it's going to check this very very rarely because this is part of the old generation now whereas something like this some variable it's part of the young generation because it is declared quickly and then also freed up soon after as well. So it's going to query this young generation a lot more. That's basically how a generational garbage collector works. The non-generational garbage collector is the complete opposite of that. It does not divide it, does not divide variables into generations. It just queries all of the variables without actually dividing them into generations and whatnot. And the reason the Go language uses a non-generational garbage collector is because there's a ton of different compiler optimizations inside Go, which basically just make this generational hypothesis completely pointless to use in Go. Because most of the Go variables are stored inside a stack. There's a ton of optimizations done in the Go compiler that allow us to store most values inside a stack. And you can go read about these optimizations on your own as well. I'm not going to discuss them in this video. It would just be too long. Alright. But basically the Go compiler allows us to store most variables inside the stack which means that we don't really need this generational garbage collection and we can just go with the non-generational garbage collection which is a lot simpler because it does not divide into young and old generations. It's a lot simpler method of garbage collection and Go is a very simple language so they went with this. That's basically what the non-generational garbage collection means. Now, let's put this away somewhere. Concurrent. Concurrent garbage collection. This is very simple. This basically just means that the garbage collector is going to run alongside your program, all right? Like, it's not going to stop the execution of your program midway. It's going to run alongside your program simultaneously, right? So there's two types of garbage collectors. There's the concurrent type and there's the stop the world type. Stop the world garbage collectors are basically garbage collectors that are completely going to stop the execution of your program, all right? So as soon as the garbage collector runs it's going to completely stop the execution of your program, pause it, run the garbage collection, free up some memory, and then resume the execution of your program. Those are the stop the world garbage collectors and as you can imagine they're probably really bad because they're going to stop your program Execution and there's going to be delays and performance issues and stuff, right? Which is why go uses a concurrent garbage collector, which basically will run right alongside your program It's not going to stop your program in any way. So that's what a concurrent garbage collector means Now let's put this away somewhere as well. Let me just actually delete both of these. I don't think we need to keep them over here. There we go. So now let's talk about the tricolor and the mark and sweep algorithms. So before we talk about the tricolor algorithm let's first talk about the mark and sweep algorithm because that is what uses the tricolor algorithm under the hood. And by the way please also remember that this garbage collector only runs on the heap right. The stack is automatically managed as we talked about in the last video, there's no need to run a garbage collector in the stack because the stack automatically manages its memory, right? Garbage collection is only used in the heap. So let's talk about the mark and sweep algorithm. So this is basically the way in which the go garbage collector finds the unused variables and freeze them up. So the way the mark and sweep algorithm works is first of all it's going to stop the world. All right stop the world just means stop the execution of your program and yes I did say that this is a concurrent garbage collector but just let me finish. First of all it's going to stop the world but only at the beginning of the marking phase. All right this only runs at the beginning of the marking phase and it runs so basically Go can set up the garbage collector state and also enable a write barrier on the memory in your program. So basically this is going to ensure the correctness and the consistency of the program memory, right? Go is going to enable a write barrier which this isn't going to prevent you from writing memory. It's just going to allow the garbage collector to know which new variables you're declaring, what new memory you're storing in your program right so that the garbage collector can also process that as well once this is done it's going to start the world again and begin the marking phase right so this mark and sweep algorithm it consists of two parts first it's going to run the marking phase and then the sweep phase right so here it's going to start the world and begin the marking phase now the marking phase is where the tricolor algorithm is actually used so let's add that as well at this point the garbage collector is basically going to use the tricolor algorithm to find unused objects in your heap memory right We know that the garbage collector only runs in the heap so let mention that over here as well it going to use the tricolor algorithm to find unused objects in your heap memory let me also show you a diagram of this let me draw something out over here let's go down over here and draw a bunch of circles Alright, so I have a bunch of circles over here and also a bunch of labels. Let's talk about how the tricolor algorithm works and how the Go garbage collector uses it to find the unused memory. So let's imagine that all of these circles, all of these nodes over here are objects stored inside of our heap. What the Go compiler is going to do is it's first going to start processing up top at the root node which in this case is a right look at these colors as well over here look at these labels first of all it's going to color it blue all right so let me change the background over here to blue there we go and blue just means processing the go compiler the go garbage collector is processing this root node it's going to see which objects are still connected to it so in this case it's the b and the c variables and since the garbage collector can see that this variable that this object is still being used it's just going to color it brown instead of blue because it knows that it's being used brown equals in use over here then it's going to process the b and c variables which means it's going to color them blue as such and then let's just say that the b object is connected to the d and e object and the c object is connected to the f object over here right now it's done processing these objects as well and it's going to say that they are still currently in use the program is still using these b and c objects then it's going to process the d the e and the f um objects which means it's going to color them blue blue means processing right there we go and the f object as well and as soon as it sees that all of these are still being used it's just going to color them brown instead of blue brown means in use right the object is still being used now we still have these g and h objects and they're not connected to the root node a over here right which means that they are not being used anymore inside of this program which means it's just going to color them white instead of black as such and i guess i should change the text color over here as well because this is hard to see there we go there we go awesome so any object that is not being used it's just going to be white which just means unused so that is the tricolor algorithm right it uses three colors that is why it's called tricolor and obviously inside the memory it's not going to obviously color objects where it's not going to fucking sprinkle some color on the objects this is just what we call it to just represent it and just understand it better right but the actual objects inside memory it's not going to give them a color right but anyway that's just how we understand it so just to give you guys a recap every single object inside the heap it's going to start off with the color of white which means unused. Then the go garbage collector is going to start at the root node which in this case is A, process it which will change its color to blue and then see which nodes are connected to it, which objects are connected to it and so on and so forth. As soon as it's finished processing a node it's going to change that color from blue to brown and it's just going to keep going down the chain until it runs out of nodes right. At the end of that chain whichever objects are completely unused, they will have never been processed, which means the Go garbage collector could never reach them. And since all objects are white by default in the beginning, and they only change to another color after they're done processing, which means that every single object that's still white at the end of this analysis, at the end of this tricolor marking algorithm, if they're still white, that means that they're unused, right? All objects start off with the white color and then as they get processed by the garbage collector the color changes which means any object that's still white at the end of this tricolor phase is just going to be unused in memory right and so this is the marking phase and it uses this tricolor algorithm to mark the unused and used objects inside your memory let's move this away and go back over here so that's how the tricolor algorithm works to find unused objects in your heap memory. Once the mark and sweep algorithm has finished the marking phase and found the unused objects inside your memory, it's going to run the sweep phase, run sweep phase, which will basically delete all of the unused objects in the heap, right? All of the unused objects that are left in the heap, such as this G and H variable over here, right? These are unused. They never got processed by the go garbage collector It could never reach them And so this is going to get deleted in the sweep phase of the mark algorithm and that is how the go garbage collector is going to run it what algorithms it going to use and how it going to clear the memory and free up some memory inside your program now finally the last thing I want to talk about is the go GC variable let me put this over here somewhere and change the text color to white go GC environment variable there we go let me actually show you guys the documentation for this so over here on the official go website in the runtime package definition in the environment variables section you can see this go GC variable and what this basically does is it sets the initial garbage collection target percentage what that means is how much how much data how much memory needs to increase since the previous garbage collection until the go garbage collector is run again right so a quick example over here if you are if the go let me zoom in as well if your program is using let's say 5 MB memory right and the go GC variable is set to a hundred percent that means that the go garbage collector is going to run when your program memory reaches let's say 10 MB right because the go garbage collection percentage is set to 100% which means the memory literally must double until the GC is run again right if instead I set the go GC variable to let's say 50% that means that the memory only needs to increase by 50% until the garbage collector is run again so 50% of 5 MB is I'm not good with numbers but I think 7.5 MB so as soon as your program uses 7.5 MB in memory the garbage collector is going to run right if I set this to 200% instead I guess that's going to be 15 MB as soon as your program reaches 15 MB in memory the garbage collector is going to run. So you can use this go GC environment variable to basically go away Google Drive to basically tell the garbage collector when it should run right and you can basically optimize this as much as you want. I have never needed to optimize this all that much. I just go with the default value which is 100 percent. So basically every time your program memory is going to double the garbage collector is going to run that's what i use i just go with the default value but if you're an advanced software engineer and you need to tweak this value you have the option to do that by using this go gc environment variable this is basically how go decides how often and when the garbage collector should run right we've already talked about how the garbage collector actually works what it uses all the algorithms and everything and this go gc variable is how it decides when to run all right and by the way you can also set this to off like you can literally set this variable to the string value of off and if you say that then the gc is just never going to run right if you set go gc variable to off that means that the garbage collector is just never going to run you basically turn off the garbage collection completely in the program right and uh personally i don't know why you would ever do this i don't see a use case for this but there probably is right they gave you this option for a reason but yeah you can turn off garbage collection as well if you want to i don't know why you would do that i don't know what kind of programs you're writing if you do this but yeah you do have that option so with that we are done with this video series we talked about how memory management works in go we talked about the kind of garbage collector that go even uses it's a non-generational concurrent tricolor mark and sweep algorithm using garbage collector. We talked about what all of those terms mean. We talked about the generational versus non-generational hypothesis, what the concurrent garbage collectors are like, what the stop the world garbage collectors are like. We also talked about the mark and sweep algorithm and how the tricolor marking works as well. And we talked about the go GC environment variable over here and how that works as well. With that, we are done with this video series i hope you learned how go manages memory in its programs it's actually a very fascinating topic like i read about this a lot and uh you guys know i want to learn as much as i can about the inner workings of these languages and inner workings of systems i've been reading about this and it is a very fascinating topic like you you read about all this and you understand what different performance trade-offs these developers have to make in order to write these algorithms and use them and all of the different design decisions they're going through in their minds to decide which algorithm, which method to use, which would be best and so on and so forth. It's just a very fascinating topic. So I hope you guys learned something as well from all of this. And yeah, thank you so much for watching. Like, comment, subscribe, share the video, all of those wonderful things. I am actually late for class right now. I should be in university right now taking my classes and I'm sitting home recording a video for you guys. So you're welcome. And yeah, I need to get going now. So see ya.