“Duff’s Device”是一个循环体展开技术,它使得一次迭代中实际执行了多次迭代的操作。它最早是在1983年C上由Tom Duff实现,然后2001年Jeff Greenberg移植到JavaScript上。
我们先来一个典型的实现方式:
//credit: Jeff Greenberg var iterations = Math.floor(items.length / 8), startAt = Items.length % 8, i = 0; do{ switch(startAt){ case 0: process(items[i++]); case 7: process(items[i++]); case 6: process(items[i++]); case 5: process(items[i++]); case 4: process(items[i++]); case 3: process(items[i++]); case 2: process(items[i++]); case 1: process(items[i++]); } }while(--iterations);
“Duff’s Device”基本原理是:在每次循环中调用8次process(),减少迭代次数。首先先用循环总数除以8求余数放入startAt,表示第一次循环应调用多少次process(),之后每次都会执行8次process()。
下面是此算法一个略微优化的版本,取消了switch语句
//credit: Jeff Greenberg var i = items.length % 8; while(i){ process(items[i--]); } i = Math.floor(items.length / 8); while(i){ process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); }
如果迭代次数很非常多,性能问题比较大的情况下,各位可以尝试一下这个算法。至于可读性吗……….大家自己根据实际情况权衡。
更多资料:Duff’s device Wiki
2011-08-19 更新
上面提供的两段代码有几处明显错误,之前自己只看懂了思路,代码没细看就放出来了,在这里更正一下:
var iterations = Math.floor(items.length / 8), startAt = Items.length % 8, i = 0; do{ switch(startAt){ case 0: process(items[i++]); case 7: process(items[i++]); case 6: process(items[i++]); case 5: process(items[i++]); case 4: process(items[i++]); case 3: process(items[i++]); case 2: process(items[i++]); case 1: process(items[i++]); } startAt = 0; //这里从书上少抄了 }while(iterations--); //可以改这里的条件,或者上面iterations的赋值
var t = items.length % 8 , i = 0; while(t){ process(items[i++]); } t = Math.floor(items.length / 8); while(t){ process(items[i++]); process(items[i++]); process(items[i++]); process(items[i++]); process(items[i++]); process(items[i++]); process(items[i++]); process(items[i++]); }
在此感谢二师兄指出问题哈!
Drop Comments