I was wrong about Duff’s device
Duff’s device is a C language technique that looks like this:
send(to, from, count) {
register n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
It achieves two things:
- It unrolls the loop in chunks of eight. Unrolling the loop is when instead of telling the computer “do X 5 times,” you say “do X do X do X do X do X,” trading some code readability and memory usage for higher speed.
- It cleverly (ab)uses a property of the C language to unroll the remainder of the loop, which normally would be impossible to do as the remainder is less than 8 and different every time. It does so by basically overlapping a
do/whileloop atop aswitch/casestructure in a way that should come with a coding equivalent of a parental warning.
I always assumed the technique is from the 1970s and was just a show-offy thing that didn’t serve any function, a “look how clever I am” from a programmer who was perhaps just a touch too nerdy. But yesterday, I found a 1988 message from its inventor, Tom Duff, and it turns out I got almost everything wrong.
First of all, the technique was from 1983, when Duff was at Lucasfilm – much later than I expected.
Second of all, it actually solved a problem. Duff’s device wasn’t just making things faster abstractly, but actually fixed a user-visible performance issue. “[The loop before applying the device] was the bottleneck in a real-time animation playback program which ran too slowly by about 50%,” writes Duff.
Most importantly, however, Duff himself had mixed feelings about it:
Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and revulsion at this discovery.
I recognize this set of feelings from many different software hacks I invented in my life. I think it’s important to carry them all with you – not fall in love with the hack and continue seeing it for what it is (and what it will be in the future as code ages), but at the same time not be above using it if it’s solving a real issue.
Also, Duff adds:
Many people […] have said that the worst feature of C is that switches don’t break automatically before each case label. This code forms some sort of argument in that debate, but I’m not sure whether it’s for or against.
I can’t speak for C, but I have always felt frustrated about JavaScript stealing that convention – it’s so error-prone, and in my many years programming in it, I have never had to use a Duff’s device or anything else that benefitted from it.