Handmade Hero»Episode Guide
Thread-safe Performance Counters
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:16Recap and plan for today
0:16Recap and plan for today
0:16Recap and plan for today
2:27Packing a tiny monospaced font into the asset file
2:27Packing a tiny monospaced font into the asset file
2:27Packing a tiny monospaced font into the asset file
4:05Supporting font selection
4:05Supporting font selection
4:05Supporting font selection
6:54Adding the debug font
6:54Adding the debug font
6:54Adding the debug font
9:09Testing the packing of multiple fonts
9:09Testing the packing of multiple fonts
9:09Testing the packing of multiple fonts
10:08The AssetCount is wrong. Let's debug that
10:08The AssetCount is wrong. Let's debug that
10:08The AssetCount is wrong. Let's debug that
11:50We're missing one entire character set
11:50We're missing one entire character set
11:50We're missing one entire character set
14:45Are TypeIDs not initialized?
14:45Are TypeIDs not initialized?
14:45Are TypeIDs not initialized?
15:22Let's see if it's the asset processor's fault
15:22Let's see if it's the asset processor's fault
15:22Let's see if it's the asset processor's fault
17:36The way the code is structured, we can't BeginAssetType twice for the same AssetType...
17:36The way the code is structured, we can't BeginAssetType twice for the same AssetType...
17:36The way the code is structured, we can't BeginAssetType twice for the same AssetType...
18:13... but we can group all the font packing calls inside WriteFonts to sidestep that issue
18:13... but we can group all the font packing calls inside WriteFonts to sidestep that issue
18:13... but we can group all the font packing calls inside WriteFonts to sidestep that issue
19:16Tagging the fonts
19:16Tagging the fonts
19:16Tagging the fonts
22:05Testing the new font packing
22:05Testing the new font packing
22:05Testing the new font packing
22:40Picking a different font
22:40Picking a different font
22:40Picking a different font
23:55It works!
23:55It works!
23:55It works!
24:33Specifying the size of the font
24:33Specifying the size of the font
24:33Specifying the size of the font
27:30Adding some extra TIMED_BLOCK calls
27:30Adding some extra TIMED_BLOCK calls
27:30Adding some extra TIMED_BLOCK calls
31:59There are still two problems that we need to solve:
31:59There are still two problems that we need to solve:
31:59There are still two problems that we need to solve:
32:021) The timing of anything that encloses the render process is wrong
32:021) The timing of anything that encloses the render process is wrong
32:021) The timing of anything that encloses the render process is wrong
32:402) The access to the timers is not thread-safe
32:402) The access to the timers is not thread-safe
32:402) The access to the timers is not thread-safe
35:00The first problem can be solved by displaying the counters with one frame of delay...
35:00The first problem can be solved by displaying the counters with one frame of delay...
35:00The first problem can be solved by displaying the counters with one frame of delay...
36:20... but we'll first solve the threading problem
36:20... but we'll first solve the threading problem
36:20... but we'll first solve the threading problem
36:42(Blackboard) Thread-safe performance counters
36:42(Blackboard) Thread-safe performance counters
36:42(Blackboard) Thread-safe performance counters
36:55Review of implementation of performance counters. Using Record->CycleCount as temporary storage is problematic, because it should contain the end result
36:55Review of implementation of performance counters. Using Record->CycleCount as temporary storage is problematic, because it should contain the end result
36:55Review of implementation of performance counters. Using Record->CycleCount as temporary storage is problematic, because it should contain the end result
39:20Using a separate value to keep track of the StartCycles
39:20Using a separate value to keep track of the StartCycles
39:20Using a separate value to keep track of the StartCycles
40:15The concurrent access to HitCount and CycleCount is also a problem
40:15The concurrent access to HitCount and CycleCount is also a problem
40:15The concurrent access to HitCount and CycleCount is also a problem
42:28Implementing AtomicAddU32
42:28Implementing AtomicAddU32
42:28Implementing AtomicAddU32
44:15Consulting the _InterlockedExchangeAdd docs
44:15Consulting the _InterlockedExchangeAdd docs
44:15Consulting the _InterlockedExchangeAdd docs
45:56The result does not look correct yet
45:56The result does not look correct yet
45:56The result does not look correct yet
46:20Resetting the counters atomically
46:20Resetting the counters atomically
46:20Resetting the counters atomically
47:44Correcting the _snprintf_s format specifiers of the time counters
47:44Correcting the _snprintf_s format specifiers of the time counters
47:44Correcting the _snprintf_s format specifiers of the time counters
48:10Updating CycleCount and HitCount atomically together by merging them into a single U64
48:10Updating CycleCount and HitCount atomically together by merging them into a single U64
48:10Updating CycleCount and HitCount atomically together by merging them into a single U64
52:32Making the reading and resetting of the counters also atomic using an unconditional atomic exchange
52:32Making the reading and resetting of the counters also atomic using an unconditional atomic exchange
52:32Making the reading and resetting of the counters also atomic using an unconditional atomic exchange
53:56It seems to be working
53:56It seems to be working
53:56It seems to be working
54:05We are now thread-safe
54:05We are now thread-safe
54:05We are now thread-safe
55:20Reporting both DebugRecordsMain and DebugRecordsOptimized
55:20Reporting both DebugRecordsMain and DebugRecordsOptimized
55:20Reporting both DebugRecordsMain and DebugRecordsOptimized
58:48Reporting also the line number of TIMED_BLOCKs
58:48Reporting also the line number of TIMED_BLOCKs
58:48Reporting also the line number of TIMED_BLOCKs
59:45Adding some more TIMED_BLOCKs
59:45Adding some more TIMED_BLOCKs
59:45Adding some more TIMED_BLOCKs
1:00:30The path of least resistance should be the right path, so that doing the right thing is never drudge work
1:00:30The path of least resistance should be the right path, so that doing the right thing is never drudge work
1:00:30The path of least resistance should be the right path, so that doing the right thing is never drudge work
1:01:10Q&A
🗩
1:01:10Q&A
🗩
1:01:10Q&A
🗩
1:01:36andsz_ This was, again, pretty awesome! Thank you
🗪
1:01:36andsz_ This was, again, pretty awesome! Thank you
🗪
1:01:36andsz_ This was, again, pretty awesome! Thank you
🗪
1:01:44TheBuzzSaw Wouldn't a union be helpful for that HitCount_CycleCount? It just seems unnecessary having to remember their offsets and / or lengths
🗪
1:01:44TheBuzzSaw Wouldn't a union be helpful for that HitCount_CycleCount? It just seems unnecessary having to remember their offsets and / or lengths
🗪
1:01:44TheBuzzSaw Wouldn't a union be helpful for that HitCount_CycleCount? It just seems unnecessary having to remember their offsets and / or lengths
🗪
1:02:14elxenoaizd Yesterday I asked about preprocessor constants other than __FILE__, __LINE__ etc. I did some searching and found out about __TIME__ and __DATE__. Maybe it's useful for us to include a date-time stamp in some of our logs?
🗪
1:02:14elxenoaizd Yesterday I asked about preprocessor constants other than __FILE__, __LINE__ etc. I did some searching and found out about __TIME__ and __DATE__. Maybe it's useful for us to include a date-time stamp in some of our logs?
🗪
1:02:14elxenoaizd Yesterday I asked about preprocessor constants other than __FILE__, __LINE__ etc. I did some searching and found out about __TIME__ and __DATE__. Maybe it's useful for us to include a date-time stamp in some of our logs?
🗪
1:02:50insofaras Can you align the text into columns with %32s in the sprintf or something?
🗪
1:02:50insofaras Can you align the text into columns with %32s in the sprintf or something?
🗪
1:02:50insofaras Can you align the text into columns with %32s in the sprintf or something?
🗪
1:03:09handmade.cpp: Align the text into columns
1:03:09handmade.cpp: Align the text into columns
1:03:09handmade.cpp: Align the text into columns
1:04:25elxenoaizd You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use it to exit a function instead of 'return' then the destructors won't get called!
🗪
1:04:25elxenoaizd You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use it to exit a function instead of 'return' then the destructors won't get called!
🗪
1:04:25elxenoaizd You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use it to exit a function instead of 'return' then the destructors won't get called!
🗪
1:04:58dandymcgee Will you marry me?
🗪
1:04:58dandymcgee Will you marry me?
🗪
1:04:58dandymcgee Will you marry me?
🗪
1:05:27panic00 Won't rtdsc give wrong results if your thread is pre-empted and scheduled onto a different CPU between the constructor and destructor calls?
🗪
1:05:27panic00 Won't rtdsc give wrong results if your thread is pre-empted and scheduled onto a different CPU between the constructor and destructor calls?
🗪
1:05:27panic00 Won't rtdsc give wrong results if your thread is pre-empted and scheduled onto a different CPU between the constructor and destructor calls?
🗪
1:08:18MannySlain Are you working on any games other than Handmade Hero?
🗪
1:08:18MannySlain Are you working on any games other than Handmade Hero?
🗪
1:08:18MannySlain Are you working on any games other than Handmade Hero?
🗪
1:08:37twitch_makes_me_itch General Programming Question: Do you have any general advice for optimizing code performance, e.g. multithreading, algorithm complexity analysis, etc.)?
🗪
1:08:37twitch_makes_me_itch General Programming Question: Do you have any general advice for optimizing code performance, e.g. multithreading, algorithm complexity analysis, etc.)?
🗪
1:08:37twitch_makes_me_itch General Programming Question: Do you have any general advice for optimizing code performance, e.g. multithreading, algorithm complexity analysis, etc.)?
🗪
1:09:00elxenoaizd Sorry I made a typo in the previous question: You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use "exit" to exit a function instead of 'return' then the destructors won't get called!
🗪
1:09:00elxenoaizd Sorry I made a typo in the previous question: You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use "exit" to exit a function instead of 'return' then the destructors won't get called!
🗪
1:09:00elxenoaizd Sorry I made a typo in the previous question: You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use "exit" to exit a function instead of 'return' then the destructors won't get called!
🗪
1:09:44Wisteso The values are pretty hard to read when they're changing literally every frame. Wouldn't it be better to average them?
🗪
1:09:44Wisteso The values are pretty hard to read when they're changing literally every frame. Wouldn't it be better to average them?
🗪
1:09:44Wisteso The values are pretty hard to read when they're changing literally every frame. Wouldn't it be better to average them?
🗪
1:10:11panic00 Have you considered keeping the timers in thread-local storage instead of using atomics every time you write to them?
🗪
1:10:11panic00 Have you considered keeping the timers in thread-local storage instead of using atomics every time you write to them?
🗪
1:10:11panic00 Have you considered keeping the timers in thread-local storage instead of using atomics every time you write to them?
🗪
1:12:11cubercaleb Are lock-free data structures worth the time they take to write?
🗪
1:12:11cubercaleb Are lock-free data structures worth the time they take to write?
🗪
1:12:11cubercaleb Are lock-free data structures worth the time they take to write?
🗪
1:12:35teryrorDS Do you think it would be worthwhile to make the time records hierarchical (like a call tree), and how would you go about it?
🗪
1:12:35teryrorDS Do you think it would be worthwhile to make the time records hierarchical (like a call tree), and how would you go about it?
🗪
1:12:35teryrorDS Do you think it would be worthwhile to make the time records hierarchical (like a call tree), and how would you go about it?
🗪
1:14:43SeaOfSorrows Can you explain the difference between mutexes and interlocks?
🗪
1:14:43SeaOfSorrows Can you explain the difference between mutexes and interlocks?
🗪
1:14:43SeaOfSorrows Can you explain the difference between mutexes and interlocks?
🗪
1:15:17Blackboard: Interlocks and Mutexes
1:15:17Blackboard: Interlocks and Mutexes
1:15:17Blackboard: Interlocks and Mutexes
1:20:43ijustwantfood Wait, about the values, can you draw a graph out of them?
🗪
1:20:43ijustwantfood Wait, about the values, can you draw a graph out of them?
🗪
1:20:43ijustwantfood Wait, about the values, can you draw a graph out of them?
🗪
1:20:55elxenoaizd NOOO! Save the Cherry MX Blues
🗪
1:20:55elxenoaizd NOOO! Save the Cherry MX Blues
🗪
1:20:55elxenoaizd NOOO! Save the Cherry MX Blues
🗪
1:21:03ttbjm Will you be able to fix the click bug at the end of sounds with the debug system?
🗪
1:21:03ttbjm Will you be able to fix the click bug at the end of sounds with the debug system?
🗪
1:21:03ttbjm Will you be able to fix the click bug at the end of sounds with the debug system?
🗪
1:21:36guit4rfreak Can you still time a smaller section inside the code or does it just work for whole functions now?
🗪
1:21:36guit4rfreak Can you still time a smaller section inside the code or does it just work for whole functions now?
🗪
1:21:36guit4rfreak Can you still time a smaller section inside the code or does it just work for whole functions now?
🗪
1:22:21elxenoaizd I noticed you prefer to keep things on the stack and return by value. 0) This helps with locality of reference and is more cache friendly, am I right? 1) Is the stack size something to be concerned about? 2) When returning by value, is the time taken to copy the object and return it something to be worried about? Maybe when the struct is large? In that case, do you prefer to return a pointer to the object?
🗪
1:22:21elxenoaizd I noticed you prefer to keep things on the stack and return by value. 0) This helps with locality of reference and is more cache friendly, am I right? 1) Is the stack size something to be concerned about? 2) When returning by value, is the time taken to copy the object and return it something to be worried about? Maybe when the struct is large? In that case, do you prefer to return a pointer to the object?
🗪
1:22:21elxenoaizd I noticed you prefer to keep things on the stack and return by value. 0) This helps with locality of reference and is more cache friendly, am I right? 1) Is the stack size something to be concerned about? 2) When returning by value, is the time taken to copy the object and return it something to be worried about? Maybe when the struct is large? In that case, do you prefer to return a pointer to the object?
🗪
1:23:06sparklyguy How do threads wait on lock-free structures? Do they?1
🗪
1:23:06sparklyguy How do threads wait on lock-free structures? Do they?1
🗪
1:23:06sparklyguy How do threads wait on lock-free structures? Do they?1
🗪
1:28:20gasto5 What's wrong with pointers to inline functions?
🗪
1:28:20gasto5 What's wrong with pointers to inline functions?
🗪
1:28:20gasto5 What's wrong with pointers to inline functions?
🗪
1:28:59elxenoaizd Why you skips my questions?
🗪
1:28:59elxenoaizd Why you skips my questions?
🗪
1:28:59elxenoaizd Why you skips my questions?
🗪
1:29:09BIurberry Did you get a degree in CS? What's your background on programming?
🗪
1:29:09BIurberry Did you get a degree in CS? What's your background on programming?
🗪
1:29:09BIurberry Did you get a degree in CS? What's your background on programming?
🗪
1:29:42Wind it down
🗩
1:29:42Wind it down
🗩
1:29:42Wind it down
🗩