Most of this kind of content comes off as relevant/topical but mindless entertainment. This is not a "deep dive" of anything that I could practically apply in my daily work. It feels good to think this content might add value and then to subsequently consume it, but it's effectively junk food.
I used to spend a lot of time watching crap like lex and primagen before it became obvious that these kinds of information channels are not meaningfully enriching despite sounding like they should be to a casual observer.
> Open source is the very worst thing currently going on because it is so incredibly exploitative, it's far more exploitative than any actual company is of the workers who work at the company.
> Even the people who are getting paid in open source are getting massively underpaid to do it compared to how much the people who are using their code are making, it's nothing compared to the power that is accreted by the people who have co-opted that work thanks to the open source model. And then mark zuckerberg gets to define how the internet works despite having paid for almost none of the software that his company actually needed to make that work.
> It's like feudalism or serfdom, these people did the work and got nothing for it. It's like you took the worst aspects of capitalism for workers and the worst aspects of socialism for workers and put them together, that's open source. You get no power and you get no money.
> It's exploitative whether the people chose to be exploited, just because someone chooses to let you exploit them does not mean that you didn't exploit them. And for the record that's how most exploitation works; convincing people to do something that turns out to be very bad for them and very good for you, and that's exactly what the open source movement has turned out to be.
> I really don't see the "we post stuff on github under a gpl2 or lgpl or apache or mit license", all that is to me now is just exploitation. You can say that there's solutions but until someone demonstrates that those solutions work, it's the standard "real communism has never been tried" argument. AGPL is the only thing that I've seen so far that's an attempt to fix these fundamentally unfair compensation practices.
Casey is far more measured, careful and accurate. Casey feels like an engineering educator first, who happens to make YouTube videos. I don’t always agree with Casey’s technical opinions, but he seems like a thoughtful guy who thinks things through.
When has History of any kind ever held practical value?
I should also add that even interviews are valuable. Coders at Work is fantastic at that and drawing out technical opinions and reasoning; notably the subjects interviewed don't all agree and have sometimes drastically different work styles and preferences. (And also adding from another comment, Turing Award Lectures are great history, and Uncle Bob even has a history book out now on influential programmers.)
But I'm curious who you think #3 is.
I skimmed through the video because I don't have two hours but there's no lost knowledge in it, he's going over well known papers from Dijkstra, Hoare or Knuth. The paper he bases most of the talk around Knuth's Structured Programming with go to Statements is his most often cited work, there's a very high chance you'll encounter that early in any undergrad course. So the answer to your question is, pretty much at any local uni with a CS course.
It’s a pity there’s not more people like him. I’ve met some incredibly smart people in the FP world. I wish more of them made approachable YouTube videos explaining what they know. I recently learned about “Safe Haskell” which, if adapted to rust and other languages, could solve a lot of the security problems with npm and cargo. But nobody knows about it! We need FP Casey.
There's two reasons Safe Haskell is substantially worse than what Rust does. Safe Haskell works by annotating code that is safe, but that's entirely backwards. We need to annotate unsafe code, and explain in plain English exactly why it is okay in that particular instance (of course it would be better to explain in code, like, give a formal proof that is checked by the compiler, but then it isn't unsafe anymore!). Safe Haskell answer for that is to annotate good unsafe code as trustworthy, but that doesn't work because it doesn't goes in detail on why the code is trustworthy (to do so you really need to go into the details, you can't handwave it). It's the // SAFETY comments that are at the heart of Rust's unsafe, carefully explaining safety invariants that must be kept (specially important if we are modifying code), not unsafe { } blocks.
The second reason is much simpler. It's optional, and approximately nobody uses Safe Haskell or cares about it. If people used it we would have something to improve upon. So Rust achievement here is mostly sociological, it's a community of programmers that care about safety. Which is good given that a Rust program typically have much more unsafe code than a Haskell program.
Here's a thread about Safe Haskell issues https://www.reddit.com/r/haskell/comments/zwkqke/deprecating... that links to https://discourse.haskell.org/t/deprecating-safe-haskell-or-...
And an older thread https://www.reddit.com/r/haskell/comments/msa3oq/safe_haskel...
This would guarantee - at a language level - that leftpad or log4j can’t root my computer.
Safe rust doesn’t give this guarantee. Safe code can still make arbitrary syscalls. Safe rust can convert a path string to a File. Or open arbitrary network sockets. Rust also doesn't have a way to import a crate but forbid the use of any unsafe blocks.
I want to be able to use 3rd party code from cargo without getting hacked. Right now rust does not keep me safe from these supply chain attacks.
I don’t know enough about safe Haskell to know how close it tacks to this. But that’s what I want.
But if you don't want an ironclad guarantee and instead you're content with making wrong code obviously wrong even if it's not formally verified, then I recommend Haskell with a capability system (what the Haskell world calls an "effect system"). As far is I'm concerned there are two practical choices in 2026, Bluefin (mine) and effectful (one of Bluefin's inspirations)
On infection, I think it's a bit like being infected by mitochondria :)
While I suspect he could do research, he also just isn't personally experienced in large tracts of SWE culture as others. Others have worked a far larger variety of jobs in the software industry and thus tend to have a broader idea of the cultures and how they've evolved. In a recent clip I saw of him and others discussing how BS are various phrases engineers say (the root of all evil phrase being one of them), he hadn't heard of the YAGNI acronym/idea before. That's no fault on him, programmers live in different worlds. But regardless of one's feelings about such ideas, or whether they've heard of them or not, a history of SWE would have to cover them and the schools of thought that originated them. And this is just one minor thing in living memory and recent careers, there is so much from before he was born that has to be researched and if possible also talked about with the older practitioners who are still around and remember things. If you don't already have some awareness of things that should be covered in a history, whether from personal experience or just general curiosity about history that has led you to see such things before somewhere, the only hope is further research uncovering them, and I don't trust his researching that much.
Reading The Psychology of Computer Programming from the 70s was such an interesting read for me from a historical perspective as well as being able to see how some ideas they were thinking about back then came to fruition in some way or another. (e.g. Stack Overflow.) It's just one small part of history. A "complete" history as the top comment suggests would be better as a multi-author endeavor, would probably need many books, and that's if it could be done at all. In the meantime at least one can always go read primary sources and develop an idea of the history on one's own.
It's just absurd to me to point at Casey, of all people, as the most informed person who would be best positioned to publish something containing all of the history of anything broad.
Casey points out that many of the lessons they came to were so obvious that it just became how it is done that no one even remembers it was done in any other way. In the talk the laments it makes it really hard to track down who originally came up with these ideas.
Like I agree with most everything he says and I like to optimise my own software, but for my day to day jobs and contracts it's simply not feasible.
That level of performance and rigor is not what is demanded nor paid or appreciated.
E.g. in Enterprise circles it's still OOP from top to bottom.
Mixed with a tad more functional style due to varying adoption of that paradigm in the languages used by enterprise.
But low level optimizations are not interesting to these customers at all, even though they could help them with some problems.
I suppose it is a matter of what one works on, but that has been consistent in my career.
I have seen many be rewarded for choosing what I would deem intentional, gross negligence. But hey, those devs get work finished faster, and that's all that matters to the non-technical folks.
His dismissal of the argument Knuth makes regarding the hot loops could have been explored a bit better. I found it weird he didn’t mention the difference of types of programs of then vs now. Even today, in scientific code it is still absolutely the case a lot of the time that a huge chunk of the runtime comes from a single very very hot loop. It might be hidden in a library, but it’s there. Instead he focuses only on “program size”. Knuth samples where very small FORTRAN programs (compared to today’s standards). Today’s program are bigger but the fundamental number crunching primitive of “let’s compute stuff in a loop” remains. It’s just buried under a pile of extra cruft (data loading, parallelism, dispatching etc).
Now we just deal with a lot more programs that are of a whole different class compared to what they where doing with computers in the 70s. We have much more I/O involved. And hot loops don’t like being I/O bound.
iirc, in the talk casey in fact does goes on about how he tried to find examples, but couldn't. in the q&a, he was also asked about this further.
"I can't do anything because my program is I/O-bound" is more of an excuse / mental justification of why your program is slow instead of an honest reason for so.
This is backwards. I bet that by count, many more programs are written in domains where they're necessarily IO bound than the inverse. Anything that uses the network for its core functionality, anything reliant on a datasource whose aggregate contents are O(memory)+ size, or anything reliant on slow peripherals (lots of embedded software) are in this class.
Scientific simulations, HFT algorithms, video games, LLMs, etc.--the stuff in the other class--aren't inconsequential, but they're dwarfed in number by the class of software that spends 99+% of its time waiting for IO. Hell, entire programming languages (node.js) have been created in response to that proportion.
You're not wrong in that there are some programs that could be doing more work in CPU/memory while waiting for IO, but those, too, are dwarfed by the number of programs that can't really do anything meaningful until IO completes. Anything that RPCs or IPCs data is generally going to be waiting for a complete RPC IO to finish before doing compute (and even the most granular RPC protocols tend to communicate in pretty big, slow chunks to maximize throughput). Lots of software waiting on local hardware (e.g. storage) is similarly doing IOs in pretty big pieces--maybe page-sized, or disk-block-sized, or file-sized--and can't do much meaningful CPU work until that's done. In embedded, it often behooves programs to get as much IO-sourced data read or written as is possible with available resources before switching back to CPU work--doing this increases throughput on slow hardware, and can also improve power efficiency.
Put another way: modelling IO as a stream with something like io_uring won't save the end user much latency if the completions inside the ring wait for slow, batched IO, or if application code needs to see completed transactions before proceeding.
Latency, throughput, power, hardware cost--those often trade off, and there's no free lunch.
And a GPU does orders of magnitude past this.
Networks are not even close.
https://chipsandcheese.com/p/a-new-year-and-new-tests-gpu-l1...
Most of the stuff I work on is almost exclusively network I/O bound. I wouldn't say it's a _result_ of bad engineering practices, though. One group decided on a particular system that's also public-facing, and the group I actually support prefers a more internal-facing system. It also doesn't help that the budgets for both projects are completely separate and firewalled from each other by law. Growth opportunities don't apply here because I deal with a captive market with legally-forced customers.
Such programs are not necessarily impossible to optimize. One common optimization is to use an event loop, allowing just a few threads to handle thousands of concurrent operations. Because while a thread is waiting for I/O in one request or unit of work, in the meantime it moves on to work on processing another request/unit. Another common optimization is batching/grouping of I/O calls.
This isn't really true anymore. IO has bad latency, but modern SSD bandwidth is ~5-15GB/s. If your program is IO latency bound and processing less that 5GB/s you aren't IO bound, you aren't hiding your latency well enough.
That's nothing compared to modern memory bandwidth.
Not anymore, no. Your SSD, before any caching, does gigabytes per second of sequential reads. For any bytewise processing, except the most trivial of tasks, you’ll struggle to get above a few hundred megabytes per second with scalar (native) code. To actually keep up with a modern SSD, you’ll virtually always have to hand-write SIMD loops, minimize the number of syscalls with tools like io_uring, or possibly be smart about distributing tasks across cores without ruining the access pattern.
For instance, simdjson is famously fast but I don’t believe it can keep up with say a high-end PCIe Gen 4 SSD like a Samsung 990 PRO, let alone the latest-and-greatest (and, literally, hottest) Gen 5 stuff. And I know of no Unicode normalizer that would be able to do a gigabyte per second on general inputs (not ASCII, not Latin-1) simply because the latency for dependent lookup table accesses is absolute murder.
What your comment demonstrates is that it is possible in some cases for I/O to be fast enough to not be a performance bottleneck for certain kinds of programs. But not that I/O is not slow.
And I think you’re being unfair labelling my couple of examples “some arbitrary algorithm[s]”: my choice was indeed arbitrary, but it’s also immaterial. The general setup would be that you’re processing elements in a loop and that your iterations are serialized (as they usually more or less are before you get around to optimization). A loop body of even three lines of C is likely to have a latency of 5–10 cycles or so, and you’re running on a core clocked somewhere from 5 GHz (desktop) to half that (server). So the best you should expect is ~500 MB/s if your elements are bytes, ~2 GB/s if they’re 32-bit integers, etc. For very simple tasks (that are also somehow not susceptible to vectorization), it is possible to not lose this order of magnitude and get down to almost 1 cycle/element in scalar code, but that requires heroic effort[1].
In saying that there are some novel and very clever algorithms that continue on without seemingly necessary boundary data, that then self correct when the data comes through, thus completely hiding the latency at the cost (in both accuracy and time) of running a correction process.
I would very much prefer something written down, so I could absorb this at my own pace. I know, gift horse, but still.
I used to do manual labor and I would work my way through like eight hours of audiobooks per day.
I would like to learn to focus... (https://youtu.be/1IRn8BN3Qhw?t=331)
I used read a lot of books when I was younger, then slowly stopped, and found getting back to reading quite hard as well. Armed with the knowledge that I used to be able to do this, I just forced myself to. And after a while, I found I had no trouble committing any more.
The basic idea is that the origin assumes a highly critical inner hot loop, don't assume where it is, and optimize there.
There's some other time spent saying this justifies slower abstractions for maintainability elsewhere.
I think the GOTOers just died out.
Some day null, statements (rather than expressions) and side-effects will have always been wrong.
The actual GO TO complained of is, like the jump instruction in machine code, just entirely unbothered by context. Want to go from the middle of this code about employee payroll processing to mid-way through initializing a weather simulation? No problem. Well. No problem for the machine, for a human programmer it's a complete nightmare. Actually that's putting it mildly, nightmares have more structure. You cannot do anything like that with for example C's goto.
You compiler can, and in a few cases (that's what the discussion about the tail-call optimisation is about for example) it will, but the program you wrote doesn't do this and so you don't have to try to keep the whole program in your head.
So in that sense GOTO died out with, maybe BASICs? I think the BASICs tend to have that wolf nature GOTO feature, but nothing modern has it.
However, having written a good chunk of ASM in my life. I don't think jumps or branches are really that hard to follow. Jumps/Branches and GOTOs specify the next location. It is not as though one has to guess where.
It's not the arrow, it's the archer that is the problem.
My guess is that your ASM is inflected by structured programming everywhere. Yes, unlike COME FROM we can see where we're going next with GO TO but if you go back 60+ years there is some scary code that even today's optimizers probably wouldn't emit because it's too crazy. Suppose calculate-total-fuel ends with three CPU instructions which copy register F into register H then add register C to it and multiply the sum by four. Over in locate-horizon it so happens we need to add two things together and multiply them by four and we could do that last. So, if those two things were in registers F and C we could just GO TO that last part of calculate-total-fuel.
You're correct that we don't need to "guess where" it goes, but good luck understanding why the program works when it's like this, let alone the ordinary maintenance work of making small modifications.
I think you're probably right. To expand on this:
In asm, you can have things that are clearly functions. You have a stack discipline going in and out of them. They end with stack cleanup, then a RET or some such, which pops the return address off of the stack and jumps to it. Within that function, you have JMP instructions (or whatever) that move around within the function. You may also call other functions, by pushing variables on the stack, and then calling JSR or whatever to push the program counter on the stack and jump, and when those functions return, you'll be right where you were in this function. That's all sane, and it's "structured assembly".
Non-structured assembly would be like the example in your second paragraph. You're in one function, and you JMP (not JSR) into the interior of a second function. Or, you simply don't have functions, just labels that you jump around do. That's not structured, and not sane.
(I am the GP)
Your response was far better than mine. If those instructions were executed more than a couple of times and the constraints/assertions were identical, I'd absolutely throw them in a function. I'll handle what I need to before/after the function.
I would never branch to some coincidental label. That is why I love ASM so much. If you are sloppy or lazy, you will most likely be punished severely for those choices.
(Tangential, but when I first learned ASM in college, I felt like I learned more in that one semester than all the sum of all classes in my entire degree.)
When you need to do X here and there, you write code to X and then you call it where it was useful - you don't have code in one function just jump to a label in a completely different function because, in this era where structured programming is taken for granted - that seems crazy. And it is, but only the same way that chattel slavery seems crazy today, in the Antebellum South it was just usual and likewise in 1950s computer software just jumping into unrelated code was normal.
> My guess is that your ASM is inflected by structured programming everywhere.
I am not certain what you mean.
> if you go back 60+ years there is some scary code that even today's optimizers probably wouldn't emit because it's too crazy.
Why was this as common as the allegations lead me to believe? Was it just a product of time? No better way to handle such logic at the time?
As for your example, I know it is intended to be interpreted trivially, but I just want to clarify I understand you correctly. Is the issue due to locate-horizon depending on logic from a completely orthogonal operation?
If so, I see the red flag immediately. However, I do not see an issue with creating a separate function. I'd just have to be damn sure H was not storing anything used for some other upcoming operation prior to the function call, I'd check F and C for valid state (if necessary), take other potential side-effects into account, etc.
It feels a lot like the DRY advice being abused in higher-level languages, you know? I agree with expression, "duplication is better than the wrong abstraction."
Same reason that nobody did the Fosbury Flop at the 1948 Olympics - Dick Fosbury hasn't shown this technique yet and it's not obvious if you've never seen it that this is a better way to perform an Olympic regulation high jump. Twenty years later, he does exactly that and wins Gold and by the 1988 Olympics this is how everybody does a high jump, but in 1948 nobody knows it.
Your instinct to "create a separate function" is exactly Structured Programming.
So we can jump over a variable declaration which is pretty confusing, but we can't jump into unrelated code.
Also while COMMAND.COM can't be as old as BASIC it must be pretty old.
It's also a little fluffy. It's basically the history of how the book Structured Programming came about, because it's that book that essentially caused Knuth to write an article that contained the quote.
A lot of it is fairly interesting but it also highlights a big problem I do have with Muratori. He generalizes from self. He didn't fully understand or appreciate the quote about premature optimization, so no one did. And even though he's been told what it actually means, and was probably pointed to the full quote, he would stick on his interpretation. It's likely someone he views as "higher", like Jon Blow, challenged him and then he took the time to actually look at it.
He ain't wrong though.... most people definitely don't get the jive for sure. Knuth was talking about a massively different kind of optimisation than what we do today yet people keep continuing to parrot the 97% figure uncritically like as it was some gospel. [0]
Though lately I've been uploading the audio to AssemblyAI, I somehow still haven't used up my credits after several years lol
At one point I built a system that would summarize the transcript and I'd be able to ask questions about it, but Gemini can do that natively now so I usually just use that.
It is something you can maybe whip up with the help of an LLM but then you're left wondering whether it is actually communicating what the video intended to begin with, as you wouldn't be as knowledgeable about the topic, one wouldn't be able to spot the parts where an LLM interpreted something horribly and thus reaching the wrong conclusions.
For all of the above, I do not consider audio transcript to be of any help when one prefers written content. It is useful for translation or people with hearing issues, but both of those receive help of the visual parts to convey the topic.
(to be clear, I'm a big fan of Casey)
Titles aside, his talk is really insightful and it is super interesting to do a deep dive on these old computer/programming topics as the modern concepts were being discovered
Yeah Ive been meaning to watch that talk - I love listening to pretty much anything Casey says/does. He's extremely thoughtful and fair.
Exactly!
Thank you for bringing a term to a thing that has been bugging me: people who purport to be devs but spend most of their time on podcasts and blogs talking and writing about being devs, rather than just being devs.
I’m sure you can find bugs in the work of any game dev you would consider legendary, game implementation is generally very messy
There is massive amount of knowledge in there for anyone bothering to actually learn something and it was all provided free of charge. Hats off to Casey for sticking to it as long as he did.
The craftsmanship is dubious. I think it's a problem that people assume Casey knows what he's doing when so often he's like "We're doing it live" and Casey's hand coded solution is pretty bad whereas the thing which came in the box is very good. Casey understands Casey's version, and that's an upside if you are Casey but you are not. If the result was a finished game then hey, whatever, the game was finished and that matters. But that part didn't happen either, so then it's just like watching Tsoding or something.
His second attempt, no matter how he made it, was made with the context of his earlier mistakes.
RAII doesn't lead to spaghetti code necessarily. If anything, "unity builds" would more encourage spaghetti as it's easier to reference anything else in your build.
For video games you can get things pretty badly wrong on the technical front these days and deliver an excellent game, that's one of the things Blue Prince demonstrates really well, a lot of the guts of Blue Prince are a trash fire, but the player will not ordinarily notice so who cares? Rebecca (of Rebecca's Pixel Quest) noticed, hundreds of hours in, that if she has two of certain special items the game gets confused. That's the sort of bug a better engineer wouldn't have, but she'd been playing the game for over a year when she noticed.
Fine, as I recall, Doom data assets are searched linearly whenever they need to pull new data. So if you switch to the chainsaw, and need to rev, the game does a linear scan of all graphics, maps, and sounds looking for the vroom noise.
There are many different data structures that could perform this lookup faster. These have been known since the earliest days of computing.
Does it matter? No. Engineering is all about trade-offs. A linear scan was obviously fast enough and simple to implement.
Similarly, if walk monster manually trolls the map, that does not say anything about Casey in isolation. I believe all of Blow's games use a custom game engine, so unless a nav mesh system was already implemented, that was going to take additional work. The walk monster may have been better bang-for-buck.
There are some tradeoffs here, my instinct would be to bring hash tables into play and that's perhaps a mistake because it means you're doing fewer reads but more arithmetic and on some hardware that's a bad trade. But "linear search" is only the simplest and probably not the smartest option.
Casey is professionally best known for his work at RAD game tools (a highly successful middleware provider for game development back in the day), not games he himself developed.
What he is most highly regarded for is his teaching, particularly the Handmade Hero series on YouTube, which various programmers directly attribute as being responsible for their own professional success to a large extent.
He did work on the video games Dungeon Siege and The Witness afaik, but that's not what he is known for.
He also made one of the fastest terminal emulators (refterm), purely out of spite, to show Microsoft they were full of shit in their answer to an issue he posted to the Windows Terminal github. This directly led to performance improvements in Windows Terminal.
Bink was the cutscene video codec for a long time and it's still the most popular option by far. Kraken compression is so good Sony worked with AMD to make a hardware decoder for the PS5 and paid for a general license that lets games use it for free. They are probably stronger than ever in terms of games using their tech and collected license fees.
True, though they've been acquired by Epic since 2021. They keep the RAD Game Tools branding, but aren't their own separate company anymore.
Oodle/Kraken is mostly the work of Charles Bloom and Fabian Giesen, a couple of other "legendary game programmers" at RAD, but who aren't quite as visibly prominent as Casey has been in the modern software developer mediasphere.
And I never left Python, the slowest language around.
AI is only going to make the problem worse unless you know what to look for.
this shouldn't be right, wtf
Also I learned to program in Turbo C and Turbo Pascal with its debugger and nothing comes faster (at least nothing single threaded)
When did you start using computers? I'm getting older now, and some people weren't alive when I first used a computer.
It's because the older programming approach was to just tell the computer how to do the thing - and the modern approach is to write a framework inside which you write a framework inside which you write an inefficient version of the thing because it's constrained to the tools available in the framework stack.
Old-school implementation of "scroll up": copy pixels then redraw the pixels at the bottom.
New-school implementation of "scroll up": delete virtualized rows from the beginning of a DOM table and add more to the end. Change the height properties on different parts of the scrollbar. Relayout the whole DOM, several times if you're not careful. Redraw the whole screen.
I don’t know the extent to which he contributed beyond that, but he is therefore by some reasonable definition _a_ game developer.
[1] the-witness.net/news/author/casey/
Like they can't comprehend the fact that these things only happen if there is an incentive for it
I think its because they work in games where there is a business incentive for performance, users care a lot if framerate suffers in a game
They are so used to working in games that they take it for granted that the business incentive for performance exists
As someone who has worked in both AAA games and big tech it just comes across as a bit naive to me
Yes it’s incentives - but why these incentives exist and not others is an interesting question to study.
In the 2010s we pushed everyone to learn how to code and maybe lost some of our higher standards. Maybe we’re doing that now with AI?
Maybe broader social and economic incentives have had a lot of short term thinking of late? It’s hard to organize society or a company to go in one direction very long before incentives completely change everything. Who knows, maybe that’s a feature, not a bug.
It’s worth asking though why we have this software industry and not another one. I’m not convinced it’s for legitimate reasons.
Then we can talk about how we all pay the increased cost in energy and materials, and so forth.
Optimizing code for max performance does take work. But just not doing incredibly dumb things and writing simple programs just takes education (and re-education).
I can’t count how many times I’ve replaced a distributed system with for loop.
It takes a lot more work to keep performance good in a large project than just letting it degrade.
I find Blow in particular a bit naive when it comes to the complexity of modern non-game software. Games are very complex, but Blow puts them on a pedestal separate from other software, as if a web backend can't be as complex. He calls software slow while simultaneously ignoring most of the functionality.
He's essentially never had to deal with distributed systems, or anything that allows multiple users to use the same system, with all the performance and anti-abuse issues that come with that.
His opinions about game development are insightful, and his thoughts on craft can be quite inspiring, but I think he could benefit from a stint on a (good) big tech server team to see some of the things he's currently missing.
In fact, Jon played a crucial role in the invention of the first MUF worm. We had just finished an extension to MUF that permitted triggering programs wherever a text string was expected. This gave a great flexibility and functionality to run MUF programs passively, by third parties, all kinds of new ways.
Unfortunately this also gave rise to a "worm" type of MUF that replicated itself whenever it was triggered passively. We went a little crazy when this was discovered, but it was all part and parcel of a multi-user game system, where there were permissions to consider, and multiple read/write/execute access to objects that should be owned by their respective player characters.
Jon Blow also inspired a lot of my exploits as I tested other systems of MUD programmability. In that time, TinyMUSH was also experimenting with a language that was more akin to scripting, and boy was it vulnerable. TinyMOO was also coming out, with a rather revolutionary programming paradigm. So in the mid-1990s, just in the insular TinyMU* world, there were at least 3 branches of programmable MUDs being actively developed.
Hopefully Jon could recall my greatest contribution to the corpus of early MUF programs. On Atlantis MUCK, I programmed a simulation of Conway's Game of Life. Of course, there was no animation possible and there was no multithreaded execution possible, either. So my program was given a starting board of Life, and then computed each frame in sequence, output it into the text stream of the game, and terminated after N iterations. Meanwhile, the entire game server locked up, because it could only run one MUF program at a time. Everyone else's commands and input would be held until my MUF program finished running.
This was a real issue, of course, and Jon and I worked to mitigate the problems caused. I think, ultimately, we just limited the number of iterations or the number of instructions that could be executed by any one MUF program at a time.
But Jon and I collaborated on a tutorial for player-programmers, and he helped us find and extinguish many bugs. And these were very complex systems, with 64 or even 256 simultaneous players.
Perhaps Jon has forgotten some of those lessons, but perhaps not.
That said, and this is coming from someone who (sadly) missed the era of computing you're describing, I think there's still a difference between dealing with a 64-256 player multiplayer system, and scaling a server application across dozens? thousands? of machines, across the world.
My limited research suggests that MUDs run almost exclusively on a single machine (?), or even just having a small number in one location drastically simplifies the problem space.
It doesn't really contain anything new or earthshattering, but if you find diving into the history of programming as a discipline interesting, it might be for you.
I would recommend it to anyone who liked the rambling style of "The big OOPs", but imo that one was better. I still liked it.
The best thing you could take away from this lecture is something a reasonable person should take away from the original "root of all evil" saying anyway. Measure. Measure. Measure. If you aren't measuring that's not optimization it's masturbation.
Ironically in the process of measuring for a third time yesterday I tripped a bug in Bill's language for which I opened an issue. This is not the goal of measuring three times but merely a happy accident.
Along the way Casey discovers (?) that Structured Programming means just what we today call programming†, that software was a lot smaller in the days when 4096 bytes of RAM was a good entry level option and that loads of these famous people from 1970s computer science knew each other.
† And knowing about this is one reason the Structured Concurrency people want that everywhere. Very possibly there's a future where it seems silly that people once wrote programs which did not use structured concurrency.
There is some space for this "Estimate the theoretical maximum" as a high level insight, if the software needs to do a thing which your estimate says is impossible that's important to address up front but I think for practical software engineering you're much more likely to need profile-fix-repeat
Actually measuring is crucial and an estimate is not a measurement. I think one of the reasons many in the Handmade Community don't like measuring is that it too often ruins their "estimate" of how the crap they've written is achieving a "theoretical maximum" in favour of a boring fact that it's much worse than alternatives.
That is you know the data is some size, and memory throughput is some rate, and clock cycles is some rate etc...
You are entirely correct about the line of thinking if your assumptions are down a different line of thinking such as algorithmic estimates though, where you might miss some better way of doing things.
This can be applied roughly to anything. I find it very handy when thinking about CPU/GPU performance as well. For instance knowing that at 5GHz you have 5 billion clock cycles per second, which depending on instructions and pipe lining etc... can be roughly 5-30 billion operations per second per core tells you how long some process should take if you know roughly how many operations are required and the data size you are operating on.
Obviously as you drill down things get much more complicated, but they give you some rough idea about how fast things could be under some set of assumptions. Very similar to how a physicist works with models and assumptions.
1. Your hottest loop is spilling registers which only shows up as non-local cache thrashing (i.e. some other random code becomes slow) or randomly slow instructions i.e. "why is this xorps to initialise this float suddenly slow" due to pipeline stalls
2. Your code stops fitting into cache due to the code bloat, there's no one method which is slow, everything is slowed down by a percentage factor
3. A lot of useless work being done like temporary strings being copied everywhere
4. Your code is "I/O bound" because all the data you're accessing is scattered all across memory, leading to completely predictable TLB stalls
It's very easy to make a large program, quite a bit harder to make a small one...
I'm on AMD and uProf isn't that good (it often fails to match PDB to source, it's slow / crashy, stuff like that) so I mostly use Superluminal myself (has godly UX) and only drop down to uProf when I have a suspicion and want to gather hardware stats.
The problem is knowing what to measure. There's another saying
"When a measure becomes a target, it ceases to be a good measure."
As an example from memory, there was a game dev company that celebrated they had maxed out the cores on the PS3. That didn't mean anything though, anyone can max out the cores by filing them with bad code. But hey, their "measurement" told them they had maxed out the machine
This can be a problem, but much less so because so often we're doing "easy mode" where we don't need a proxy. The "it ceases to be a good measure" is because you're measuring a proxy. You wanted to deliver happiness, you measured wealth because it was easier to measure but seemed correlated and now you've got rich miserable people, oops. But software engineers can often measure the actual thing they want to improve directly, not a proxy and so it cannot cease to be a good measure.
Latency and hitching are annoying to measure, so for a long time, they were pretty much ignored. That has improved and hopefully will continue to improve. There is the bufferbloat initiative, gaming magazines take frame time histograms now, input devices and screens commonly have their latency measured. But latency is still under-measured - for GPUs / GPU drivers, for all software, for games and particularly for websites.
If your goal is fast software it can be measured quantively and you’re likely to improve the actual thing using those metrics.
Why not measure performance for which there are many good metrics.
People still do that today. They run some LLM or gen AI type app. See all the numbers reach high percentages, and wrongly think "this app is using all of my machine's potential"