The Stack Is An Implementation Detail
blogs.msdn.com
blogs.msdn.com
I'm all for avoiding premature optimizations, and giving priority to short and comprehensible code over faster code. But "leaving performance considerations aside" is like discussing dictatorship and "leaving human rights issues aside".
Good programmers have good hunches about performance, better programmers pick the shortest code anyway, the best programmers measure and then maybe optimize.
A great programmer is able to think about performance at every point in designing something without obsessing about it to the point where it decreases reliability, readability, or extensibility.
Having written one lousy implementation in X months does not mean that the good implementation, when starting over, will take X more months.
I have never seen a functional specification reaching more than 50% accuracy on details (most are not even close). When implementing you always discover more about the problem.
What stops you from starting over tends to be that the customers have integrated with your system according to published specs, or large roll-outs have been made already.
Of course, but one is not always implementing a totally new system that justifies "throwing one away". Often one is implementing something whose design is well-known enough that one should expect to be able to do it right the first time.
Having written one lousy implementation in X months does not mean that the good implementation, when starting over, will take X more months.
Sure, but it still takes Y more totally unnecessary months, even if Y is less than X.
If you wait until everything is mostly written, you risk finding out that a fundamental design decision is causing your performance problems.
Agreed, you should measure as soon as you can and it's best to be building and measuring, not guessing where your bottlenecks are up front.
With porting an operating system across processors or when performing significant changes and upgrades to an operating system and its interfaces, the details of the data and call stack and the thread stacks and register-passing and register spillage and all the other related ugliness can be (and often is) exceedingly platform-specific.
Adding applications dependencies on these details means your code can be somewhere between faster and less portable, or faster and non-portable.
Or your applications can pin the vendor in a corner by depending on a design statement that the vendor might now regret having made. Whether that might provide or prevent a thread stack, or changes to the call frames, or stack randomization or otherwise.
I'm working in several areas where the vendors spend far, far, far too much time describing the internal details of their implementations. Which is bad on several levels. It can pin the vendor to the design; into choosing compatibility or choosing to break applications. And it tends to obscure the information presented to application programmers with details that are less than relevant.
There's more here than strictly performance; there's also compatibility and maintainability, and stability and sustainability, and extensibility.
Absent specific reasons and whenever in doubt, the decision should be to present an opaque interface. "The stack is an implementation detail."
It's very appealing (and obvious) step to then execute these declared constraints - that is, to code directly in terms of the mathematics.
But here's the problem: the maths doesn't tell you the answer; it just tells you its constraints. The answer you want is somewhere in that space. Of course, it's possible to write a language that will always give you an from within that space. The most well-known way for this issue to show up is in efficiency: the solution given by the language does fall within the constraints, but it takes too long. If we had a way to declare the efficiency as a constraint, this might change... but apparently that's a hard one. Other constraints are things like: usability, understandability (to coders of average ability, average education and average deadlines), interoperability with standards (which are never ideal, but which exist and which work), portability, modularity and many others that I haven't encountered or imagined.
Partly the difficulty is in specifying a soft, human constraint in formal terms; the other part is solving for that constraint, which appears to require strong AI or bump up against the halting problem - or else we could just declare the constraint: "fastest possible solution".
On another aspect of it: the last couple of days, I've found it very effective to think of a model as just the nouns, not verbs; data structures, not algorithms (as in the Brooks quote). Guess this is implicit in the idea of a constraint, but it's helping.
The other thing is that the model doesn't have to be precisely correct. It only needs to be correct in the important ways (if I don't already know what the important aspects are, a complicated model probably won't enlighten me). This gives me conceptual framework to think in, rather than to be an authoritative definitive description, perfectly correct in every minor details (they can be corrected early or late, if they really are minor). I find it helps to give me a vantage point, to see further. My mind is very fertile with finding solutions - provided I can see where I am.