13

Back in the "good ol' days," when we would copy shareware onto floppies for friends, we also used a fair bit of assembly. There was a common practice of "micro-optimization," where you would stare and stare at lines of assembly until you figured out a way to express it in one fewer instruction. There was even a saying, which was mathematically impossible, that "You can always remove one more instruction." Given that changing runtime performance by small constant factors isn't a major issue for (most) programming today, are programmers transferring these micro-optimization efforts elsewhere?

In other words, Can a best-practice be taken to an extreme state where it's no longer adding anything of value? And instead is wasting time?

For example: Do programmers waste time generalizing private methods that are only called from one place? Is time wasted reducing test case data? Are programmers (still) overly concerned about reducing lines of code?

There are two great examples of what I'm looking for below: (1) Spending time finding the right variable names, even renaming everything; and (2) Removing even minor and tenuous code duplication.


Note that this is different from the question "What do you optimize for?", because I'm asking what other programmers seem to maximize, with the stigma of these being "micro" optimizations, and thus not a productive use of time.

11
  • @Macneil, I do not know what other programmers micro-optimize for, but I do not have much time for that. My co-workers are busy as well (Just my 2 cents).
    – Job
    Nov 28, 2010 at 0:36
  • @Job: You've never seen someone wasting their time, changing the code for no reason? Consider yourself lucky. There are two great examples below: Variable names and minor code duplication.
    – Macneil
    Nov 28, 2010 at 0:38
  • 1
    The question, as currently worded, is an improvement. I can't remove the close vote, but it will age away in a few days. Actually, the question is attracting some pretty good answers. Nov 28, 2010 at 4:06
  • 1
    BTW, any best practice can be taken to such an extreme that it no longer produces value. Nov 28, 2010 at 4:27

12 Answers 12

21

Code Formatting

Don't     get    me   wrong             ,
code      should be   consistent        & 
readable                                , 
but       some   take it         too far.
5
  • Ah yes, the good old variable types and variable names need their own columns in a series of variable declarations. Oh! Forgot the extra row for the = and the fourth for the initializers!
    – Macneil
    Nov 28, 2010 at 15:42
  • [Darn, would upvote, but my daily limit is reached...]
    – Macneil
    Nov 28, 2010 at 15:42
  • 3
    Our professors forced us to format the code for out assignments this way. Took me years to get rid of this habit. Nov 28, 2010 at 21:18
  • Oh dear. On other answers I was laughing, but this one really hurts :-(
    – user8709
    Nov 28, 2010 at 22:45
  • 2
    +1 I once worked with a library where the developer refused to make his code const-correct because it screwed up his column-formatted code... Nov 28, 2010 at 22:56
20

I used to write a lot of assembler back in the day. It is not just that compilers have gotten better, it is that most hardware now has lots of logic devoted to out-of-order execution of code. The real micro-issue is scheduling, most computer instructions take several machine clocks to produce a result -and a memory load that misses cache may take several hundred! So the idea was to schedule other instructions to do something useful, instead of waiting for a result. And modern machines can issue several instructions per clock period. Once we started getting out-of-order execution HW, I found that trying to get great performance with hand coding became a mugs game. First the out-of-order HW would not execute the instructions in your carefully crafted order, the fancy new HW architecture has reduced the penalty of inoptimal software scheduling enough that the compiler was usually within a few percent of your performance. Also I found out that compilers were now implementing wellknown but complexity generating tricks, such as unrolling, bottom loading, software pipelining etc. The bottom line, you have to work really really hard, skip some of these tricks and the compiler beats you. Use them all and the number of assembler instructions you need increase several fold!

Probably even more important, most performance issues, are not about instruction issue rates, but getting the data into the CPU. As I mentioned above, memory latency is now hundreds of cycles, and the CPU can execute several instructions per clock period, so unless the program -and especially the data structures are designed so that the cache hit rate is exceedingly high, microtuning at the instruction level will have no payoff. Just like military types say amateurs talk tactics, pros talk logistics. Performance programming is now more than 90% logistics (moving data). And this is hard to quantify, as modern memory management typically has multiple levels of cache, and virtual memory pages are handled by a hardware unit called the TLB. Also lowlevel alignment of addresses becomes important, as actual data transfers, are not in units of bytes, or even 64bit long-longs, but they come in units of cache lines. Then most modern machines have hardware that tries to predict which cache line misses you might need in the near future and issue automatic prefetches to get them into the cache. So the reality is that with modern CPUs performance models are so complex as to be almost un-understandable. Even detailed hardware simulators can never match the exact logic of the chips, so exact tuning is simply impossible anymore.

There is still a place for some hand coding. Math libraries (like say the exp function), as are the more important linear algebra operations (like matrix multiply) are still usually hand coded by experts that work for the hardware vendor (i.e. Intel or AMD, or IBM), but they probably only need a couple of top notch assembler programmers per mega-computer corp.

2
  • 1
    Hand-coding is increasing difficult for persons working outside the CPU vendors, as the task is increasingly dependent on insider knowledge and vendor specific tools (compilers and profilers). spiral.net tries to model CPU optimization and automate the search for optimal solutions.
    – rwong
    Nov 28, 2010 at 23:51
  • Many computer languages push programmers to senselessly micro-optimize by making it a pain to use double precision for calculations whose results will be rendered into float. For some reason I can't fathom, many people see to think this is a good thing.
    – supercat
    Oct 25, 2014 at 2:41
11

I sometimes spend (waste?) time while choosing a good name for a variable or a method so that it is not only precisely descriptive but also has a good linguistic style.

It goes a little further when I attempt to put the entire works (a program) into the same linguistic style. Sometimes my opinion changes and I revise the book. :)

No that it takes that much time. It's rather rare. But I like to keep the good grammar in my programs.

5
  • 3
    Naming is hard. Hence you should refactor a name when you think of a much better one. Note that this captures mind effort, and hopefully crystalize "why"'s too.
    – user1249
    Nov 28, 2010 at 1:18
  • 1
    This is very much a left-brained thing (the left side of your brain is responsible for processing language). As a right-brained programmer, I tend to spend much less time worrying about semantics and more time worrying about how all the pieces fit together. Nov 28, 2010 at 2:56
  • 7
    Variable and method naming is an important part of maintainability. One should spend time thinking about names, so that 5 years from now, the person maintaining the code has an easier time with it. Nov 28, 2010 at 3:20
  • @grandmaster: Couldn't agree more. Nov 28, 2010 at 4:09
  • 4
    @right-brainers: Please code for the lef-tbrainers, so I can read your code also Dec 6, 2010 at 17:11
10

Time complexity. I spend way too much time optimizing things for worst case performance on a scale that is orders of magnitude larger than anything I know the program will realistically encounter.

I'm just too obsessive to let go of the 'but it could grow that big' bone, even when other design decisions preclude that from realistically happening.

However, in my defense, should the unrealistic become reality .. the optimization really isn't 'micro' any longer. Note, I didn't say impossible, but unrealistic.

Of course, requirements take precedence.

5
  • 1
    I worked for a company that sank because of this.
    – Henry
    Nov 28, 2010 at 8:35
  • 2
    @Henry - I promise, it wasn't me :)
    – user131
    Nov 28, 2010 at 10:37
  • 1
    @Henry: You mean they wasted time optimizing for things that likely would never happen, or they didn't think about things that likely would "never" happen... until they did happen and it was too late? Nov 28, 2010 at 22:52
  • 2
    @Henry: If a company has a highly scalable product and still sank, it's the sales and marketing's fault (for not targeting high-volume customers and not pricing appropriately), not the development's.
    – rwong
    Dec 23, 2010 at 6:12
  • 2
    The company spent too much time designing a system for millions of users when they didn't have 1 user. It must have been marketings fault. Yeah let's blame marketing, those guys are idiots.
    – Henry
    Dec 24, 2010 at 9:17
8

I think I've wasted weeks worth of time fiddling with Java exception handlers.

This is a lot of work for code that fails two or three times per year. Should this be a warning or an info? Error or fatal? Is it really fatal is the process will be re-spawned in five minutes? Is it really a warning if everything is still in default state?

Lots of navel gazing and discussion about the nature of an IO error. If you can't read a file over the network, is it a file error or a network error? And so on.

At one point I replaced all the concat strings with String.format so the yearly file error doesn't result in extra objects in the heap. That was a waste.

1
  • 3
    This is important work. The price of failure = your error message being featured on the daily WTF.
    – user8709
    Nov 28, 2010 at 23:01
7

I suppose I am concerned with LOCs too much. Not so much LOCs themselves, but rather number of statements and even more number of duplicate statements. I am allergic to duplicate code. In general I love refactoring, but I suppose about 50% of what I do doesn't make the code signifficantly nicer.

2
  • 4
    +1 for "I am allergic to duplicate code". See also my reply here: programmers.stackexchange.com/questions/14610/…
    – Macneil
    Nov 28, 2010 at 0:20
  • Thinking about it - I have this issue with loops which relates to a point Knuth made about goto, and sometimes having to trade a cycle or two or some duplicate code in order to write structured code. I will use a goto in very rare cases (most common = generated code), but my variation of this disorder is wasting time worrying and fiddling with a loop endlessly trying to eliminate a trivial inefficiency yet keep the code readable.
    – user8709
    Nov 28, 2010 at 22:40
5

Reading a file line by line instead of just reading the whole line into a string and process the string in one take.

Sure, it makes a difference in execution speed but is rarely worth the extra lines of code. It makes the code far less maintainable and increases code size.

Yes, this probably doesn't make sense if the file is 3GB big but most of the files aren't that big (at least not the ones I'm working with ;-)).

1
  • 3
    Even if it is 3GB or more, a 64-bit machine can handle it with virtual memory. Use a memory mapped file and it won't even read any part of your file until it's needed. Mind you, even that's micro-optimisation in the normal case.
    – user8709
    Nov 28, 2010 at 22:53
3

When I was writing assembly language it made sense to nitpick over bytes and cycles, but that was a long time ago and compilers have come a long way since then. I wouldn't try to manually out-optimize one now.

Similarly, when I switched to writing in C it was pretty easy to do a better job than the C compilers, but every year Borland or Microsoft or someone would release a new 'n improved one that kicked the previous one around the room. I started paying attention to the actual assembly code that the compiler was emitting and, danged if it wasn't writing some nice and tight code, unrolling loops, moving variables outside the loops, etc.

Now days I'm writing in a lot higher languages like Perl, Python and Ruby. I use some of the compiler tricks up front, like loop unrolling if it makes sense, moving static variables outside the loops, etc., but I don't worry about it nearly as much because CPUs are a weeeeee bit faster now. If an app seems to be dragging unexpectedly then I'll use a profiler and see what I can find, and then if something can be improved I'll start benchmarking various ways I can think of to do something faster, and then see how it scales up.

In general I try to be smart on how I write code, based on years of experience.

1
  • Hi Greg, thanks for the answer, but I'm looking for what programmers do to waste time, not to optimize runtime performance. There are two great examples above: Variable names and removing even minor code duplication.
    – Macneil
    Nov 28, 2010 at 0:40
3

A micro-optimization: improving single-threaded performance of things that are parallelizable or that can simply be improved with new hardware.

If something is slow on a computer from 10 years ago, a cheaper solution is probably to buy a newer, faster computer, rather than to waste programmer time optimizing. A big focus of optimizations considered, though, should be finding a way to use the 8 cores you can get today, or the 64 you'll be able to get in a couple years, instead of agonizing about minutia like the extra cost of garbage collection.

2

Micro-optimization in terms of runtime performance is hardly a closed problem even today (although it might be less common). I occasionally have to explain to people that the overhead of allocating an extra object every request or adding an extra function call is negligible.

Aside from that, I also see programmers micro-optimize for simplicity (including myself). I have yet to work somewhere that I didn't have to explain the difference between simplicity and simplism.

5
  • Why would programmers. be any different? What is the difference, please. Nov 28, 2010 at 4:12
  • @Yar - Why would programmers be any different from what? Nov 28, 2010 at 5:35
  • why would programmers. = programmers.stackexchange.com be any different from every place that you've worked where you've had to explain the difference between these two concepts? Please explain the difference. Nov 28, 2010 at 22:15
  • @Yar - I don't know that it would. In fact, as the point of programmers.se is to help programmers pool knowledge, I would hope that it isn't so that people might be at least a little bit enlightened by my answer. Nov 29, 2010 at 1:17
  • 2
    So what's the difference b/t simplicity and simplism? Nov 29, 2010 at 16:12
2

I'm all for the don't-optimise-unless-really-necessary principle. And I'm all for the profile-first principle. And in principle, I will only optimise something that will make a needed difference.

That's in principle. But principle is a liar.

I have a habit of taking care with functions in frequently used libraries that I think will be used a lot in inner loops. And then, when you spot something in another function, that isn't so often used...

Oh - and then there's the "I'm writing it - of course it's an important library" logic.

Oh - and BTW. I have never yet used a profiler to guide an optimisation. Don't have access to a commercial one, and never quite built up the motivation to figure out gprof.

Basically, I'm a hypocrite. These principles apply to other people, but I have too much fear of someone saying "but why did you write it that slow and crappy way?" so I can never really apply them properly to myself.

I'm not really as bad as I make out here, though. And I'm completely immune to self-deception, so you know I'm right about that!

EDIT

I should add - one of my major stupid hang-ups is call overheads. Not everywhere, of course, but in those I-think-it'll-be-used-a-lot-in-inner-loops cases (where I have no objective evidence of a problem). I have written nasty offsetof-based code to avoid making virtual method calls more than once. The result may even be slower, since it probably isn't a style of coding that optimisers are designed to deal with well - but it's cleverer ;-)

2
  • +1 Ah, yes! This class parses my application's highly specific and quirky command-line arguments, but let me format and fully document it when Javadoc, because surely others will be using this for years! [Will need to upvote later, my daily cap is reached.]
    – Macneil
    Nov 28, 2010 at 15:45
  • @Macneil - that's Doxygen, I'll have you know. With every option I can find switched on, so every little function gets "documented" in excrutiating detail, complete with a dozen pretty GraphViz graphs. Really helps everyone appreciate just how important my code is - and the print-out can wallpaper quite a large office block.
    – user8709
    Nov 28, 2010 at 22:29
1

In the old days when computers had clock times measured in microseconds, memory measured in kilobytes, and primitive compilers, micro-optimization made some sense.

The speed and size of current generation computers and the quality of current generation compilers mean that micro-optimization is usually a total waste of time. The exceptions tend to be when you absolutely have to get maximum performance out of some computationally intensive code ... or you are writing for an embedded system with extremely limited resources.

but I'm looking for what programmers do to waste time, not to optimize runtime performance.

Twitter and Facebook spring to mind :-)

3
  • Hi Stephen, that is a great commentary on micro-optimization, but do you see any modern day equivalents? [Facebook and Twitter are not "best practices" that can be carried too far.]
    – Macneil
    Nov 28, 2010 at 2:15
  • It still makes sense. The clock times might be orders of magnitude smaller, but the code is orders of magnitude larger...
    – hplbsh
    Jan 15, 2011 at 5:04
  • @Stuart - that means there's orders of magnitude more code to micro-optimize ... which simply doesn't scale.
    – Stephen C
    Jan 20, 2011 at 2:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.