Definitely still useful, but some info, esp on some C++ things, is already outdated or even wrong. But still a good resource if approached with "trust but verify" mindset
For example, on page 36 he asserts: "Accessing a variable or object through a pointer or reference may be just as fast as accessing it directly." While this might be true for a large/compound object (neglecting non-cached memory access vs cached memory, such as the stack), this is certainly not true in general case for simple POD types, such as ints or floats, if a compiler can't prove that between accesses the variable hasn't been modified (which happens actually very frequently). I've seen x10 speedups of computations in tight loops when I explicitly cached a value used in the loop into a variable from under a pointer/reference.
On p65 he asserts: "Assume that a function opens a file in exclusive mode, and an error condition terminates the program before the file is closed. The file will remain locked after the program is terminated and the user will be unable to access the file until the computer is rebooted." This is just hilarious not at the last modified date 2023-07-01, but even two decades ago. This could be true in times of DOS and maybe Windows 3.11. I might not remember exactly, but I think even Windows 95 have already dealt with it by tracking resources acquired by a process, and releasing everything after process termination. All WindowsNT family definitely didn't/doesn't have this issue (unless your program is a kernel-mode driver, but I'm not even sure in that, since my knowledge of kernel mode is circa ~2007 at most).
And I could keep counting, this isn't all issues, unfortunately...
So there's some historical interest in the document, but...one shouldn't trust it blindly for today's things.
> if a compiler can't prove that between accesses the variable hasn't been modified (which happens actually very frequently). I've seen x10 speedups of computations in tight loops when I explicitly cached a value used in the loop into a variable from under a pointer/reference.
This is indeed an important gotcha! Let's say you have a filter and want to process an array of floats. If the coefficient is a struct member and has the same type as the audio samples, you must cache it in a local variable, otherwise the compiler might reload it from memory on every loop iteration. ('restrict' can somewhat help with these kind of aliasing issues, but you need to be careful.)