5 ms·
These strange syntaxes are perfect additions for the article "How to write unmaintainable code", which already has a Duff's device example: switch(count %
by cjslep 11y ago
These strange syntaxes are perfect additions for the article "How to write unmaintainable code", which already has a Duff's device example:
switch(count % 8) {
case 0: do{ putchar('0' + (int)j);
case 7: putchar('0' + (int)j);
case 6: putchar('0' + (int)j); /* Unrolled
case 5: putchar('0' + (int)j); * for greater
case 4: putchar('0' + (int)j); * speed.
case 3: putchar('0' + (int)j); */
case 2: putchar('0' + (int)j);
case 1: putchar('0' + (int)j);
} while(--j > 0);
Without syntax highlighting, a passing glance may not recognize cases 3 through 5 are commented out.
- skarap 11y agoThis is not code - it's a trap!
- marcosdumay 11y agoYou are missing a close brace. I liked a lot how you switch on count and loop on j. If gcc didn't comply, I would never notice it.
- sago 11y agoSeems an odd example: any code with a multiline comment can have the same issue. That's nothing to do with the strangeness of Duff's device. It would work the same in a series of function calls or calculations. And even then it is a matter of experience. It looks odd to me to have multiline comments not in its own 'paragraph' of the code, so draws the eye right away. Perhaps this would foil some programmers, but not more than once, I'd have thought. In my experience, run-on compound statements are much more common and hard to intuitively spot: if (foo) bar(); sun(); Duff's device is difficult to understand from first principles, but even that is a bad example of unmaintainable code because a) it looks like nothing except Duff's device, you only need to see the pattern once or twice and you'd recognise it, and at least know 'it's that weird pattern for unrolling loops', and b) it is a performance optimisation that only belongs in code that is profiled and needs to go that fast. As such it should be well commented to avoid regressions by well meaning refactor-zealots. Inline assembly or heavy intrinsics are more difficult to read than regular C too, so you only use them when you need to. In my experience manual loop unrolling is very rarely needed.
- jcranmer 11y agoActually Duff's device is very likely to be a performance hit most of the time. It will have bad branch predictor behavior and it creates unstructured code, making it harder for the compiler to reason about and optimize. Although it should be noted that the original person to use Duff's device did admit that he tried everything else to optimize it and only that worked, and he never advocated that people should use it as a general optimization technique.
- sago 11y agoThat's been my experience too, not just of Duff's device but in general with trying to unroll loops. There may have been a point where it was practical (although early in my career I didn't do the profile-first-optimise-later thing very well, I confess). But if you think you can manually unroll a loop in a way that beats the branch predictor and a good compiler on most modern hardware, you're probably fooling yourself.
- nwmcsween 11y agoEh, this is still relevant, loop unrolling can still have a drastic effect if the compiler cannot optimize.
- sago 11y agoI suspect I'm just not in the group of people for whom it is relevant any more. Way back I was optimising for console hardware when that hardware was quite rudimentary. Now the hardware is much more sophisticated, I don't need it. Can you say what kind of stuff and in what kinds of situations you unroll loops. Just out of curiosity.
- adrusi 11y agoIt's worth noting that there are definitely exceptions where loop unrolling is a good practice for optimization. When writing code that will run on obscure old architectures, and even some common ones, the CPU doesn't have things like branch prediction and caches, and your compiler is likely quite rudimentary. As always, profiling is key.
- 0x400614 11y agoThat's a great insight. I had to read it a couple times to realize that the comment extended until it found `*/`. This would not pass my code review.
- comex 11y agoNot that the comment trick has anything to do with Duff's device, but any editor with syntax highlighting would display the commented-out lines in a different font, making the situation considerably more clear.
- buserror 11y agoDuff's is not just about unrolling, it's mostly a way to use the 'case can be anywhere inside a switch statement'. It's used a lot for other purpose, some of them very, very handy. The stackless coroutine trick is very useful for example (see http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html ) On platforms with very little RAM (embedded) it's fantastic to be able to 'port' linear code that might have run in a thread, and convert it to a coroutine that is a lot easier to read and maintain than having to convert it all up to a 'manual' state machine. Note that with gcc, you can reach the same results by using the 'indirect goto' that is both more powerful, and more dangerous! void * lab; lab = &my_label; goto *lab; my_label: ...