Mike Acton's articles on game and console performance, covering strict aliasing, restrict, concurrency, and data-oriented design.
HN cites it for "Three Big Lies" and its data-over-code argument, plus its concurrency introduction and its aliasing articles in C optimizer debates.
I think this is pretty well stated:
There is no value in code being some kind of model or map of an imaginary world. I don't know why this one is so compelling for some programmers, but it is extremely popular. If there's a rocket in the game, rest assured that there is a "Rocket" class (Assuming the code is C++) which contains data for exactly one rocket and does rockety stuff. With no regard at all for what data tranformation is really being done, or for the layout of the data. Or for that matter, without the basic understanding that where there's one thing, there's probably more than one.
Though there are a lot of performance penalties for this kind of design, the most significant one is that it doesn't scale. At all. One hundred rockets costs one hundred times as much as one rocket. And it's extremely likely it costs even more than that! Even to a non-programmer, that shouldn't make any sense. Economy of scale. If you have more of something, it should get cheaper, not more expensive. And the way to do that is to design the data properly and group things by similar transformations.
It's from this blog post called "3 Big Lies": http://cellperformance.beyond3d.com/articles/2008/03/three-big-lies.html
When I read it I thought: "That's a pretty common understanding isn't it? Not really a big lie." Then a few days ago I saw this: http://www.quora.com/What-is-the-best-mental-model-for-object-oriented-programming
Facepalm. Note the "M.S. degree in computer science." WTF? To…
> Therefore the existence of the q pointer does not tell the compiler what type actually exists at memory address p/q. Is it invalid to construct q from p? I wouldn't think so as long as they are in the same allocation, but maybe I'm forgetting a rule.
But then the question is, how would you construct an allocation where both q[-1] and *p are guaranteed to be valid objects of their respective types, using standard C? (i.e. without relying on implementation-specific behavior).
> Surely there's a way to allocate two different types up against each other, though?
If by "against each other" you mean without padding between them, then I think the C standard allows that but there's no reliable/portable/guaranteed way to do it (that I know of).
By that I mean that specific implementations can guarantee that, either with struct packing or, in some cases, by carefully aligning them within a struct or a union. But this depends on the implementation/architecture, so it's not strictly portable/standard C, I think.
> Even if you don't make an actual struct, you can grab some char and say that X bytes are size_t and Y bytes are something else, can't you?
I'm not sure that is possible according to the standard, unless they already were objects of those types. See this[0]:
> It is always presumed that a char* may refer to an alias of any object. It is therefore quite safe, if perhaps a bit unoptimal (for architecture with wide loads and stores) to cast any pointer of any type to a…
Not sure if you're familiar with Mike Acton (as mentioned in the article). One of his key points of focus is data-oriented design, and that when designing software, ignoring the architectural realities of the hardware is ignoring one of your responsibilities as an engineer to deliver performant software.
Now, it's possible to argue that writing performant software is not important. The prevailing modern sentiment definitely seems to be "The compiler / interpreter takes care of that". But given his track record of delivering high performant running software, and the trend in computing towards sluggishness, I'm trending more and more towards his camp, than the "don't micro-manage the runtime" camp (which is starting to feel more and more like a thinly-veiled "I don't want to have to think about it").
Edit: A summary post he wrote as a source https://cellperformance.beyond3d.com/articles/2008/03/three-big-lies.html#more
> he needs to accommodate that
Clearly he doesn't. He just disabled harmful features and called it a day. Stuff like strict aliasing and undefined signed integer overflow apparently do nothing but serve as an excuse for the optimizer to screw up perfectly reasonable code.
https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
https://stackoverflow.com/q/2958633/512904
Looks like this is a pretty good approach to fixing the C language. Take the nonsensical undefined stuff and tell the compiler to define it.
Looks like there is a may_alias type attribute to tell GCC that some types may alias:
https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-may_005falias-type-attribute
I'm not sure if it's worth the effort though.
One should never loose to the complier, after all you can see it's output and it can't see yours.
Also, the programmer can "cheat" by doing things the compiler would consider invalid but are known to be ok given the larger context of the application.
The restrict keyword in c gives an example of how one can optimize code by knowing the larger context.
https://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html
The problem is the ROI is usually pretty bad as these assumptions rarely hold as the code evolves, in my experience, and the optimization usually only lasts for finite (sometimes shockingly short) amount of time. i.e. OS changes, hardware changes, memory changes, etc. etc. etc.
I actually use macros along the lines of:
#define LOAD(TYP, ptr) (*((TYP *)memcpy((TYP[1]){ }, ptr, sizeof(TYP))))
#define REINTERPRET(AS_TYP, FROM_TYP, val) LOAD(AS_TYP, (FROM_TYP[1]){ val })
In practice (that I've found, with GCC), the memcpy and single-use temporaries get optimized away entirely. In strict C99, writing one member of a union and then reading a different member of the same union is undefined in the general case, last I checked. http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html seems to agree, but suggests that every major compiler recognizes it as a de facto idiom and supports it anyway.