Comment by columbo

13 years ago

> In reality, "premature optimization is the root of all evil" is advice given to new programmers so they don't waste time dinking around with micro-optimizations instead of thinking about algorithms, data structures, and higher order reasoning. (Or worse, muddying their code up to make it "fast.")

It's also for experienced programmers who dink around with macro-optimizations. For example, designing an entire application to be serializable-multi-threaded-contract-based when there's only a handful of calls going through the system. Or creating an abstract-database-driven-xml-based UI framework to automate the creation of tabular data when you have under a dozen tables in the application.

premature optimization is the root of all evil is a really really important mindset, and I agree it doesn't mean to not optimize, and many developers seem to take it that way.

X+1 = How many transactions your business does today

Y = How many transactions your business needs to do in order to survive

Y/X = What the current application needs to scale to in order to simply survive. This is the number where people start receiving paychecks.

(Y/X)4 = How far the current application needs to scale in order to grow.

The goal should be to build an application that can just barely reach (Y/X)4 - this means building unit tests that test the application under a load of (Y/X)4 and optimizing for (Y/X)4

Spending time trying to reach (Y/X)20 or (Y/X)100 is what I'd call premature optimization.

Disclaimer: (Y/X)4 is no real point of data that I know of, just something I pulled out as an example, anyone who knows of actual metrics used please feel free to correct.

> > In reality, "premature optimization is the root of all evil" is advice given to new programmers

> It's also for experienced programmers who dink around with macro-optimizations.

The hilarious thing is that everyone seems to think everyone else's optimizations are premature.

Don't believe me? Just go ahead and ask someone an optimization question, like maybe on StackOverflow. Those who respond might not know you, but I'll be damned if their first reply isn't to tell you that you probably shouldn't even be optimizing in the first place, because obviously if you'd thought about it more carefully, you'd have realized it's premature.

  • If you don't want people to tell you that your optimization is premature, then make sure to mention your profiler results.

    • Is experience worth nothing?

      Do you have to spend all your time and resources architecting the system poorly the first time, just to "prove" that you are wrong -- even though you knew it would happen before you even started coding?!

      That's like telling an engineer to prove (by actually building it and subjecting it to a lot of stress) that the bridge he designed would be prone to collapsing before helping him find a better design!

      1 reply →

The canonical version is Alan J. Perlis Epigram 21:

   'Optimization hinders evolution.'

If you have a black box, then optimize the fuck out of it. The Windows kernel is not a black box.

  • I think you missed half the argument. Windows is noticeably slower than Linux or Mac on the same hardware. Isn't that a problem?

    And if optimization always hinders evolution, boy should Windows be evolving... I mean... the NT kernel should have smashed through all kinds of antiquated paradigms by now. It should be doing memory deduplication, disk deduplication, fast JIT compilation of binaries for alternative architectures. It should support live process migration between machines, joining of systems together efficiency to form larger super-systems, a better permission model obviating the need to rely completely on virtualization for true privilege isolation in enterprise environments. It should have truly efficient network filesystems supporting disconnected operation, sharding, etc.

    Oh wait... it's stuck in the 90s... never mind. And it's slow.

    Linux, which optimizes a lot, has at least some of the things I mentioned above.

    "Premature optimization is the root of all evil" is a deeply nuanced statement that is nearly always misunderstood. "Optimization hinders evolution" is probably likewise. They're quotes cherry-picked out of context from the minds of great craftsmen who deeply understand their craft, and alone I do not believe they carry the full context required to comprehend what they really mean. I think they have more to do with maintaining clarity and focusing on higher-order reasoning than they do with whether or not to try to make things run faster. (And like I said, the most effective optimizations are usually higher-order conceptual algorithmic improvements.)

    • > Windows is noticeably slower than Linux or Mac on the same hardware. Isn't that a problem?

      Windows isn't slower at running Windows apps, fitting into a Windows infrastructure (Active Directory, management tools, Exchange etc), using Windows device drivers, working with NTFS volumes and their features, backwards compatibility, printers etc.

      It all comes down to what the goals of the users (or purchasers) are, and I doubt anyone buys Windows because of "performance" in the sense being talked about. But they do care about the "performance" of items mentioned in my previous paragraph.

      Linux has been able to optimise because of being open source and vehemently ignoring closed source. Open source means for example that the Linux USB stack could be optimised and all affected code due to API changes could be updated. This and other topics are covered really well in Greg Kroah-Hartman's OLS 2006 keynote - http://www.kroah.com/log/linux/ols_2006_keynote.html - see "Linux USB Code" about halfway down for that specific example.

  • I recently realized, e.g., that the HotSpot JVM is the R.M.S. Titanic, and invokedynamic (or any change in bytecode) is the iceberg. That's probably a reason why we're still waiting for lambdas, in-memory transactions, etc. It's too large to evolve quickly.

    • I've read your comment three times today. I still cannot avoid thinking of Richard M Stallman and trying to link him to the Titanic. Even though I know it is wrong.

      I've got the wrong closure over HN.

"Or creating an abstract-database-driven-xml-based UI framework to automate the creation of tabular data when you have under a dozen tables in the application."

I'm not an experienced programmer, and I'd use that approach anyway, simply because it makes sense (is there any alternative that isn't worse?). What does that mean? (Oh, and I'd skip XML. I abhor violence.)

  • Factories only make economic sense if you are planning on building a large number of widgets.

    For small applications, dynamic form generation infrastructure dwarfs the actual business logic. It means writing a lot of code which isn't solving your business problem.

    Your project has an extra layer of 'meta'. It's harder to debug. It decreases flexibility. Validation is hard for multi-field relationships. Special-casing that one form can require major infrastructure changes. The approach tends to be slower and buggier than the naive approach for all but the most form-heavy applications.

    • It's not just the form generation. I've given some thought to how one might work with a MVCC/MGA system such as the one you have in PostgreSQL and Firebird to make an interactive system with tabular display that would keep the beneficial properties of these transactional architectures (optimistic concurrency) and still work the way that people expect from "business apps with data grids". Among other things, this implies data edit conflict resolution etc. The problem is that even if the way of going about this is straightforward, I'd never, ever want to write this even twice. Not just because it's extra work, simply because generating the updating transaction in the manner recommended by the designers of these RDBMS systems (a snapshot transaction to populate the UI and a read-committed transaction to post the edits) is error-prone.

      Also, why would an extra layer of 'meta' make it harder to debug and decrease flexibility? I would have thought that it would enforce more structure by centralizing certain functionality, thus making it correct-by-design instead of relying that you'll follow conventions in multiple places consistently, and increase flexibility by separating aspects that you'd otherwise have to "weave-in" throughout the code and later change in multiple places.

      3 replies →

  • For a small number of tables?

    Just bite the bullet and render them by hand. It'll take less time than writing the abstract whatever-driven autogenerated UI framework, making it lay things out nicely, handle all the corner cases and auto-wiring of stuff which might not be needed in all cases, and tweaking the generated code to look good for all the data.

    • You know, this is where conciseness comes in handy. Another suspicion that I have (in addition to the one I've voiced elsewhere here) is that complex, inflexible languages almost force people to write stuff "by hand". What exactly is the reason for a simple, small generative layer to be so complex that it can't beat hand-written stuff for two dozen tables? I'd understand if you were talking about Java and Cobol, for example, but I'd think that such languages as Ruby, Smalltalk, and Lisp will have the threshold for "now it's worth it to be generic" quite a bit lower. I'm not sure where exactly, but certainly lower.

i admit to doing this... made a multithreaded simulation framework for use by my game team.... too bad the games they make with are so computationally simple as to make the sim framework a complete waste :(