Most applications need to store data in memory to run successfully. We called that earlier, how processes interact with the OS to request chunks of memory, and then release them when they're no longer needed. When writing programs in languages like C, or C plus plus, the programmer is in charge of deciding how much memory to request, and when to give it back. Since we're human, we might sometimes forget to free memory that isn't in use anymore, this is what we call a Memory leak. A memory leak, happens when a chunk of memory that's no longer needed is not released. If the memory leak is small, we might not even notice it, and it probably won't cause any problems. But, when the memory that's leaked becomes larger and larger over time, it can cause the whole system to start misbehaving, not cool memory leak, not cool. When a program uses a lot of RAM, other programs will need to be swapped out and everything will run slowly. If the program uses all of the available memory, then no processes will be able to request more memory, and things will start failing in weird ways. When this happens, the OS might terminate processes to free up some of the memory, causing unrelated programs to crash. You might be thinking why should I care if I don't plan to code in C or C plus plus, it's true, the languages like Python, Java, or Go manage memory for us, but things can still go wrong if we don't use the memory correctly. To understand how this works, let's look into what these languages do. First, they request the necessary memory when we create variables, and then they run a tool called Garbage collector, that's in charge of freeing the memory that's no longer in use. To detect when that's the case, the garbage collector looks at the variables in use and the memory assigned to them and then checks if there any portions of the memory that aren't being referenced by any variables. Say for example, you create a dictionary inside a function, use it to process a text file, calculate the frequency of the words in the file, and then return the word that was used the most frequently. When the function returns, the dictionary is not referenced anymore. So the garbage collector can detect this and give back the unused memory, but if the function returns the whole dictionary, then it's still in use, and the memory won't be given back until that stops being the case. When our code keeps variables pointing to the data in memory, like a variable in the code itself, or an element in a list or a dictionary, the garbage collector won't release that memory. In other words, even when the language takes care of requesting and releasing the memory for us, we could still see the same effects of a memory leak. If that memory keeps growing, the code could cause the computer to run out of memory, just like a memory leak would. The OS will normally released any memory assigned to a process once the process finishes. So memory leaks are less of an issue for programs that are short lived, but can become especially problematic for processes that keep running in the background. Even worse than these, are memory leaks caused by a device driver, or the OS itself. In these cases, only a full restart of the system releases the memory. Say you notice that your computer seems to run out of memory a lot, you look at the running programs over the course of some time, and realize that there's a process that keeps using more and more memory as the hours pass. If you reset that process, it begins with a very small amount of memory, but quickly requires more and more. If that's the case, it's pretty likely that this program has a memory leak. So let's jog its memory, what can we do if we suspect a program has a memory leak? We can use a memory profiler to figure out how the memory is being used. As what debuggers will have to use the right profiler for the language of the application. For profiling C and C plus plus programs, we'll use Valgrind which we mentioned in an earlier video. For profiling a Python, there are bunch of different tools that are disposal, depending on what exactly we want to profile. We can be as detailed as profiling the memory usage of a single function, or as big picture as monitoring the total memory consumption over time. Using profilers, we can see what structures are using the most memory at one in time or take snapshots at different points in time and compare them. The goal of these tools is to help us identify which information we're keeping in memory that we don't actually need. It's important that we measure the use of memory first before we try to change anything, otherwise we might be optimizing the wrong piece of code. Sometimes we need to keep data in memory, and that's fine, but you want to make sure that you're only keeping the data that you actually need, and that you've let go of anything you won't be using, that way the garbage collector can give that memory back to the OS. Of course, if you check that you're using the memory correctly, but still find that your exhausting available RAM, it might be time for an upgrade. Did you commit all that to memory? Don't forget, there's a lot more to say about memory profiling than we have time to cover it, but we've included links to more information about some of these profiling tools in the next reading. Up next, we'll talk about a different resource that might need some special care, disk space.