Duff's device (v31)

Revision 31 of this benchmark created by Jörg Schaper on


Description

Simple test of variations of loop unrolling/unwinding based on the original Duff's Device.

Result may vary based on the number of iterations, browser, OS and external influences...

Usually Fast Duff's Device #2, #3, #4 runs faster when the number of iterations is bigger or when the test is executed multiple times without browser refresh - bitwise operations have a really strange behavior in JS, sometimes they are really fast and other times they run slower than the Math methods.

Make sure you test each approach using real application code (since results may vary) and just use this kind of optimization if you really need it! Try to combine techniques and avoid property lookups!

PS: It's over 9000 iterations!

Preparation HTML

<script>
  var iterations = 12345;
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
Regular Loop 1
var testVal = 0;
var n = iterations;
while (n--) {
 testVal++;
}
ready
Duff's Device
/**
 * Duff's Device 
 * http://home.earthlink.net/~kendrasg/info/js_opt/jsOptMain.html#duffsdevice
 */
var testVal = 0;
var n = iterations / 8;
var caseTest = iterations % 8;

do {
 switch (caseTest) {
 case 0:
  testVal++;
 case 7:
  testVal++;
 case 6:
  testVal++;
 case 5:
  testVal++;
 case 4:
  testVal++;
 case 3:
  testVal++;
 case 2:
  testVal++;
 case 1:
  testVal++;
 }
 caseTest = 0;
}
while (--n > 0);
ready
Fast Duff's Device #1
/**
 * Fast Duff's Device
 * @author Jeff Greenberg
 * http://home.earthlink.net/~kendrasg/info/js_opt/jsOptMain.html#fastDuffsdevice
 */
var testVal = 0;
var n = iterations % 8;
while (n--) {
 testVal++;
}

n = parseInt(iterations / 8);
while (n--) {
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
}
ready
Fast Duff's Device #2
/*
 * Fast Duff's Device
 * @author Miller Medeiros <http://millermedeiros.com> 
 * @version 0.1 (2010/08/25)
 */
var testVal = 0;
var n = iterations % 8;
while (n--) {
 testVal++;
}

n = Math.floor(iterations / 8);
while (n--) {
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
}
ready
Fast Duff's Device #3
/*
 * Fast Duff's Device
 * @author Miller Medeiros <http://millermedeiros.com> 
 * @version 0.2 (2010/08/25)
 */
var testVal = 0;
var n = iterations % 8;
while (n--) {
 testVal++;
}

n = (iterations / 8) ^ 0; //`value ^ 0` is the same as `Math.floor` for positive numbers and `Math.ceil` for negative numbers
while (n--) {
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
}
ready
Fast Duff's Device #4
/*
 * Fast Duff's Device
 * @author Miller Medeiros <http://millermedeiros.com> 
 * @version 0.3 (2010/08/25)
 */
var testVal = 0;
var n = iterations % 8;
while (n--) {
 testVal++;
}

n = (iterations * 0.125) ^ 0; //multiplication is faster than division in some cases
while (n--) {
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
}
ready
Fast Duff's Device #5
/*
 * Fast Duff's Device JS.1
 * author: Jörg Schaper <Joerg_Schaper@gmx.de>
 * supplied: 2014/01/20
 */
var v = 0;
var i = iterations;
while(i>7){
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 i-=8;
};
while (i>0){
 v++;
 i--;
};
ready
Fast Duff's Device #6
/*
 * Fast Duff's Device JS.2
 * author: Jörg Schaper <Joerg_Schaper@gmx.de>
 * supplied: 2014/01/20
 */
var v = 0;
var i = iterations;
while(i>7){
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 i-=8;
};
switch(i){
 case(7):v++;
 case(6):v++;
 case(5):v++;
 case(4):v++;
 case(3):v++;
 case(2):v++;
 case(1):v++;
};
ready
Fast Duff's Device #7
/*
 * Fast Duff's Device JS.3
 * author: Jörg Schaper <Joerg_Schaper@gmx.de>
 * supplied: 2014/01/20
 */
var v = 0;
var i = iterations;
while(i>7){
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 v++;
 i-=8;
};
switch(i){
 case(7):v+=7;break;
 case(6):v+=6;break;
 case(5):v+=5;break;
 case(4):v+=4;break;
 case(3):v+=3;break;
 case(2):v+=2;break;
 case(1):v+=1;break;
};
ready
Fast Duff's Device #8
/*
 * Fast Duff's Device JS.4
 * author: Jörg Schaper <Joerg_Schaper@gmx.de>
 * supplied: 2014/01/21
 */
var v = 0;
var i = iterations;
while(i>15){
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 i-=16;
};
switch(i){
 case 15:v++;case 14:v++;case 13:v++;case 12:v++;
 case 11:v++;case 10:v++;case  9:v++;case  8:v++;
 case  7:v++;case  6:v++;case  5:v++;case  4:v++;
 case  3:v++;case  2:v++;case  1:v++;
};
ready
Fast Duff's Device #9
/*
 * Fast Duff's Device JS.5
 * author: Jörg Schaper <Joerg_Schaper@gmx.de>
 * supplied: 2014/01/21
 */
var v = 0;
var i = iterations;
while(i>31){
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 v++;v++;v++;v++;
 i-=32;
};
switch(i){
 case 31:v++;case 30:v++;case 29:v++;case 28:v++;
 case 27:v++;case 26:v++;case 25:v++;case 24:v++;
 case 23:v++;case 22:v++;case 21:v++;case 20:v++;
 case 19:v++;case 18:v++;case 17:v++;case 16:v++;
 case 15:v++;case 14:v++;case 13:v++;case 12:v++;
 case 11:v++;case 10:v++;case  9:v++;case  8:v++;
 case  7:v++;case  6:v++;case  5:v++;case  4:v++;
 case  3:v++;case  2:v++;case  1:v++;
};
ready
Regular Loop 2
//Jörg Schaper
var v = 0;
var i = iterations;
while (i>0) {
 v++;
 i--;
};
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.