Blow’s surgical approach to decoupling debugger overhead showcases the rare technical rigor needed to build truly transparent systems. It is a masterclass in solving the recursive complexities that most modern developers simply choose to ignore.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
CompilerrrrrrrAdded:
So, that's not optimal.
Um so, I'll put those in and make sure it still runs.
Okay, so um We don't exactly have a plug-in for the visualizer separately, but we we'll deal with that later. Okay.
Um if visualize memory debugger in it visualize memory debugger. All right, so Actually, where does that get called from?
Okay.
We need this separate simpler in it function to in it the mutexes that happen um that guard a couple of data structures we use.
These need to be set up before any alloc or free is called, which is why this is factored out. Okay.
So, we're going to just in it some mutexes.
We're going to We're going to just say uh We're going to just do that.
And then here we're going to do that.
So, sometimes Dude, Twitch chat I just I don't know what to do about Twitch chat, guys.
I don't know what to do about Twitch chat. Hyped for the game? Well, I'm glad you're hyped for the game. I am hyped for the game.
I've been working on it for a real long time.
So, it's going to be good to have it out.
Ignore the randos. I know, dude.
It's it's an important survival thing.
Okay.
So, we have these add free this frame and add alloc this frame.
All right, so Okay, actually, you know what?
Maybe we don't need any of this [ __ ] that I just typed.
Cuz we should use the same mutex.
Right?
Um Can we assert that a mutex is held?
I don't think so.
Okay, this load thread group thing can probably get simplified out.
Maybe not.
I don't know.
Maybe.
>> Okay.
I think I'm going to make some tea.
But I think we just Let me just see where this is called.
Add at allocation this frame that's in um here.
So, when we do this Yeah, so we're inside address table mutex. I would like to be able to assert Well, let's check for the other call. So uh Yeah, this is also okay.
So, actually Dude, I need to Hope I didn't have any changes.
Um So, I think we just need to do this. So The problem is down here.
These this frame tables.
Yeah.
Okay.
So This is all copied out of the report.
Okay.
When accessing Alex this frame and freeze this frame we must be holding address table mutex since these could be modified by uh alloc re-realloc, etc., which can be called on many threads.
We would prefer not to be doing this much.
Um We would prefer not to be doing much work inside this mutex, so we actually take it twice.
Okay, so we're going to do this.
We're going to go bytes total is an int.
We're going to assign down there, and then here we're going to do that.
So, the thing about mutexes is there's at least two major problems that happens if you hold them for too long, right?
One is just things get log-jammed cuz someone's waiting a long time for this mutex while you're doing stuff, and someone else is waiting a long time, and someone else is waiting a long time on that guy, and then nobody can run, and then the whole point of being parallel is so that people can run. So, that's not good.
But the second issue is um Well just the more complicated of code that you call while holding the mutex, the more you don't really know what's happening.
And like you could be grabbing other mutexes while you're holding this one.
And you could have like mutex inversion and stuff. Which by the way, this would be a good thing to do sometime. We'll definitely do this after the game ships, but maybe before the game ships. Like for our default mutex implementation there's all sorts of things that you probably want.
Um So, for example, you want to be able to ask if you're holding it right now. Or you want to be able to assert that you're holding it right now.
Um But you also want to detect mutex inversion and stuff, and I think I kind of want to figure out a good version of that to put in by default.
So, for example There's There's one way of preventing mutex inversion, which is just uh you know, every utex mutex has a static priority number, and when you go to lock the mutex you can only lock things at that priority uh and below, right?
Or above, whichever way you're counting, right? And then um And then if you ever don't do that that's a problem. Now, that's That's actually uh more um more serious or that's more constraining than you would actually need to be correct, but it's like it's this point of usefulness, right?
Do we handle asserts gracefully? What?
What do you mean?
First of all, you control what happens when an assertion fails.
But secondly, what do you want us to do for an assertion failure?
Is the compiler going to ship before or after game release? Uh after, but hopefully not that long after.
The reason is we just uh we don't want the compiler to distract from the game release, and we want to give out a version of the game source code when we give out the compiler. So, you know.
Both of those Yeah. All right, let me get my tea. Back in a second. Any other technical questions that people have?
Okay.
I'm back.
I got some tea.
>> I don't know what the cleaners did with my tea tray. Oh, there it is.
I found it right as I was leaving.
Are they nice to use in C asserts? Yeah.
Of course they are, but you control what happens. You You can override the hook of what happens when an assertion fails to do whatever you want, just as you would expect.
Like it's not that big of a deal.
Um What kind of mutexes? Well, uh it's operating system dependent. We just use whatever is the operating system's preferred mutex.
All right.
Uh I forget.
Um I guess we could run this on Sokoban, but usually we would like a simpler test.
Um Yeah, I guess we can we can do this.
All right. Uh Well, is there a test in here or is there?
There's an examples. Oh, there's a tests.
This probably tests everything.
Okay, well, that's great.
Examples, do we have a All right.
Okay.
So, this doesn't do the visualizer, but we didn't break [clears throat] compilation there.
Uh which is great. Okay. So, we're going to run this bad boy.
And um I forget.
We have uh There's a way to turn this on.
Memory view.
All right.
So, we'll see what happens.
We're building a bunch of shaders.
Okay.
So, all right, some stuff's happening.
We only uh only only using 384 megs. Let me pour myself some tea.
So, you'll see first of all, uh let me go to a simple level where it's easy to understand. Well, and also that's using real graphics. I'm going to give >> So, a big piece of my >> you'll see that we're not doing a lot of memory spam from frame to frame.
I mean, you know.
Which video games should not freaking do, like when we resize the window, we did a little bit. Like we've got some stuff when major things happen, but like you see the numbers bumping up to like 32K.
That's pretty small for a modern video game. And we could get rid of that if it were a priority. But the point being, like if you put a freaking, you know, I don't even know, Unity game in here, you would be seeing some stuff right now.
Um So, we could do this and right, I can run around. I mean, it's working, obviously.
For some definition of working.
Okay. Stop recording.
And then uh we can just inspect the frames, right? So, let's let's do frame 1337.
All right.
Um yeah, we need 2K on that frame.
Transition barrier. This is graphics stuff.
Uh I don't know why I don't know why we're doing that exactly, but it's something we could get rid of.
Like we've probably got an array of how many of these there are, and on this frame the array grew, but it's not that big of an allocation, which make which makes me just think, just like make a big array that can expand, but like usually doesn't.
Right?
So, this is easy to get rid of, I think.
Um Anyhow, I mean, it's working.
Let's look at where our memory comes from.
Allocate geometry, okay.
That makes sense. So, you know, we have like 78 megabytes of meshes.
Um at least. There might be other call stacks. There probably are other call stacks that do, but we've got like 78 megs of meshes.
Um the freaking animation data structures, which is >> [sighs and gasps] >> It's ridiculous that they're this big.
It's maybe I'll change it before ship, maybe not. Okay.
Um Shader material table What is this?
Update material How do we have 25 megabytes of materials?
Okay, this is a hash table that holds materials, I guess. Okay, so that's questionable.
This is not the entire memory footprint of the game, by the way.
Cuz the vast majority of the memory is texture maps, but they don't go through allocations here, which is why you don't see them.
Um They just go straight to the graphics driver.
I guess.
Yeah, I don't know.
I don't know.
What's the back of the envelope for what goes into 78 megabytes of meshes? Seems like a lot. I mean, it's only 7.8 megabyte of meshes per year we worked on the game.
That seem like a lot?
Doesn't seem like a lot to me.
When you put it that way.
This is still more animation player crap, dude. Animation player is really spammy.
This is loading entities.
Yeah, you can you can invest to McGate all the things.
Anyway, we put this in and it appears to be working.
So I'm going to run the tests.
Oh.
I What happened there is I just alt F4 the game.
What is this assertion?
Data is equal to message. Oh, cuz we failed to write though.
I mean are we did Well, actually I don't know. I don't know what happened there.
The problem is because someone [ __ ] up our thing and I'm still angry about it. I can't attach from that point.
Let's see if that happens again.
I don't think that that had anything to do with the change that we made. I suspect that that would have been happening already.
But let's see let's see if we can reproduce that.
Tables grew between the two mutex locks.
Um That's a good point. Okay, let's think about that.
I don't I don't think that that's it's it's just happening when I exit the game interestingly, but it's a good point.
Um Maybe we're not >> [sighs and gasps] >> Okay.
This is safe in the following sense. If the tables grow between the two mutex locks, they're only going to grow. Like we know that we don't shrink the table and so we're looking at safe entries. We just might not actually catch all the entries and that's bad. It's a good point cuz when you grow the table you rehash and all this stuff. So I either we hold the mutex for a long ass time.
Um Which I don't think that's causing that assert by the way.
It's just It is a good point the twitch chat brings up here.
It is a good point.
Just don't exit the game. Yeah.
Yeah.
Okay.
Address table mutex.
I mean if we're Unity game engine we just grab the address table mutex the whole time.
I just would prefer not to do that. We could copy this array while holding the mutex the first time and then copy it over later.
I feel like that might be our best option.
Slug is public domain now. I saw that.
That's pretty cool.
I've never actually looked at the algorithm so I don't know if I would prefer to use it over just what we do now. Although there are benefits.
Right? So if you felt the code complexity was good.
You know, since we have since we have a an intellectually well-to-do beta program full of smart people.
I imagine somebody will just port it at some point.
I do not have time to do so.
I might do so at another time just for the benefit of everyone who uses the compiler, but this is not the right time to do it on the year when we are shipping a game plus the compiler plus the engine.
It's just a lot.
Will you see people implementing it in a day or so?
I mean I guess.
If it's that easy how is it patented?
So with slug is it is there still a license?
Can you license an algorithm like that?
I doubt it, right? Like Need a license the library itself.
Right? But if you did your own port Right. So if it's if it's your source code. Okay, there is a gray area though.
Here's the problem.
The problem is most people who do this kind of thing are not very careful about it legally speaking. I mean of course the laws vary around the world anyway, but like if you make your own version of it by looking at the original source code and then you decline to license the original library um they could sue you for that.
Right?
So it has to be like a clean room implementation from just the algorithm description not looking at the code.
He published reference shaders. Yeah, but are they are the are the reference shaders in the public domain?
Or are they you know, whatever.
You know what I'm saying.
You don't think the original source code is available. Okay, I see.
Okay.
Then that's not an issue.
All right.
What do we do about this?
Um Here is the thing.
I think I I don't remember, but I think this is everything in the heap right here.
And of course if you were being careful about this and trying to keep utilization minimal you would just send what happened this frame.
And you would rely on this the client to put the information together over time, right?
But we don't want to do that cuz at least for now if you send it this way and they don't have to put that information together over time. It's just like easier to scrub and stuff cuz all the data is right there without you having to reconstruct it.
Long-term though we might want to do something different. Okay, but for now this is the problem is I suspect this is a lot of stuff.
Right? And so um So, we don't want to hold this mutex for this long. And so, the alternative is to copy this thing. All right?
So, let's look at this.
Um Okay, this also, by the way, is uh not good.
Okay, so uh I should have should be more careful.
Okay.
So, we're going to assign these while holding the mutex.
And then assign it into the data.
Let's check to see if there's anything else. Alex, this. Nope, not till down here.
Oh, and then, of course, Okay.
All right.
So, let's do this. Uh bytes for mutex controlled data.
Right? And that's going to be It's going to be this stuff.
All right. So, now we're going to need to do this copy.
Okay? And then down here, we're going to go um mem copy data um uh mutex controlled data copy, right? Um.data mutex controlled data copy. count. All right.
And we're going to go data plus equals this.
All right.
And then that should come out the same.
Uh we don't ac- Okay, well, we don't actually need this.
Okay. So, um here we're going to go Uh what what do I call this? Control mutex controlled data copy.
Mutex controlled data copy if dot uh allocated is less than um bytes for mutex controlled data.
We don't want to do this very often.
Uh array reserve controlled data copy here.
That finger.
So, that makes sure we're at least as big. And now we're going to go mutex controlled data copy. count equals the the this.
Dude, I was traveling for 2 weeks and just typing on a laptop keyboard the whole time, and it's hard to get used to this. All right. So, um data is um mutex controlled data copy.data.
And then we cursor it forward, and we're going to assert data is equal to mutex controlled data copy.data plus mutex controlled data copy. count. All right.
Um so, what is this?
It's going to be uh one of these.
Okay.
I'm going to rewrite this comment. We'd prefer not to be doing much inside this mutex.
But but report.sorted summaries could be quite large.
Um You know, writer reserve message bytes total.
Yeah. So, that's fine.
Okay.
Could be quite large.
So, we copy the per frame data, which is hopefully pretty small, so that we don't have to hold the mutex that whole time.
There could be some other creative solutions to the problem.
For example, we only need to know the byte total because we are sending a single message containing all the data.
But if we broke the mutex controlled data into a separate message, we could uh perhaps uh >> [laughter] >> avoid some of this entanglement.
But then you'd have to be guaranteed that the message allocation is fast.
Message target memory.
Okay.
Okay, so um I mean, I just typed some stuff.
Right?
We probably made some mistakes there.
Who knows?
It compiled the first time, which of course means we one-shotted it, obviously.
Okay, I messed that up. 233.
Okay, this is weird. So, Alex's frame out locks this frame. count times that freeze this frame. count. Bytes for mutex controlled data.
So, this is Did I mess something up here?
This looks correct to me.
>> [snorts] >> I guess we will look in the debugger.
Dude, we have multiple instances.
Our cloud credits are just climbing due to all the instances we are running.
>> Okay. Boom, right away.
Vis update.
Data.
Commander data mutex controlled data copy.
Okay, well, it is a startup frame.
So, admittedly, it's probably big. Okay, so um I mean, we honestly probably shouldn't be allocating and freeing that much stuff at startup, so that's something we could look at.
Um Okay, is the mutex even doing its job?
No.
Okay, guys.
This is what I'm saying about like I want to add the ability to assert that the mutex is held. Look at this.
Look at this.
We assign it up here.
We're supposedly inside the mutex, but by the time we get down here, uh it's not. Now, this could actually be us.
But, I don't think so, cuz we don't we wouldn't free anything on the first frame.
Hello.
Raiding party of 12 people. How you doing?
How you doing? All right.
Well, let's go back and check that real fast. I I feel like this might be us.
But, I don't think an array reserve would do four allocations in one free, but it might if that includes our internal structures.
So, I mean, honestly, we could just do this.
All right. I don't know if this re- redoes correctly, so we're just going to restart that every time.
So, we're just going to set a breakpoint there.
Okay.
Allocates frame freezes frame 9288.
So, these numbers match.
Boom.
Okay, wait. That that those line numbers.
Okay.
It looks like this counts us.
Which is a problem.
It is a problem. We're going to maybe step down in that, but why?
Maybe I just didn't recompile enough times.
Okay.
So, 92842511.
Step. Okay, we actually match now.
So, we're going here.
We're going here.
That's just a macro on arrays. So, we're calling realloc.
Calling the overriding allocator proc, which is a debugging procedure. We're calling the uh actual core allocator to get the memory. I'm going to skip over that.
And then we're calling record new memory.
Um Okay.
Is that a macro? Let's memory debugger report new What?
What?
What?
Oh, that's overriding allocators record new Okay.
Okay. So, this is all So, overriding allocator has all its own [ __ ] Because when you free something, we need to know how big it was. So, this is a thing that just puts trash bytes into your memory when you free it so that you know you freed it, right?
In debug builds. All right. So, this is where we are looking at now.
We lock the address table mutex. We find We put that allocation in our address table, which is another bookkeep.
So, we're doing tracing.
Okay.
Now, add an allocation if we're visualizing the memory debugger, which we are.
Okay.
So, we're going to go table add.
Okay. Table's fine.
Let's take a look at it.
Slots filled 9284.
Allocated 16384.
16384 *.7 is 11. So, it's a while before this table would grow.
So, we're not really going to allocate anything there.
Okay.
Except right.
So, we are right here adding an allocation for this frame.
Um Okay.
So, this is happening because I kind of made an oopsie.
And the oopsie is as follows.
Uh we shouldn't be using the overriding allocator anyway. We might still need to deal with this separately, but when you're writing a memory debugging system like this, you want to be um insulated from program state.
And so, um in general, uh we explicitly assign the allocator, right? Let me look for that happening.
Uh in the init function, for example. Uh let's look at stack trace table. Stack trace table.
Yeah, we're pushing context-based default allocator.
This is what we have chosen to do here, right? And the reason we're explicitly pushing an allocator is because we're being called from a program that could have the allocator set to anything, right?
That's also true here.
So, when we are here, um uh mutex controlled we want to be using our own allocator um like this.
Now, that might not solve the problem.
Uh but it will reduce the problem because part of it was that other overriding allocator doing thing, which is why I was surprised cuz in my mind I was like wait, we're just Okay, I forgot to start the thing.
We're just doing the default allocator.
No. No, we were not doing the default allocator.
Oh, are we we're breakpoint? I was sitting there waiting for something to happen.
I'm like, oh, we're breakpointed. Okay, so now Okay, well, we still this is still counting as one, right?
The problem is the problem is we're reporting this.
Do we I mean, do we like reflexively, recursively, self-referentially account for this extra allocation by doing it again?
I guess so. I mean, this is this is a little bit crazy balls, but um cuz we have to have the memory for it, right?
Um Right?
So, we're like, okay, there's actually going to be one more allocation than we wanted.
Now, this is a weird thing. I mean, maybe your memory debugger should just be stealth and not do any of this stuff.
But right now, that's not how it is.
Uh Although, actually, maybe it could be.
Hold on.
I don't remember what policy decision we made on whether this is what we want to be doing for everything inside memory debugger.
What's it called?
context.
inside memory debugger.
Shh.
False. Okay. Actually, actually, um I think the problem is we actually should be doing the following.
Although, actually, in when when is this set?
When we make the leak report, when we shut down, when we init.
Yeah.
All right.
Let's just do this here.
So, we're going to undo that.
And we're going to do this.
Cuz the thing is the reason I say policy decision is because on the one hand, you might think, oh, I really want to know about all the memory that my memory debugger is using cuz I want to trace literally everything, right?
And it's like, yeah, but on the other hand, that's also just noise that keeps you from seeing your actual program's behavior and your shipping program isn't going to have the memory debugger in it, right?
So, um All right, that still [ __ ] did it.
What is going on?
Okay.
So, I mean, I I guess we're calling into the memory debugger somewhere else.
And the pro See, the problem is this inside memory debugger is meant to be it's meant to be a leaf operation.
Like a Leaf Erikson operation.
Wait, did we not Oh, wait.
Let's just recompile just to make sure.
I think I did.
Okay.
So, I think what's going to happen is we're going to go we're going to do an allocation and it's going to get shut off, right?
Yeah.
So, oh, when we make the leak report, right?
But I feel like that's that's not even necessarily Well, we'll see.
Okay, so let's go back to this scenario on here.
Hey, look, it stayed it stayed the same.
Okay.
It's tricky. I never quite remember because I don't work on this code that much. I never quite remember exactly what's going on, but I believe that when that value is set, we do record the allocation now that it happened.
Because if you free that memory later from something, we need to know that it's a valid free or whatever. I don't know.
I don't know, but we don't we don't put it in this thing.
I don't think. We can look into that some other time.
The point being this All right, so this is going to be thousands for now, and then we get down here.
I'll just step it.
Boom. Boom, it worked.
Worked the first time, baby.
For some definition of first time.
All right, so Hey.
It's working. All right. So, that was just all to fix that. I feel like we got to run the tests and take the W, but we still may have this assert when I quit the game. Let's see what happens.
No. Okay. So, actually, I guess it was just when you close the game, there's more intensive uh there's more intensive memory activity, so you're more likely to hit that race condition. We should test a few more times, etc. But, let's uh Um we set inside memory debugger so that we don't mess up the accounting that the user sees.
And also, so that the report size stays stable while we are trying to transmit it.
Um Okay. However, however, make leak report sets this to false assuming that the caller is not inside the memory debugger.
Mayhap we should do this in a more formal way, but for now, we just set it back to true.
Keep in mind, there is a defer active that will set it to false still when we close the scope.
Okay.
Don't you wish code you were reading had nice comments?
Okay.
This is one of the reasons.
Okay.
Okay.
Cool.
Shall we Let's make a release build of the game, which due to LLVM general as bloat, will take a long time.
Uh but we'll make it with the memory view enabled, right?
So, that's just going to stress it out more.
Is it accurate to say that a hybrid programming paradigm is the best way to manage complexity once the core problem is solved?
I don't So, the examples given being procedural or OOP, data oriented.
I mean, both OOP and data oriented are procedural, so I don't get that first of all, but secondly, I mean, I don't use object oriented for basically anything at this point, right?
I use uh I do use a one layer deep hierarchy of things for like entities and sometimes for other things, but they don't like have methods and stuff, right? So, like entities in this game do not tick themselves.
That's literally not anywhere in the game at all.
So, not really. I mean, I would say what you said is true in the sense of like if you really work hard at programming and figure out what really works for the kind of problems you're going to solve, it probably doesn't match anything that anyone teaches you in college exactly and may in smaller parts resemble some of those things, right?
But, like hybrid gives more credit to various things than they maybe deserve.
Like, oh, your choice is to hybridize by taking different It's like, no. It's It's dude, it's code, man.
You write the code that works and it works.
You know what I'm talking about?
Okay.
So, All right. I mean, we're running around.
I mean, I don't All right.
Boom.
What did we free?
Input per frame event update window.
Interesting. All right.
I'm confused because Oh, we're looking at one frame.
I was like, why? Because I was clicking on the wrong thing, that's why. All right. So, what here? Send key event.
That's probably Yeah. So, this is trimmed so that you don't see everything all the way down, but um array add like That's a known leaf, we call it, right? So, you know, this calls Alec down and so we stop there.
Uh making a bitmap.
Yeah, you know, we could get rid of all this if we did some slug going on.
Oh my god, the animation system, dude.
All right. Array resize load all paint data.
Load level and then general.
Yep.
I mean, this all looks reasonable.
So, here the the transaction system does Alec and free.
And that's something we could clean up in the end cuz it's not doing anything really complicated, but that is something that happens right now.
Um Scan one entity. So, down here, right?
We see both So, this was freed this frame, but we also see that it was when it was at or We don't see what frame number it was allocated. That could be a useful addition, but we show you where it was allocated.
Anyway, let's run the general compiler test testerinos.
Just to make sure we didn't break nothing there.
And uh let's make sure we didn't leave a no check in.
And then, I think I think that's the main thing we wanted to do tonight. We're going to ship another beta soon.
Um Oh, I didn't need another editor. We have one.
Please.
Um basic um memory debugger fixed a race condition in the visualizer.
Um modified uh uh uh Wait, what what would I say?
Um, took extra steps to ensure that allocations internal to the visualizer do not pollute the user's memory report.
Did we do anything else?
Hey, look, it all passed. Um, So, we did that. We did this.
I don't like it when the lines of code go up by that much, but yeah.
Okay, now that's that's pretty much what we did.
Dude, we went from 300 lines to 370 lines.
Uh, but some of that's comments, so whatever.
Whatever.
Whatever.
Okay.
Cool. Um, I will reply internally where you cannot see to a team email.
And I will say, um, I supposedly fixed this just now.
Please test.
Keep in mind, uh, uh, that said, we don't have any kind of ASan equivalent at this time, so or sorry, TSAN.
TSAN equivalent, so it's hard to know for sure.
Da da da da da da. All right.
So, dude, TSAN, I keep thinking once in a while we should implement our own TSAN and make it built-in and really easy to use.
And then I go every time I go read the TSAN paper, I have no idea what they're talking about cuz they start out by just saying, "Hey, they do the mission statement, which is like, of course, it's a good idea to detect these bugs and stuff.
And then they're just like, "And we do some ad hoc stuff, and we detect some threads to And it's really weird because it's like I was always under the impression that it was some kind of like actually accurate race detector, and it's not. It's just like, "Well, we did some stuff, and we kind of detect some things.
The end."
It's pretty weird.
Any technical questions that anyone has?
Can we please get a no AI discussion?
The problem is, if I ban the string AI, which I would love to do, I think it'll hit any word with the substring AI in it, right?
Space AI space.
AI Pacino.
All right, are there any actual serious questions before I go out and have fun at the dance?
How do you get out of beginner hell?
Have felt like it for 2 years now, can't seem to improve. Okay.
Um, what What do you mean? Like, what is What is happening to convince you that you're not improving? Like, what's an example?
Cuz it's hard to answer that question without more concrete information.
What TypeScript is to JavaScript? No, that's a completely inaccurate.
Uh, completely inaccurate.
Will PhilC actually work and make C memory safe? I don't know anything about PhilC.
You want to work on a project and keep running into problems.
You cannot seem to solve and struggle to find solutions. Okay, let's talk a Pick a problem. Let's talk about it right now.
What's an example of something you couldn't solve?
One specific problem.
Because maybe what's going on Like, successful programming involves a certain way of breaking down problems into easier problems. And if you don't get that, everything's going to be hard forever, right?
So, type in the problem, and we can look.
You want us to develop a Sims-like game?
You know, back in like 1998, I wanted to do a game vaguely like that, but it wasn't really Sims. It was a little different.
But, you know what? We didn't make that game.
>> [snorts] >> You can't think of anything specific, but memory allocation issues has been a recent problem.
What kind of memory allocation issues?
Like, do you mean like you're freeing something multiple times and it's a bad time?
Or do you mean like you're using something after it was freed?
Or what?
What what kind of issues?
The Sims, but it's survival genre. There are several games that fit that description.
How do I differentiate between ideas and figure out where there's potential? I've given so many talks about that.
What do you mean?
You got wrecked by hash table pointers not being stable. What Well, that's I mean I would assume there's even a comment in the file that says that.
Right?
Maybe there isn't.
Oh, no, cuz this has a giant comment about how it works.
Yeah, there's no pointer stability in a hash table, obviously.
How do you tackle physics-based algorithms? For example, 2D orbital mechanics.
Uh you didn't mention an algorithm.
What do you mean physics-based algorithms?
If you mean how do you implement physics for a game that has things that orbit in 2D, first you implement the very simple version, which is you use the stuff you learned in high school physics and do a step-by-step simulator.
And then eventually you discover that you need to do some things to get a little more accurate than that.
So, like you at least upgrade to midpoint method, but you you probably eventually do like a more powerful integrator, and that gives you uh the opportunity to learn about integrators, and so forth.
But, that's not an algorithm.
You also got wrecked by this. Guys, get good.
It is It is a little bit easy to forget about these things sometimes, right?
I mean, if this were the 1980s and you were Microsoft, you could name every single variable in your program by whether the pointer is stable or not.
Right?
Um and then the Rust version of that is like that's literally the lifetime value, right?
But, you know, weak pointer gang, I I don't understand why anybody likes weak pointers, but whatever.
They're like they're such a pain in the ass implementation-wise, unless I mean, unless you do the generational index thing. That's like the only But, like why? It's just not good.
It's not a good way to do things.
Because like if your weak pointer is null now and you wanted to use it, what are you going to do?
Like either you didn't want to use it and and therefore you shouldn't be holding a pointer, or you want to use it.
But, but now you're like, "Oh [ __ ] the thing went away.
What do I do?"
Must have missed the talk where I talk about how to select what to convince the people to work on. I mean, >> [clears throat] >> that comes up in like to some degree in literally every talk.
Like why do I do these talks? It's because these things are interesting to me.
Why are these things interesting to me?
Well, because Wondering what I think about stackful, stackless. I don't give a [ __ ] about coroutines. I don't I don't know why people like them.
All HTTP calls and database calls block the thread. Yeah, well just have a thread do that.
I don't like Like it doesn't take much to start a thread and give it a function and say do this function, right? That's the thing.
And so, the reason I don't care much about coroutines is because they take all this extra infrastructure to give you like a small amount of syntactic sugar on top of that. Now, this becomes a little bit different if you have a different thesis about the language. Like So, for example, Go has a thesis that it makes sense to have a 57 quintillion coroutines, most of which are asleep, all right? But, I don't think that's true. That doesn't make much sense to me at all.
So, like I Why can't you just have a function and say, "Job system, please do this."?
You know?
How do you design a satisfying ending for the game? You know, the answer to that is different for every game.
How do you handle recursive dependencies?
I mean, in this language they're just like automatically handled. I don't I don't know what the problem is.
Is the metaprogramming system basically just macro maxing? No.
No.
What are you talking about?
That's That's actually an offensive question the way that you phrased that, and it's like so clueless about how the language works, you get a temporary ban for that.
Don't ask intentionally aggravating questions when you don't even know what you're talking about. Holy [ __ ] It's just not polite.
It's not polite.
You could do async to async? I mean, I don't think So, here's the thing.
You never really want to do anything totally async when you're reading a web page anyway, right? It's like because if you're going to somewhere to request some data, it's cuz you want to use the data in a second, right?
It's just you might want to do three things at the same time because the web is all messed up that way. So, yeah, you just do the three things at the same time, and then you wait until they're all done, and then you go, right? Like that's fine. That's That's a multithreaded program thing.
I just I don't really understand what coroutines really gives you apart from oh, I'm in a super high-level programming language, and so I can pretend I that I have this certain infrastructure, right? But, this isn't a super high-level programming language in that way. I mean, it's very high-level for a systems language, but it is a systems language.
So, you know.
>> I mean co-routines and the the other reason why I say that I don't think much of them is just they're like a lot of things in programming languages and frameworks and abstractions and all this stuff, right?
There's this very, very common pattern.
And the pattern is this thing looks tidy and convenient and neat for small, easy problems.
And then doesn't help you much for difficult, gnarly problems.
That's like 98% of language features and abstractions and all that, especially in the past 20 years.
And the problem is things that are easy are already easy.
Why do you want to put Why do you want to spend the complexity budget of your system on making things that are easy 20% easier?
I mean, maybe maybe if everything you do is easy, then it makes sense to accelerate that by 20%, but that's usually not how it is. It's usually you blast through some easy stuff and then you hit one of the hard things and the hard thing is pretty hard.
And like, every all the design that I do is to help with hard things.
Because that's the limiting factor on what we're able to accomplish is how many hard things are we able to do?
And co-routines is one of these things that helps you with easy things and I just I don't care about that.
The problem is you block the thread holding the connection. What?
You No.
What? No.
I mean, unless you want to, no, you don't have to block the thread holding the connection.
Implementation-wise, it's potentially more performant than a gazillion OS threads if you have a very, very large number of them.
But nobody does.
Nobody does. Like the example that I just gave you.
I mean, again, there's there's two separate worlds, right?
There's the web world where people think about concurrency.
But concurrency, as I always say, is kind of a weasel word.
In the game world and in the other high-performance application world, you care about parallelism.
Parallelism is a stronger word than concurrency cuz it means you're actually doing things at the same time.
Concurrency means the things may be overlap somewhat. It's a very weak word.
Or it you know, the things maybe are unordered.
Right? Like what?
Um so parallelism means oh, we're actually using the hardware that we have to get the task done more quickly. And if you want parallelism, then the number of threads that you have should be related to the number of cores that you have.
Okay? And there's no reason to create threads for everything like in the web example that I just said.
You just write a five-line function or whatever that gets the page and puts the result into a known place and you give that to the job system and that fires and and then it's done. You don't create a thread for that, right?
You don't want to create a thread for that because you don't want tons of things running all the time, right? So One of the things he was trying to implement is to park jobs that are past a predetermined deadline.
Wouldn't co-routines help?
Since Windows dropped user mode scheduling blah blah blah. I don't know anything about user mode scheduling in Windows anyway. Um but wouldn't co-routines help there? I mean you could do that with co-routines, but you can also do it without co-routines.
Like Okay.
There's one very fundamental thing about programming in systems languages or many languages, but you know, like functional style languages give you primitives to deal with the following thing that I'm about to say.
Uh when you're programming in system languages especially there's this thing where your control flow is interleaved with like the stack, right? There's this implicit data structure called the stack that has to be there for you to run.
You know, and as you call functions and return from them, the stack bloops up and down and all that, right?
And then the thing about what you're talking about, about suspending some code, naively in a systems language you're like, oh, I don't know how to do this cuz I called all these functions and like I'm just on the stack somewhere and I don't know what to do, right?
But there are two basic ways to handle it.
One is on most systems languages, we actually don't provide a fundamental way of doing this, but you could implement it yourself, but you know, in C back in the day, you would use setjmp and longjmp and figure out the range of the stack and you would just copy the stack if you wanted to do that, which is maybe expensive back in the day, but these days is very cheap cuz stacks are not that big.
Um you could do that, right?
Uh but but I wouldn't prefer to do it that way anyway. What I would do is um just have So so the the way to become more powerful in situations like that is you just disentangle the state of the job that you're trying to do from the stack, right? And that just means you have a data structure that represents the task you're trying to do.
You have a function that just iterates over the upcoming tasks and looks at them and makes progress on them, right?
And once you centralize it in that function um you uh you know you can just yield if something is taking too long and whatever and go to the next one.
That's kind of like writing your own scheduler, but it's tremendously, tremendously, tremendously simpler because it's only a simple set of well-defined things that you know everything about, right? Now, of course that by itself implies some constraints on the code. So you can't call something that blocks indefinitely because you wouldn't be able to yield it, right?
But like you know it's fine. Just don't do that.
Concurrency equals using same core.
That's not true.
No, concurrency is not even that well defined.
But two things on different cores are concurrent for sure.
It's just concurrency like I said, it's just a weaker word than parallelism.
I'm saying a timeout fires. No, not necessarily.
The what I was outlining is more of a cooperative thing. Um like you're talking about with co-routines, but co-routines implies a lot of things that are not really necessary if you just need to solve this problem within your own system. Like the thing is, a co-routine abstraction is it's like built for customers of this language feature and so it does a lot of things to handle a lot of things that people need to do in various cases that you don't necessarily need to do.
Right?
Oh, you meant to reply to the earlier question. I see.
All right. Anyway it is time for me to head out. Thanks, everybody.
Uh let's raid somebody since um since it's a while, sometimes the rating is grim, and we don't know how to do it.
Um >> [snorts] >> Who shall we raid?
Who shall we raid?
Travis Roman.
Okay, we'll do that. I hope it's good.
Thanks, everybody.
And uh see you later. I'm back from traveling, so we might do more streams.
Who knows?
Who knows?
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 views•2026-06-01











