达夫设备(Duff's Device)

网上看到一段有趣的代码, 叫达夫设备. 这段代码主要用来做字符拷贝. 这段代码的优势在于卓越的性能, 这段代码有两个比较有趣的地方: 1. case 语句没有break 2. 在switch 语句中杂糅了while 语句
首先来看这个case 语句, "case 1:" 这个是标号, 只对goto 和switch 语句有效. 如果不在这两个语境中, 标号可以忽略. 标号的作用就在于跳转. 如果没有break 语句, 在switch 语句中命中一个标号之后, 会继续执行后面所有的代码(忽略后面的标号). 所以我们来看达夫设备这段代码中, 首次进入switch 语句, 命中"case 4:" 这个标号, 然后就依次执行后面所有的代码(忽略"case 3:" 等其他标号. switch 语句类似于goto, 用于跳转). 接下来由while 语句接管, 每8个一组拷贝. 每个while 循环会从do 开始执行, 之后再也不会走到switch 判断了. 其实这段代码把 "case 0:" 写到do{} 语句里面也是可以的. 达夫设备的本质就是"首次利用标号跳转, 以后都用循环, 因为标号只对跳转有效. "
为什么达夫设备的拷贝效率更高呢? 看下面的实例代码:
for (int i = 0; i < count; i++) {*to++ = *from++;}
实例代码中, 循环一次拷贝一个字符, 但是达夫设备中, 循环一次拷贝8个字符. 赋值是简单的操作, 但是循环是比较重的操作. 而且每次循环都要做一次比较, 因此整体上实例代码的运行效率比达夫设备低的多.
另外介绍几个命令:
g++ -S test_duffs_device.cpp 生成 test_duffs_devoce.s 汇编代码.
strings 查看二进制文件中的字符
readelf -a bin_file 查看二进制文件的elf 信息