"Is performance still an issue in this era of cheap 486 computers and super-fast Pentium computers? You bet. How many programs that you use really run so fast that you wouldn't be happier if they ran faster? We're so used to slow software that when a compile-and-link sequence that took two minutes on a PC takes just ten seconds on a 486 computer, we're ecstatic—when in truth we should be settling for nothing less than instantaneous response."
Not sure if I want to laugh or cry at how 100% relevant this still is 20 years later...
I've had people tell me all of the extra bloat/slowness in modern software is because it has more features, and because accessibility / localization is a thing more often. I'm not sure I actually believe that's true. Maybe accessibility and localization contributes to bloat/slowness, but that doesn't mean it couldn't be much much more efficient and keep the same features.
The numbers don’t really add up. Computers are a hundred times (replace with actual value, but it should work even for a 10x increase) faster, yet the feature set hasn’t increased by anywhere near that factor. Also “feature” is a big word, usually a single feature doesn’t even eat up that much performance.
I think it’s rather — just as Moore’s Law — a psychological phenomenon rather than a mathematical one. There’s just so many seconds we’re willing to wait and at one point, we don’t even care. Also the Internet hardened us for long wait/download times.
Exactly this. Anyone who was gaming and "websurfing" back in the 90s will recognize that load times today are no better than back then, and are often times much worse.
And that view isn't a psychological rewrite of the past. I regularly game on systems from both the 90s and modern day, and the load times for modern games are usually much worse than the CD games of old. The funny thing is that people would complain like crazy about CD load times back then, even citing it as a reason why CDs could never become mainstream.
And yet, here we are present day with obscenely shitty load times for most software.
I think the one area that has improved dramatically has been video streaming though. Real Player and the like were terrible even for their time.
I dunno... I recall loading stuff off cassette tapes onto C64.
But I was there in the 90s, too.
Sure, the load times on an NES are better than, say Fallout 4, but I remember starting up Ultima 8 for the first time and that was some sincere amount of wait.
I think that things are much better now, at least in the few games I've played in the last couple of years (Bioshock, Detroit: Become Human, Fallout 4, Red Dead II). The content is way more developed, and instead of loading a pile of floppies, I just wait for it to DL what it has to do. Granted that takes a while, but at least I don't have to hand feed it.
The content is way more developed, and instead of loading a pile of floppies
Ahhhh ok you got me there. Floppies were terrible, and playing games on a low end DOS machine was terribly slow. I have played modern games that were about as frustrating though, but only if they're completely broken.
I was referring to game consoles though. Load times on Sega CD on 3DO were terrible for the time and turned off a lot of consumers back then (though not the only reason those platforms failed, they were just the slowest of the bunch). But the load times in modern games is typically far worse than those systems ever saw.
I switch between modern and retro era systems frequently, and I find modern load times embarrassing given what people were up in arms about back then.
Jonathon Blow tends to agree with me, FWIW. Check out some of his talks on the lack of optimization in modern software if you have the chance. Modern software should be a lot faster than it is given the hardware capabilities, according to him too.
I personally only game in short bursts so it's not a big deal to me to let the machine spend a whole damn day downloading fallout over a 10Mb DSL line.
I mean, that was better than spending the whole night DLing Commander Keen.
My view is that there's a certain amount of time that I'm willing to wait for certain interactions, and that's pretty consistent regardless of the tech stack. So if I have to wait a bit, I do.
I'm far less patient with things like keyboard shortcuts, UX interactions... but I feel like a lot of those really have gotten way, way better (like, no more floppies). Perforamnce is just one aspect of UX, and while you're right that it could obviously be better, there are so many other parts that are so much better (and performance really isn't worse that it was when I was playing Police Quest V).
I remember when I tried to run Doom on my old 386 HP and man was it slow haha.
I think nowadays, these online arena games take forever to load. Back in the 90s it was all about loading and performance. Quite the shift in gamer expectations.
I remember thinking I was a badass because I filled Wolf3d's resource meters all the way up.
I think one of the first actually useful programs I've written in my life was a conditional in the autoexec.bat script that let me choose different memory configurations. What fun times :D
>that load times today are no better than back then, and are often times much worse.
Uhhhh, well I don't tend to wait 3-5 minutes for a single .jpeg to load on a website any more. I can stream a hq video in real time over the internet, whereas downloading a single 30MB realmedia video so pixelated you could barely see what was on the screen would take an hour or more to download. A 3MB mp3 would take 5-10 minutes. There have been massive speed increases in web surfing for sure. I don't understand how anyone that used the web back then could think otherwise.
As for software load speed, the amount of data being loaded off a CD for a 2d or older 3d game is magnitudes smaller than the data being loaded from modern games. How many gigabytes of high res textures did those old games used to load? How many uncompressed HQ sound effects and music tracks? I remember installing multi-CD games and waiting and waiting,.then swapping the disc, then waiting then waiting, then back to disc one, more waiting, now disc 3.
I'm not saying those things are better, but there's no way in hell my old 486 could have loaded multiple gigabytes of data at the same speed my laptop or even my phone now does.
Uhhhh, well I don't tend to wait 3-5 minutes for a single .jpeg to load on a website any more.
That was not true on 56k in the late 90s. On a baud modem in 93, sure, but I wasn't talking about that.
As for software load speed, the amount of data being loaded off a CD for a 2d or older 3d game is magnitudes smaller than the data being loaded from modern games.
Irrelevant. The amount of multimedia on a CD was vastly more than the main memory available at the time. Plus you didn't have multi cores, SSD storage (or any HD) etc.
Well I was talking about 97-99 as far as internet browsing went. I don't really remember the internet before that. I wasn't allowed fuck around too much when we had dialup it cost too much. Yes it really was that slow. That was when I first started downloading music and TV shows. I vividly remember the waiting.
>Irrelevant. The amount of multimedia on a CD was vastly more than the main memory available at the time.
I don't follow. It's not like all available memory is ever used to load things from storage. All I know is, I can copy an 8GB DVD on my current computer with 6GB of RAM faster than I could have copied a 756MB CD with around 500MB of RAM.
I do agree nothing is optimized as well, but that's some hard nostalgia goggles talking there.
I mean the file size comparison doesn't really apply, because hardware back then had many limitations anyway.
We should be seeing much better load times than we are given current hardware, not incrementally better or even worse. Which is the reality, since no one optimizes anymore.
> I've had people tell me all of the extra bloat/slowness in modern software is because it has more features
Lately I've been making something of a hobby of replacing big scale-out Apache Spark ETL jobs with stuff that was hand-coded to use something other than Spark. Generally I'm finding that, with a little care, I can get a lot of these jobs done in less time on a single machine than I can running it on the Spark cluster. (Using code that's easier to reason about, too.) And even when I can't, I'm not sure it's enough slower to warrant the use of the cluster, on the principle that using half a rack worth of compute resources to get the job done in 45 minutes when you could do it in 60 on a single box isn't really a good tradeoff.
All that long-windedness by way of saying, these big data tools are kind of slow and bloated. They're slow and bloated precisely because they have more features. All the extra work they need to do to achieve reliability when you're scaling out has a cost. But that doesn't necessarily mean that the cost is justifiable.
A box truck is more capable for running errands than my Kia Soul, because I can fit half the grocery store in it. But I think we'd all agree that it would be an obscene waste of money to default to using a box truck to buy groceries and make Ikea runs, and justify that decision by pointing out that some small fraction of the time I'll need to transport more stuff than will fit in a Kia Soul, and it's better to standardize on a single model of car. In a computing setting, though, we do that sort of thing all the time.
I think people undersell the value of safety. Back in the 80's and 90's, it wasn't uncommon to drop into assembly to grab every last cycle of performance, since computers were so slow. We also didn't do garbage collection, and people were writing in languages like C and C++. Software from then was also prone to random crashes and freezes, which doesn't happen so much anymore.
We've started to come around with languages like Rust, but a lot of engineers have (in my opinion rightly) come to the conclusion that it's better to abuse the faster speed of computers to have a higher assurance of the software being correct. Could I conceivably get better performance if I wrote something in C and wrote a custom allocator? Maybe, but I'd probably make a mistake, and my GC'd language is fast enough for most of what I do.
Back in those days some of us were actually using compilers for Pascal dialects, Basic dialects, with C and C++ being yet another set of languages.
Then C++ started to gain market share on OS/2, Windows, BeOS, Epoch, macOS, Newton as the way to write UIs, even if their kernels and low level APIs were written in C, or C with C++ compiler style.
All C++ libraries bundled with compilers, provided strings and vector types with bounds checking.
It was the rise of C's adoption thanks to FOSS that brought the unsafety wrath upon us.
I agree with you in theory (hence why I gave a nod to Rust), but I think it's easier to have safe, bloated software. I think newer languages like Rust and Swift definitely are demonstrating the ability to have lean software that is just as fast as something written in C, but these are still relatively new in the scope of things.
Much as I think Java is a garbage language, there's no doubt that, by default, it's safer than a program written in C. It also typically is bigger, requiring a bit more RAM and resources.
Present day programs aren't optimized because they don't have to be. No one needs to gain a competitive advantage by squeezing the last bit of performance out of hardware because for a long time we've had steadily increasing performance levels and backward compatibility. Applications which need more performance than the present level of hardware can deliver so badly that they need to optimize to that level are very rare.
That's why Windows is the size it is nowadays... it's optimized for delivering the same user experience on all hardware, compatibility, language flexibility, manageability and user friendliness (don't laugh) instead of performance. It essentially performs the same function that Windows 3.1 did, but it does it on a far greater variety of hardware running a far larger assortment of software.
It's bigger and slower than it could be, but there are always trade-offs, and Microsoft hasn't really had any competition in operating systems for decades... Linux and variants have their place, but it's not on the desktop for most people, at least at the moment.
I disagree. Software nowadays is atrocious because it's not optimized. It's just that average users have become more accepting of long load times and bloat.
Here's an example. In the mid to late 90s, gamers would complain a lot about load times for CD ROM games. For some gamers, the load times were a deal breaker. This was one reason Nintendo could get away with using cartridges on the N64.
Fast forward to the present, and load times for many mainstream games is FAR worse than the 1-2x speed CD based consoles of the 90s. And a lot of this is due to sloppy, unoptimized code, e.g. loading assets. And yet no one bats an eye.
Another example is the web. There are so many garbage, unoptimized sites that load on my smartphone as if I were on dial up (I'm looking at you, Gawker). Yes, those pages contain a lot more multimedia content nowadays, but they still load at the same rate as a typical page in the 90s would have on dial up.
And with Moore's Law now ending (ended?), optimization may come back in vogue.
The N64 lost its console generation and solidified Sony as the market leader, in part because it used cartridges while everyone else used CD-ROMs. Way to choose an example that disproves the very point you were trying to make.
As for load times today, most modern games are implemented as scripts and assets for one of the big engines, usually Unreal or Unity. It's hard enough to manage all the assets that go into a modern game; an optimized loader would just make wrangling them all even more difficult.
The N64 lost its console generation and solidified Sony as the market leader, in part because it used cartridges while everyone else used CD-ROMs. Way to choose an example that disproves the very point you were trying to make.
Yes, I realize that. But the point was that poor decision was not enough to kill it, and the N64 was still a commercial success. A lot of gamers even preferred cartridges back then because of they didn't require load time.
As for load times today, most modern games are implemented as scripts and assets for one of the big engines, usually Unreal or Unity. It's hard enough to manage all the assets that go into a modern game; an optimized loader would just make wrangling them all even more difficult.
I would disagree with the "they don't need to be" stmt. Many photographers and artist have legit gripes in the lengthy time many filters and transforms take in post processing. Many of these are recipes that are applied en-masse to all files in a directory.
Well, I was obviously generalizing, not stating that no programs anywhere need to run faster.
However, taking your example, the filters can't really be optimized because they're applications run on top of a bloated operating system which isn't optimized for the reasons I mentioned.
Writing a highly optimized program to run directly on the hardware of a given machine would speed up filters tremendously but also be a trade-off in terms of manageability.
Funny, in a thread just the other day I was asking why we use different icons in new updates and focus less on optimization. This was in response to a commentor that suggested apps will use all available resources. If graphics has taught me anything it's: use what you need and make it fast. Other programs are relying on you.
People take for granted that an app responds in milliseconds. Engineers at Google, et al, of course immediately recognized that performance was tied to adoption in the early days and left no stone unturned in their quest for optimizations. The analogy today in portable devices is maybe with battery life drain during game play.
I think with search results you're right, and with things like GMail it seems performance is at the bottom of the priority list. Perhaps even off of the priority list entirely.
Performance is just a requirement. If it's good enough, it's good enough to release. It's not ideal and immensely wasteful, but that's how incentives are aligned.
This takes me back to the early nineties, when these articles where published in monthly installments in Doctor Dobbs Journal and, later, PC Techniques.
Incredibly, these 2 magazines were stocked monthly at my local newsstand in a sleepy suburb of Antwerp, Belgium, and every month around publication time, I’d bike there daily to check if the next issue had arrived.
I learned a lot of good stuff in college, but I don’t remember anything as exhilarating as this series, which eventually would lead to a career in the computer graphics industry.
I had the same experience (Belgium and Italy) - I would add in the same category the old Game Developer magazine, which had a regular series on game physics and math. Still have a bunch of them. Those were the days :-)
This is such an awesome book. I read this back in the day and loved every minute of it.
I think there is a lot to learn from it still, even if you're highly unlikely to be writing the same kind of graphics code.
The book has a great balance between:
- Micro-optimization - fiddling with ASM and data structures, memory alignment and such, custom math functions that lose precision in tradeoff for great acceleration due to hardware features
- Algorithmic optimization - trying to do things in ways that are mathematically faster (computational complexity)
I work in enterprise software, not games or anything touching hardware.. it is depressing algorithmic complexity is ignored so often these days and if you give an interview question it is often greeted with blank stares and there seem to be college undergrad curriculums which don't even touch on it.
I'm in that camp that feels like software has gotten so inefficient in a lot of cases that the user experience is no faster than 20 years ago. We have acceleration & optimization for certain things but every day applications are no faster than they ever were and when you have to use a web application stuff is often a lot slower than a native app was 10-20 years ago.
There are still a lot of great college texts on computational complexity even though trade publications ignore this stuff with a vengeance.
From my experience (graudated in 2016), most interviewing is centered around algorithmic complexity or at least regurgitating logarithmic complexity algos.
Potential hires still in or just out of school should have no problem answering those questions, but a few years out and most people forget those skills since most of the time the answer is to use an existing implementation or find a way to avoid the problem entirely. All of the people I know with a 4-year CS degree learned all about that stuff in their data structures/intro to algo classes.
I work in games and have had to both implement a few data structures on my own (mainly specialized trees and graphs). I've seen them help performance a ton and I've also had to scrap one or two of them because the naive implementation was faster. Nowadays a lot of indirection means your processor is spending most of it's time waiting on memory reads, while flat arrays can be loaded into CPU caches a lot more efficiently.
User interfaces are measurably slower than they were 20 years ago by at least an order of magnitude depending on how you measure it. They also do more, so it's up to the particular user and use case to decide if the trade off was good.
There was someone who said something along the lines of, "Heaven is old software on new hardware" and I personally agree with them.
I work in games doing mainly graphics work - it's amazing how many of these concepts still exist and have been recycled in interesting ways. Well worth the read if you're in my line of work.
For example, the concept of "sorted spans" in Quake is conceptually the same as how "light culling" is done in deferred and forward+ rendering pipelines. The first I'd heard of the technique was how Battlefield 3 used the PS3's SPU to do light culling for 64x64 blocks of pixels at a time.
This book is a great resource for thinking about how to optimize your code. And while VGA programming is not as relevant as it was, I still found it really fascinating to read about. Plus, the chapters on Quake are really interesting to read
Questions for experts: are part of this "timeless" and still relevant today, or is it mostly historical ? (Chapter titles like "Pushing the 286 and 386" are a bit scary :D)
Some parts are timeless, like this introduction in the first chapter about optimization:
---
Understanding High Performance
Before we can create high-performance code, we must understand what high performance is. The objective (not always attained) in creating high-performance software is to make the software able to carry out its appointed tasks so rapidly that it responds instantaneously, as far as the user is concerned. In other words, high-performance code should ideally run so fast that any further improvement in the code would be pointless.
Notice that the above definition most emphatically does not say anything about making the software as fast as possible. It also does not say anything about using assembly language, or an optimizing compiler, or, for that matter, a compiler at all. It also doesn't say anything about how the code was designed and written. What it does say is that high-performance code shouldn't get in the user's way—and that's all.
That's an important distinction, because all too many programmers think that assembly language, or the right compiler, or a particular high-level language, or a certain design approach is the answer to creating high-performance code. They're not, any more than choosing a certain set of tools is the key to building a house. You do indeed need tools to build a house, but any of many sets of tools will do. You also need a blueprint, an understanding of everything that goes into a house, and the ability to use the tools.
Likewise, high-performance programming requires a clear understanding of the purpose of the software being built, an overall program design, algorithms for implementing particular tasks, an understanding of what the computer can do and of what all relevant software is doing—and solid programming skills, preferably using an optimizing compiler or assembly language. The optimization at the end is just the finishing touch, however.
Think about the software you work on and maintain day to day: how much of it runs so fast that any further improvement in the code would be pointless? Truly we have strayed far from the light...
Well, i work in a AAA game engine that needs to run on consoles, so... :-P
(though i work mostly on tools nowadays but even then, optimization is important - from my experience people wont tell you that the tool is slow, but they'll really like it if you make it faster, which is why i always dismiss comments like "people like Electron/otherslowstuff, otherwise they wouldn't use it" as way more often than not, people wont tell you about something being slow and they'd rather get used to it, unless it REALLY affects them in a major way)
Sorry, when I said "you" I meant the average "HN you", who tend to have 4 abstraction layers and 5 third-party frameworks between their users and the metal :)
It's definitely mostly historical but it is an excellent read anyway if you're interested in what kind of problems faced game developers at the time and to what lengths they had to go to solve it. The chapters about getting Quake rendering to a decent level along with John Carmack are great. So, strongly recommended if you're interested in the technology during that era, not so much if you're expecting a lot of technical information that is directly applicable to current day game/graphics development.
People are still releasing DOS games, intros and demos targeting old hardware, so to them even some of the specific techniques described in the book may be relevant. On a higher level the algorithms described may be useful in modern systems with simple frame buffers. On a yet higher level, the general attitude towards optimization and problem solving that the book promotes seems timeless to me.
I also think that there is always some value in understanding the past in order to make sense of what is relevant to you in the now and what will be in the future, so I don't fully agree that there is a historical-relevant dichotomy. If you have the time to spare you can dig into the details of e.g. WWI and come out of it with a better understanding of the current state of affairs.
If your point is that knowing the past is, in general, interesting to understand the future, then I broadly agree.
However, at some point, records of the past become full of anectodes and little details that don't translate to anything valuable. And I was wondering if this was the case here.
I should have pointed out that I actually read part of the black book back in 2003 (how times flies...) , and, back then, I was already wondering if the book was relevant because of the focus of assembly and pre-pentium chips.
So, seeing the book mentioned 16 years later made me wonder what I might have missed, besides the eternal truth of "measure before you optimize".
The most important part for me was chapter 1: "the best optimizer is between your ears". Before you go unrolling loops and doing bit shifts to shave time at the micro scale, see if there's a different way to do what you want at the macro scale. Different algorithm, data structure, etc.
Edit: In the black book the 'ain't no such thing as the fastest code' seemed to be a bit of 'folksy' wisdom, illustrated by various anecdotes about fast code being upstaged by yet faster code.
However it rubs me a little the wrong way, considering that it's not actually a true statement as demonstrated in my link above.
You're right of course but I think we have to recognise that for all sufficiently complex problems Abrash' "folksy wisdom" is effectively true and, in his particular case, a good chapter title more than a statement of fact.
True on an ideal computer with absolutely no other software running and no cache effects, dependency chain stalls, branch prediction failures, and so on.
The best part of the book is the part about The Kennedy Portfolio, in Chapter 9.
"Reader John Kennedy regularly passes along intriguing assembly programming tricks, many of which I've never seen mentioned anywhere else."
A while ago I bought the paperback version of this book since I hate reading on the computer. It's huge, was $100 on Amazon, and someone wrote "Trash" on the side before they realized they could sell it.
This looked like a peculiar anachronism, as Markdown was created in 2004. But apparently this isn't the original source, but rather a scraped HTML[1] version converted to Markdown[2] in 2013.
OP here. Sorry if there was confusion. I came across your repo and was giddy with excitement to see it and wanted to immediately tell the world! :-) This book was a big deal for me in the late 1990s, still working as a game programmer. My copies were lost or loaned and I think I heard angels sing (or tracker/chip tunes?) when I discovered your repo. ;-)
I suffixed the headline "2019 V1.1 Release", trying for some clarity, since that was the most recent event I saw in the repo. Then it was re-headlined by someone else because that was also, apparently, confusing. Sorry! But THANK YOU for your work!
Nice work. I don’t know if I’m ahead of the curve but iBooks on iPadOS beta 13.1 comes up with a resource error for the ePub; don’t try this at home kids.
I trust there’s a way to get iBooks log files to fix issues...
I don't think I'll ever be disappointed to see this work linked. :) In some ways I feel like modern graphics programming has little to do with traditional optimisation. Rather than coding tight inner loops and wizardly algorithms, it's all about managing cache lines and pipelining data flows into your massively parallel desktop supercomputer. Which is awesome, but compared to the older stuff it's like a high speed rail network compared to a motorbike.
There are still areas where you're very much "coding tight inner loops and wizardly algorithms", namely shader programming. But it's true this is only one component within the high speed rail network.
It's not irrelevant unless you intend to focus on modern, triple-A graphics engines. Lots of indie game developers don't care about that stuff! There are even people working on new games using engines from the 90s, such as the Build engine [1]. Ion Fury [2] is one example.
I think the more you focus on modern graphics engines, the more difficult it is to stand out from the crowd. You end up in a rat race where you need a huge team of artists to create all of the assets for your photorealistic game.
On the other hand, with an old engine (or a new engine using traditional rendering techniques), you can make something distinctive and stylish with a smaller team. After all, they say the enemy of art is the absence of limitations.
Just to build on this, modern triple-A games are incredibly asset-based. It doesn't matter how good a coder you are, unless you have an art department producing every single tiny little detail of your in-game assets, they're going to look terrible.
This is part of the reason low-fi games are making a comeback in the indie scene, because they can actually look good with only one or two artists working on them (or even sometimes with programmer art.)
The technical details are pretty irrelevant for desktop computers, although there are analogues to some of the techniques on some more recent platforms eg. Gameboy Advance, smartwatches, maybe mobile VR (I do wonder if that's why Carmack is so keen on working on the Oculus Quest).
The way that it walks you through the mindset of optimising code is timeless and well worth reading, though, imo.
Yup. I bought the book after it came out and threw it away a few years ago. Most of the material in the book (like the peculiarities of 320x200 vs 320x240 VGA mode) hasn't aged very well. But that's the name of the game. You can't write truly optimal code without knowing all the details of the hw you are targeting.
Not sure if I want to laugh or cry at how 100% relevant this still is 20 years later...