Track MEMORY ALLOCATIONS the Easy Way in C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
and so guys my name is Ana and welcome back to my say boss boss series so today I'm gonna be talking a little bit more about memory and specifically how we can track allocation and the allocation of memory now the thing about memory is that it's important I'm gonna keep talking about memory probably forever because that's how computers work computers are very very closely tied in with memory if you just have a CPU and you don't have any RAM you don't have any memory then nothing really is going to happen and because it's such a popular topic for discussion a lot of people sometimes have the wrong idea about memory and I think this is further complicated by the fact that it's 2020 we don't really have that big of an issue with memory like we did 20 years ago we have gigabytes and gigabytes of memory I have like 32 gigabytes in my computer most laptops come with like 8 or 16 gigabytes of memory it's kind of difficult to write a C++ program that's gonna use that amount or more I mean not that difficult and definitely depends on what you're doing but it's still hello world is not gonna use too much memory so anyway my point with all of this is that sometimes it's useful to know when your program allocates memory specifically on the heap of course is what we're talking about if you know where your program allocates memory you can potentially work to reduce it therefore potentially optimizing your program and making it run faster because allocating memory on the heap is is not the best thing to do especially in performance critical code on top of that being able to see where memory is being allocated can also help you discover a little bit more about how your program works even if you wrote all of the code that you're currently running and we just like forget about this if I lost on a library LSU saves all of your code looking over a life project that you may have been working on for a while and being able to see okay you know my program allocates memory here I forgot about that well that was something that was from a long time ago that's useful information and we're going to talk about how we can see exactly where each allocation comes from as well as track the overall usage of memory inside our application by just writing the code to do that not relying on any other tools whatsoever and I also want to thank Skillshare for sponsoring this video for those of you who don't know what skill Shey is Scotia is an online learning community for creatives where millions come together to take the next step in their creative journey Skillshare offers thousands of inspiring classes for creative and curious people on topics including illustration design photography video freelancing and more they've got tons of stuff on their platform to help you learn a new skill and one of my favorite features about skill share is that their videos are quite concise which means that I can fit them into my schedule and I have time to actually use them to learn something new a lot of their illustration classes I particularly like because I'm always interested in improving my art and they also have plenty of classes to get you started on how to make videos make twenty twenty a year in which you explore new skills deepen existing passions and get lost in creativity with school fairs online classes and with an annual subscription of less than $10 a month Skillshare is a great way to do all of that and the best part is the skill share is offering the first 500 people who sign up using the link in the description below to three months of skill share premium so go ahead and do that as soon as possible and thank you as always to Skillshare for sponsoring this video I also want to thank all of you for subscribing and watching my videos because we've hit 200 thousand subscribers on the channel which is quite a cool milestone what I thought I would do for that is do a bit of a QA I have not done a Q&A video in like five years probably so if you guys have questions for me then drop them in the comment section below I'll be looking at the comments of this video to see what I should include in the Q&A please don't ask me to fix your card now let's dive into some card and take a look at how exactly you can be more aware of where you're allocating memory so here we have a completely blank C++ program I'm gonna use this as the foundation for showing you guys all of this stuff keep in mind though that in general everything I'm going to show you here today you can easily plug into an existing application of yours that's kind of the way that I am intending for it to happen maybe in the future we'll take a look at this inside a real project but for now I'm just gonna strip back all of that kind of craft all of that extra stuff that isn't really relevant at all and we're gonna take a look at the core basics the first thing I'm gonna do here is write a little object because this is probably going to be a good example of a real-world use case I might have an object let's just say it contains an X Y Z we have three integers in here now if I create it on the stack I'll probably end up with something like this however if I create this on the heap by calling a new object then of course that will result in a heap allocation and the point of this video today is how can we detect things like this the way we're gonna do that is by overriding the new operator and specifically we're overriding this operator globally so to do that we'll type in void pointer operator nude and then size t sighs so what this is is the new operator this new keyword here is actually a function that gets called with a particular size and potentially other arguments as well by writing this code here we're saying do not use the operator new that is in the standard library use this one instead the linker will actually link in this function instead now of course it's good to actually allocate memory here because that's the point of this your program probably won't work if you don't of course you could retrieve the memory from anywhere the point of this function is to return a void pointer which is just a memory address so because we don't really want to affect the behavior of our program we'll simply type in return malloc size so what does it'll do is allocate the appropriate amount of memory for us and return a pointer to that memory so with this change being the only change that I've made if we run this normally nothing will change but this new keyword will now run through this function which is quite nice because I could easily type in something like allocating size bytes for example and now it will actually print that to the console and perhaps the other benefit to simply writing something like this is that I can now easily stick a breakpoint here and if I run this program you'll see that my program breaks on this line and I and look at the call stack and I can see that okay it's coming from this line of code now of course in this case that's super obvious but what if we made something like a string so I should say we have a string culture now now this is a small string so it weren't allocate memory on the heap to store these characters however we are in debug mode so it still will outcast in memory if we launch this now you can see that this allocation is coming from this line of code and we can actually track that all the way in the coalsack through string and say that okay we call operator new here and we allocate eight bytes of memory which is also you can see what our console reflects just in case it's not 100% clear I also want to point out that this does not just affect you explicitly calling you if you use smart pointers so for example if this was a unique pointer and then let's change this to make you me with object addressing clear memory up here then obviously memory will still get allocated here if I run this code will skip past the string here to the next allocation and you can see that this happens from within make unique because unique actually of course creates the object on the heap by calling new so hopefully you can already see how useful this is you can stick a breakpoint inside that operator new function and trace back exactly where those memory allocations are coming from another really good example where this is super useful is if you're working on a game engine or a game when the games actually running when you're rendering frames like let's just say you finished loading you finished initialization all of that you're in your level you're just playing your game frame to frame you want to minimize the number of allocations you have because they that can have a quite significant performance impact so what you can do and what I have done in the past is you can just stick a breakpoint inside that operating new function while your game loop is actually running and kind of trace exactly where those memory allocations are coming from frame to frame and to be honest a lot of them I'm probably gonna be like string operations and stuff like that but sometimes you can you can make smarter decisions for example maybe you have a vector that keeps getting all resized maybe you can define that size ahead of time or use something that doesn't quite allocate as much memory or maybe you can write a memory arena or something like that for a given system or operation or something in your game loop so that you can reduce actual memory allocations that keep hitting the heap it's all seriously useful stuff if we go back to this little example of ours we can also write the matching delete operator which just looks like this we have operator delete and then a pointer to the memory that we want to delete and what we can do here is just type in free memory and that's really all there is to it now if we put a breakpoint here and we maybe take this unique pointer and put it into a little scope here what you should see is this operator delete being called from this main function after this unique pointer is destroyed and you can see that is the actual destructor of this unique pointer here that is actually deleting our underlying raw pointer now if we go back here you'll learn is that this of course doesn't actually contain information about the size so we can't really print anything like this well I mean we can we just have to add that parameter in because at the core this delete operator doesn't really need size information but you can optionally obtain that information by just overriding this specific function signature so now if we take a look at this and we just let our program run naturally making sure that I actually write something like freeing you can see that now we allocate 12 bytes we free 12 bytes we allocate another 8 bytes and we free 8 bytes so now using these two functions we can create some sort of allocation tracker we can maintain allocation metrics we can find out exactly how much memory is being used how much is being allocated how much is being freed all of that stuff which of course becomes really useful so what I'll do is I'll come up here and I'll write a struct called allocation metrics this will contain a UN 32t which will be our total allocated memory as well as our total freed memory I'll also write a little function here that tells us our current usage and this will just be turtle allocated - turtle 3 I'll create a little static instance of this struct here and then instead of printing this whole allocation thing I'll just say s allocation metrics turtle allocated plus equal size inside out operating you and then I'll do the same thing for the delete operator but of course that'll be our turtle breed so now what I can do is maybe write a function called print usage culture and memory usage so small clear and this will simply output our memory usage which will be s allocation metrics current usage bytes ok cool so now I can print my memory usage at the start I can print it off to allocating this object I might move this string up to make it a little bit more interesting and I'll just I'll just put these everywhere let's just run this program so now you can see that at the beginning we're not using any memory then we've allocated 8 bytes for this actual string then we've allocated another 12 bytes for these three integers because we have three integers three times four is twelve and then finally we're back down to eight bytes after the scope ends because we've freed our unique pointer pretty cool stuff anyway if you guys found this helpful go ahead and throw this into your own programs and actually test it out and see it in action I do want to make a note that of course you could use tools for this you don't have to write code that does this yourself you could use visual studios built-in kind of memory allocation tracking profiling tools whatever they're called valgrind also has some nice tools for tracking memory and seeing where it's coming from like allocations coming from all of that kind of stuff so there are tools available out there and I might make some videos on them in the future but for me personally this is a very quick and dirty way to actually see what is actually going on and also trace it back within your code without having to kind of use other tools they are definitely useful and I'm not saying that you shouldn't use them all I'm saying is that sometimes it's just a lot easier and more simple to just write something like this and instantly be able to see exactly where those allocations are coming from and this is definitely something that I use in my own technology all the time and in fact in a bigger kind of game engine for you would probably have your own kind of opera new operator to lead all that stuff because aside from having to just track metrics and make sure that that works across all platforms you also may want to control exactly where that memory is coming from anyway hope you guys enjoyed this video if you did please hit that like button don't forget to leave any questions that you may have for me in the comment section below for that 200k special Q&A video and I will see you next time goodbye [Music]
Info
Channel: The Cherno
Views: 83,285
Rating: 4.9399805 out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, game engine, how to make a game engine, game engine series
Id: sLlGEUO_EGE
Channel Id: undefined
Length: 13min 25sec (805 seconds)
Published: Thu Mar 05 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.