I'm glad to see something like this. People often take the typical optimization mantra too far. The minute you mention optimization on most internet forums (especially StackOverflow) you get slammed for promoting "premature optimization."
That's not to say premature optimization doesn't exist. Sometimes writing faster code is the difference between using a hash instead of a list. Sometimes it's spending an entire day optimizing a function that's called once. The former is performance aware, the later is premature. It seems as though most would have you believe that they both fall into the "premature" bucket.
It's as though people are using it as an excuse for their personal ignorance and would rather continue to revel in this ignorance than expand what they know. As far as I am concerned these "unimportant tidbits" about performance are gifts that keep giving.
Yes, but it's unlikely that someone asking "is it faster to concatenate strings in C# using the + operator or StringBuilder" on StackOverflow is someone that is writing a low-level database engine like SQLite. In my (totally anecdotal) experience the people who are more concerned about performance are beginners, because that is something that they can grasp, and this is where the "don't prematurely optimize" people are coming from. Obviously someone who is writing a low-level database engine knows that performance matters, and likewise, is likely to be running benchmarks rather than asking vague questions on SO.
Indeed. However, keep in mind that as this beginner "ramps up" to the knowledge level of someone who is working on a SQL database he will need a source to find out where costs lie. He's done some profiling, finds an expensive method with massive amounts of string concats, heads to Google and all he can find is "don't prematurely optimize."
You can supplement an answer with "don't prematurely optimize," but the presumption that premature optimization is occurring is a premature assumption.
He who asks a question is a fool for five minutes; he who does not ask a question remains a fool forever. ~ Chinese Proverb
I would work with beginners that are not fools, than experts who are.
Nope, if he got to that level, he'll know that the only way to really know it is testing.
He may still ask why one is slower than the other (if it is, I don't know that), but that's a completely different question that in most contexts will get a nice answer.
Suppose, for a moment, that our hero is seeing this situation for the first time and doesn't know what the alternatives are.
Tests that don't cover the best option can't possibly identify the best option. So if you want to do a really good test, going somewhere to ask, "What else should I try?" is hardly an asinine course of action. On the contrary, if our hero is new to this stuff, or is new to the platform in question, or anything like that, then asking others for advice should probably qualify as due diligence.
And that's decent advice in response to the "is it faster to concatenate strings in C# using the + operator or StringBuilder" questions. But I've also asked Stack Overflow questions that drowned under a tsunami of premature optimization tut-tutting from people who I suspect didn't even fully understand the question, and then sighed and proceeded to take a couple days to figure it out myself and improve application performance in a critical section by 50%. Which is fine, but once upon a time I thought Stack Overflow might be a resource where people might occasionally save me a bunch of time by saying, "Hey, don't waste your time, I've been there and it's a blind alley."
I think part of what's going on there is that SO's gamification can create some kind of perverse incentives for answerers. If you want to get the upvotes, you have two good courses of action: You can either already have 5 digits' worth of karma, or you can answer first. The first option isn't available to the vast majority of SO users, so most go with the latter one. This drives down the quality of answers. It also creates perverse incentives for behaviors such as users getting in a quick low-quality response that's just good enough to get a few upvotes from people who already understand what you're talking about, and then (maybe) following it up with an edit that provides a high-quality response that would be useful to the asker.
> But I've also asked Stack Overflow questions that drowned under a tsunami of premature optimization tut-tutting from people who I suspect didn't even fully understand the question, and then sighed and proceeded to take a couple days to figure it out myself and improve application performance in a critical section by 50%.
Me too. It's infuriating how presumptuous people can be.
Here is someone telling me that my attempts to avoid a virtual function call "definitely fall under the category of premature optimization": http://stackoverflow.com/a/5100072/77070
It's interesting to me that people will shout "premature optimization" before they have any idea what you are doing or how long you have worked on this problem before trying to optimize.
I'm also deeply skeptical of the pre-canned response that people should always profile - in the spirit that it's hopeless to optimize without a profiler.
In my experience, profilers are really low-level tools that often highlight the wrong problems, aren't very good at telling you where the optimization opportunities are, and tend to encourage microoptimization.
It's not that profilers are bad, it's that I get the feeling the people parroting this advice have no idea what they're talking about, and somehow believe that a profiler is "the solution", when profilers are neither necessary nor (most problematically) sufficient to fix most performance problems.
1. quickly seeing which high level functions or methods take the longest time,
2. which methods are called a lot.
Even 2. can be of marginal use. A lot of times, it's not surprising a method is called a lot, and not clear whether those calls are indicative of a performance problem. There are times, though, where a method is called a lot more than you expected, in which case it might be the clue to solving the performance problem.
For 1., it's usually click down through the call stack for the most expensive top level method, while there is still a single method taking up a good fraction of the overall time.
Hopefully the stopping point will still be a method you wrote, and not a library call. If it's your code, you likely have the ability to fix the performance problem by changing your code. If it's a library call, you might need to be a little more creative, in finding an alternative approach, or better understanding what that library call is doing under the hood.
So for me, the profiler just tells me I'm looking at the right general part of the code when trying to improve performance, and that's about it.
FWIW, both 1 and 2 can still lead you in the wrong direction sometimes. For example, if you're working in a garbage-collected language most profilers (that I've used, anyway) won't give you good insight into how much time you're wasting on excessive GC load because you're creating too $#@$% many unnecessary objects (see: boxing), or creating objects with just about exactly the wrong life span. If you're working on parallel code, many profilers are darn near useless for figuring out how much time you're losing to blocking on synchronization.
I just replaced a SQL view that was performing 24,000 reads with a procedure that performs 45 reads. Yes, it's a little different to use, but overall don't listen to the premature optimization people.
I could wait until the data in those tables grows to a crazy size and the reads are out of control (and spilling to disk) or I could just fix it now. Hmmm...
Currently, I'm using Y mechanism, and it produces correct results.
However, the performance sucks -- profiling shows me this is a big time sink in my program. So... (actual question.)
It may help with kneejerk "premature optimization" if the profiler results are mentioned before the request about how to optimize (at least, it should to the extent that the problem is people stopping reading because they see the optimization request so that they never read the comment about profiler results.)
And then you post your own solution for others who might stumble upon it and 15 minutes later the entire thread is deleted by a mod for "this is a discussion thread and doesn't fit the Stack Overflow Modus Operandi"
> If you want to get the upvotes, you have two good courses of action: You can either already have 5 digits' worth of karma, or you can answer first.
How does having karma help you get more upvotes on a brand new answer?
Answers that already have upvotes get more views, and are therefore more likely to get even more upvotes. But that's distinct from a user's reputation score.
To be fair, I once fixed a java application that completely crashed due to using string concatenation for data export, rather than a StringBuffer. It does matter sometimes even in workaday applications.
It's not a completely useless question. I wrote an API data validation gem for Ruby that needs to be as unobtrusive as possible, so it needs to be fast. I found that building strings by interpolation (e.g. "#{str1}#{str2}") is quite a bit faster than addition (e.g. str1 + str2).
The other response you'll see all the time? "Measure it!"
Low-level optimization is not a task to be undertaken casually. If you don't know where to look, you can end up just wasting a lot of programmer time for zero real-world benefit. If you don't measure before and after, you may even make things worse...
The SQLite folks didn't make these changes with a hope and a prayer; they carefully profiled, changed, and profiled again... And they invested years in building a test suite to ensure that such micro-optimizations don't inadvertently break the logic. The results are impressive, but so was the time and effort invested in achieving them. If you're not willing to be so diligent, "premature optimization" is exactly what you're doing.
And for the love of all that you care about, measure it with realistic data and use cases.
I've seen people optimise code while working with small test databases and making changes that are more efficient over the smaller data-sets but are hideously bad on larger ones (usually due to memory use growth, for instance hitting the limits where SQL Server starts spooling temporary data to disk instead of just keeping it in RAM for the duration of its existence).
Or just as bad: working with data that has the wrong balance and (to give another SQL example) giving index use "hints" that shave a little off the time to run over their test data but hamper the query planner on real data by making it ignore what might be better options.
As lmz mentioned, they inform the query planner that you'd prefer it to take a particular route to address your instructions where it might have a number of choices given your current table+index structure and data patterns (and has chosen a bad one of the options in the past).
I use the quotes around the word hint because it implies that it is a fairly informal pointer that the planner might choose to ignore where in reality they usually take it as an order and go that way without question (assuming that you know better than it might otherwise chose to do, or you would not have given the hint).
Oh yeah, definitely. In some situations performance implications are obvious. E.g. Adding to a list of unique values in a loop? Use a hash, not a list. That's the kind of thing you do up-front, it sounds obvious but you would be amazed at the bad responses you get on the internet for pointing this kind of stuff out.
What I guess I'm trying to say is that you can go in a write obviously slow code "which is fine because you shouldn't prematurely optimize," or you can be informed and, with sometimes no extra development time, write something that's at least competent from the get-go.
For everything else? Profile, profile, profile, profile! And make sure you are using a competent profiler. I've wasted days because of inferior tools, switched to better ones (cough VTune cough) and had major improvements in mere hours.
This is where knowing the full Knuth quote helps...
> Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.
Another common mistake relates to the phrase "penny wise and pound foolish", which applied to programming helps us identify those scenarios where we might waste time micro-optimizing array searches rather than choosing a hashtable (or even pre-sorting the array). Time spent optimizing your architecture will nearly always offer a bigger payoff than micro-optimizations - but once that's done, Knuth's critical 3% is worth remembering.
It goes beyond the full quote --- the whole paper is great, showing Knuth's stature as both a thinker and a writer. If you've ever quoted the "premature optimization" line to someone, or nodded when hearing it, you'd do yourself justice by understanding the context of the quote.
My own programming style has of course changed during the
last decade, according to the trends of the times (e.g.,
I'm not quite so tricky anymore, and I use fewer go to's),
but the major change in my style has been due to this inner
loop phenomenon. I now look with an extremely jaundiced eye
at every operation in a critical inner loop, seeking to
modify my program and data structure (as in the change from
Example 1 to Example 2) so that some of the operations can
be eliminated. The reasons for this approach are that: a)
it doesn't take long, since the inner loop is short; b) the
payoff is real; and c) I can then afford to be less
efficient in the other parts of my programs, which
therefore are more readable and more easily written and
debugged.
The argument behind premature optimization only really stands when first developing a product. Once you have an established product, it's no longer premature, it's just optimization.
Premature optimization is that which is done before the need for the optimization is clear. Thus debugged, feature complete (for now) ... 'Established' really has nothing to do with it, if that established product has bugs then those should be addressed before attempting to optimize. Unless of course, the lack of optimization is itself the bug.
> Once you have an established product, it's no longer premature, it's just optimization.
Its premature even if the product is completely feature complete and bug-free if the particular optimization being done is being done before more significant optimizations, which, if you aren't using some measurement more sophisticated than "this looks like it could be optimized" to choose what to optimize, it probably is.
I'm late to the discussion, but I will say that when you have an established product you have a much better perspective on how the code is organized than when you're still cobbling together V1.0. A firm grasp of the code's organization makes it much easier to contain the optimized part and slap on a /* HERE BE DRAGONS */ header.
With a full suite of automated regression tests you'll have a great deal of confidence that any changes you've made didn't break anything.
Go nuts and experiment!
> The minute you mention optimization on most internet forums (especially StackOverflow) you get slammed for promoting "premature optimization."
Typically, that's because the people asking are asking questions like "which is faster in PHP, print or echo?" to which the answer is generally "there's about a half a second difference if you run it a million times, but you shouldn't be doing that anyways".
That's because so many people asking are focusing on micro-optimizations without having profiled and while ignoring bigger factors, or else don't have working code yet.
There are few absolutes in coding. Some times optimizing a function that's called once is worth it. People often perceive software that takes a long time to load is slow even if everything else is fast. Though even just changing the loading screen can do a lot even if the actual time something takes to load does not change.
PS: If all someone wants to do is rotate an image loading photoshop really is slow.
A common advice is to focus optimization in the few places where it matters, such as in the middle of tight loops. Sqlite is in an interesting situation in than almost all their code could be called in the middle of somebody's tight loop. The same applies to many libraries, operating systems, VMs, etc, but not to most applications.
Well, I think the imporatant part to note is that SQLite has been through basic performance review, it's been heavily tested and used at this point. It is a mature piece of software.
So optimizations like this can certainly no longer be considered "premature".
Premature optimization is also not a true waste of time (IMO) if it's part of the learning process.
Man, did I ever 'waste' a lot of time on optimization when I was first learning to code (in C), but:
a) I learned what the low-hanging fruit was, so that I was eventually able to make all my code fairly fast without explicit optimization.
b) Man, where some of those early programs I wrote blindingly fast... especially compared to the higher-level python/numpy/scipy stuff I write a lot today. It's also nice to repurpose some of that old code (ie as a library) for new applications since every potential bottleneck has already been ironed out.
> Sometimes writing faster code is the difference between using a hash instead of a list. Sometimes it's spending an entire day optimizing a function that's called once. The former is performance aware, the later is premature.
I disagree, it depends on the context. If using your original list is so fast that nobody human can notice the difference, it's a waste of time to turn into a hash, not "performance aware".
Actually, whether it's a "waste of time" also depends on the context. It could be worse. It could make your code harder to understand and maintain.
SQLite has an advantage because it is a small, well defined program (for a DB) that as is much defined by what it doesn't do as what it does. The typical problem with premature optimisation is that you optimize something that is either subject to having functionality requirements altered in a significant way and the optimisations will make it brittle when you need to do this.
That's not to say premature optimization doesn't exist. Sometimes writing faster code is the difference between using a hash instead of a list. Sometimes it's spending an entire day optimizing a function that's called once. The former is performance aware, the later is premature. It seems as though most would have you believe that they both fall into the "premature" bucket.
It's as though people are using it as an excuse for their personal ignorance and would rather continue to revel in this ignorance than expand what they know. As far as I am concerned these "unimportant tidbits" about performance are gifts that keep giving.
/somewhat offtopic rant