- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Hubert's co-worker puts Duff to shame,
Admin
Like Duff's device, just with
if
instead of a loopAdmin
Isn't this just an example of code-reuse at an advanced level? It even makes sense when minimizing CPU-cycles is of the utmost importance.
Some people get celebrated for doing stuff like that (Duff's device springs to mind), others apparently get their code anonymized.
Admin
Either the use case does not need the heavy optimisation and this should be written more clearly, or it does and that thing needs a comment explaining the actual logic that it should be implementing (and some tests too).
Admin
How is this code re-use? Calling the same method in a few places is not repetition; that's what methods (procedures/functions) are for - they're created once and called when they are needed. If doStuff() is actually a block of code and not just a method call, then that block of code should be moved to a method. If it's performance critical, then inlining should be considered.
Also, how does that improve performance? If it's option A, it still checks boolX and boolB; if it's options B or C, there is no need for ifs anyway.
The code below is functionally and performance-wise equivalent to the snippet in the article:
Addendum 2022-06-29 09:37: PS. ... while being much easier to read and understand.
Addendum 2022-06-29 09:43: PPS. Remy it bothers me - please fix the indentation in my code snippet.
Admin
That could easily turn into a mess. That said we have "Select" statements in RPG where you can have conditions based on many things instead of on just one variable. It works well, is easy to read and is much more flexible than a switch statement. It looks like this: select; when a=b; do some stuff; when c=d; do some different stuff; when x contains '3'; do yet another different stuff; other; do some default stuff; endsl;
Admin
Looks like a missing "}"
@Mr. TA - not FUNCTIONALLY equivalent at the deepest levels. The flow through the processors pipelines (With look ahead) will be different as will the timing.
Admin
Compilers are perfectly capable of building a truth table and either code will compile down to identical assembly even without optimization active: https://godbolt.org/z/xdxa8ceT5. Someone who understand so little about C that they think it's still a glorified assembler should really leave the compiling to compilers.
Admin
Honestly, I think this is the first time I've been grateful C# doesn't allow case fall-through like this.
Admin
The most cringeworthy switch statement I encountered in my early years of programming was in an introductory book on programming for Windows 3. The first demo app all the way to the glorious big example at the end of the book were just gigantic switch/case statements. I quickly found another paradigm, but I can't imagine how many programmers were screwed up by that book.
Admin
It's not the most horrible
switch
I've seen, but that at least had the excuse of being extremely performance critical and other alternatives were slower, and measured to be so. (It also had So. Many.goto
s.) There's an ongoing project to do better, but it involves some pretty fancy tech and a lot of overheads.Admin
@guest - I do write compilers for a living [usually DSL]. I did test with the compiler I had handy [for embedded ARM] and there was a two instruction difference. This is enough that the pipelines would behave differently. 99.999% of the time, it does not matter - but given a bug that bit me many years ago [sailors thought a Frigate was sinking!] caused by a "insignificant change" I am VERY cautious of the word identical.
Admin
Two principles allow you to see through the mess. 1) case statements falls through, 2) a jump instruction is placed at the end of a conditionally executed block of code to have it jump to the end of the if/else overall block. If you did something like sneak in a lil' function before break of case 'C', it would be executed every single time either 'A','B', or 'C' is the someValue.
Admin
"sailors thought a Frigate was sinking!" I'm guessing this was some sort of accumulated error type of "identical" - i.e. the type of accumulated error that would wreak havoc if you tried rotating a cube in "3D" on the screen and used the previously calculated values for the corners to calculate the next ones.
Admin
Duff's Device is fine, because it's obvious what it does even though the syntax looks like it shouldn't. It's a simple way of unrolling a loop and dealing with the nasty "excess" you always have.
Example - you need to do something, but the only way to do it in time is if you do chunk it out 8 at a time. So you unroll the loop and do the action 8 times.
But you then use Duff's device to handle the leftover bit - perhaps you have 20 elements you need to go over, so you have 4 extra things to do.
Duff's device makes it easy to see that you've unrolled the loop and handled the excess in one compact thing.
But this is an abomination, purely because the truth table is just ... strange. You have to work out what it's actually doing. Rolling conditionals inside other conditionals ... just makes a mess. Duff's device wraps a conditional inside a loop to perform just part of a loop, and since the actions are the same, it's obvious from a casual read what it's doing.
Oh and these days, modern computers are fast - between the branch predictor and such, Duff's device isn't likely to be any faster than writing it cleanly since it'll all be single cycle instructions with no pipeline stalls anyways.
This... is just spaghetti in the truest sense of it.
Admin
Alas, he didn't fix it. Yes, indentation and missing }.
In this case, no doubt it's possible it will have a slightly different assembly output. However, when I say "functionally", I mean given the same inputs, the outputs will be the same. If they are not - again, I'm talking about this case only - it's either a bug in the CPU or the compiler.
Addendum 2022-06-29 17:57: Actually no, there is no missing }.
Admin
Interestingly, if you replace if (boolX) with if (false) in the sandbox, the if(false) conditional check gets optimized away, but not the Branch 0 statement, because it's honoring the label created by case 'B'. It also preserves the "jump to the end of all the if/else statements" jump corresponding to the else if(boolB) line.
It makes so much more sense when using the godbolt online compiler, where you can see the assembly and follow jump links with Ctrl+Left Click. https://godbolt.org/z/EEzT6dY54
Admin
Huh, I'd thought that Duff's Device-a-likes would have stopped working when we started having better understanding of compiler theory, and in particular parser mechanisms. (Come on, we all had to walk through LALR(1) examples on chalkboard, right?)
Admin
Actually, if my memory serves me correctly, that was the accepted way to program for Windows 3 inside the main message loop for your windows application, I suspect that even Charles Petzold would agree.
Admin
It looks like the code I get when writing hand-optimized 8-bit assembly code using c and the c compiler to do so.
(It's not just the two extra instructions added by doing it the clear way -- it's the c optimizer completely re-ordering the code and register allocation. Even when the c is unreadable, and you have to recompile after every change to see if the machine code has gotten bigger, it's still clearer than an unfamiliar instruction set).