[video output=day542 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Drawing Memory Occupancy Accurately" vod_platform=youtube id=EXWyH6CaoRc annotator=Miblo]
[0:00][Plug Handmade Seattle[ref
    site="Handmade Seattle"
    url=https://www.handmade-seattle.com/]][:speech]
[1:21][Recap and set the stage...][:speech]
[1:26][@rupan3][I'm surprised that Casey likes Chrono Trigger]
[2:23][Recap and set the stage for the day][:speech]
[3:14][Demo the current state of our :memory viewers, with the determination to draw our blocks at sizes proportional to their usage amount, and track peak usage][:"debug system" :run :ui]
[8:08][Set up DrawArenaInterval() to draw proportionally sized ranges of memory][:"debug system" :ui]
[16:52][Implement DrawMemoryRange()][:"debug system" :ui]
[30:30][Check out our incorrect :memory Arenas viewer][:"debug system" :run :ui]
[30:56][Fix DrawArenaInterval() to advance the BlockStartAddress][:"debug system" :ui]
[31:26][Check out our less incorrect :memory Arenas viewer][:"debug system" :run :ui]
[33:37][Fix DrawMemoryRange() to correctly draw sub-regions of rows][:"debug system" :ui]
[34:54][Check out our proportionally-sized :memory Arenas viewer][:"debug system" :run :ui]
[40:51][Add colours to the DebugColorTable, requesting a .h file containing the 64 most easily differentiated colours][:ui]
[43:08][Enable DrawTopMemList() and DrawArenaInterval() to track and colour allocations the same per call-site][:"debug system" :ui]
[1:03:25][Hit our "too many call sites" assertion in GetCallSiteFrom()][:"debug system" :run :ui]
[1:05:24][Change GetCallSiteFrom() to compare GUIDs as strings, rather than by pointer, and increase the ArenaCallSites size][:"debug system" :ui]
[1:05:58][Check out our :memory Sizes viewer to see call-sites currently responsible for 0 allocations, but the Arenas viewer not colouring call-sites consistently][:"debug system" :run :ui]
[1:07:42][Fix DrawArenaInterval() to use the CallSiteIndex in the lookup to the DebugColorTable][:"debug system" :ui]
[1:07:51][Check out our consistently coloured :memory Arenas call-site viewer][:"debug system" :run :ui]
[1:10:50][Change DEBUGInit() to expand all the debug views by default][:"debug system" :ui]
[1:21:00][Find that the debug views are not expanded by default][:"debug system" :run :ui]
[1:21:34][Change DEBUGInit() to call SetExpand() after the AddTree() calls][:"debug system" :ui]
[1:21:47][Find that the debug views remain not expanded by default][:"debug system" :run :ui]
[1:21:49][Scour the code for the reason why the debug views are not expanded by default][:"debug system" :research :ui]
[1:24:42][Step through DEBUGInit() to see how view collapsibility figures in to it][:"debug system" :run :ui]
[1:26:45][Consult the code to see if it matters if the View.Type is unset][:"debug system" :research :ui]
[1:28:11][Continue to step through SetExpand(), to find that we correctly match the Tree but not the Link of our views][:"debug system" :run :ui]
[1:31:31][Discover that we create dummy view groups, to later replace them in CollateDebugRecords()][:"debug system" :research :ui]
[1:33:18][Make CollateDebugRecords() expand HUD groups][:"debug system" :ui]
[1:34:46][Find that our debug views are now expanded by default][:"debug system" :run :ui]
[1:36:10][Add per-arena peak :memory usage tracking to DEBUGArenaBlockAllocate() and DrawTopMemList()][:"debug system" :ui]
[1:40:41][Check out our peak usage in the :memory Sizes viewer][:"debug system" :run :ui]
[1:42:21][Add per-call-site peak :memory usage tracking to DEBUGArenaBlockAllocate() and DrawTopMemList()][:"debug system" :ui]
[1:46:02][Check out our per-call-site peak usage in the :memory Sizes viewer][:"debug system" :run :ui]
[1:47:26][Add a %m conversion specifier for FormatStringList() to convert byte-amounts to sensible, non-zero multiples of bytes, i.e. b, kb, mb, gb][:"string manipulation"]
[1:56:26][Find that our byte-amounts are incorrectly displayed][:"string manipulation"]
[1:56:46][Prevent DrawTopMemList() from casting memory amounts to u32 in its calls to FormatString()][:"string manipulation"]
[1:57:58][Check out our correctly converted byte-amounts][:run :"string manipulation"]
[1:58:50][Tweak FormatStringList() to display 1 kb, mb and gb as such, rather than 1024 of their smaller multiple][:"string manipulation"]
[1:59:05][Check out our perfectly converted byte-amounts][:run :"string manipulation"]
[1:59:22][Q&A][:speech]
[1:59:42][@vaualbus][Q: Do you think that having a way to visualize the memory as an image could be useful? How you would implement that?][:ui]
[2:02:34][@Brian][Q: Admittedly I have not been watching all the streams or reviewed the code, but if this tracks memory, and the transient memory could reset itself throughout the frame, is what is only tracked what is left at the end of the frame? And if you have collected peak information? Is the reason the memory appears static because you are not doing anything new / different between frames?][:"debug system"]
[2:04:21][@shlver][Q: Are you planning to add more features to this?][:"debug system"]
[2:04:29][@decstar77][Q: Started watching you awhile back, is the earlier episodes still relevant / worth it, or should I start somewhere more up-to-date so to speak?[ref
    site="Handmade Hero"
    page="Episode Guide"
    url=https://handmadehero.org/watch#EpisodeGuide]]
[2:05:39][@botder][Q: Are you going to add an edit box to filter / reduce the visible lines for memory?][:ui]
[2:05:44][@centhusiast][Q: Thanks for the image scaling explanation in the pre-stream. Could you explain about zoom towards the mouse position? Thanks![ref
    site="Handmade Hero"
    page="Episode Guide"
    url=https://handmadehero.org/watch#EpisodeGuide]][:geometry]
[2:10:01][@Brian][Q: The timing part of the profiler, you had it so you could click on a section and zoom into that section to see more details about a section. Do you see value for it here? Almost like an embedded tab-view that could show the allocations of each object if you wanted to see it? Or what about an option to print to a file the current allocations?][:ui]
[2:11:14][@sc5shout][Q: In the :threading tutorial you used a pointer to a function. I know that you want to keep it C-style, but wasn't that cleaner to just use a method inside a struct? It'd remove every "pointer = func"][:language]
[2:12:52][C-style function pointer in struct vs C++-style virtual function in class][:language :speech]
[2:23:43][@botder][Q: What about C++ lambdas in that case?][:language]
[2:25:14][@sc5shout][@handmade_hero I meant "GameMemory.PlatformAddEntry = Win32AddEntry" and "GameMemory.PlatformCompleteAllWark = Win32CompleteAllWork" platform_add_entry is a void and it points to Win32AddEntry instead of just a single method in a class / struct without jumping through the files and "=" every function pointer][:language]
[2:26:32][@centhusiast][Q: My nephew started computer science a year ago and when I saw the educational materials they are not good and professors mostly teach the toy examples. I think there is a problem with computer science education. Do you know how it can be improved? Maybe the production programmers should teach the programming courses][:education]
[2:30:28][@longboolean][Q: Would there also be an issue in C++ if you wanted to have it be in a queue and some other thing, perhaps, would need to inherit from two or more things?][:language]
[2:31:13][@davep00][Q: Is the C++ way – a lot of hoop jumping just to avoid the cast from the void* to the data type (that you need to do in the C function pointer method) – did the C++ committee reason that it's more type safe?][:language]
[2:31:44][Wrap it up][:speech]
[/video]
