Duff's Device/Unrolled Max (v4)

Revision 4 of this benchmark created on


Description

Test loop unrolling techniques, such as Duff's Device implemented in JavaScript for a function to find the max value of an array.

Preparation HTML

<script>
  var data = (function() {
  
    var arr = [],
        i;
  
    for (i = 0; i < 10000; i += 1) {
      arr.push(Math.random());
    }
  
    return arr;
  }());
  
  
  var duffForEach = function(arr, f) {
      var len = arr.length,
          pos = 0;
  
      while (pos < len) {
        switch (pos % 10) {
        case 0:
          f(arr[pos]);
          pos++;
        case 9:
          f(arr[pos]);
          pos++;
        case 8:
          f(arr[pos]);
          pos++;
        case 7:
          f(arr[pos]);
          pos++;
        case 6:
          f(arr[pos]);
          pos++;
        case 5:
          f(arr[pos]);
          pos++;
        case 4:
          f(arr[pos]);
          pos++;
        case 3:
          f(arr[pos]);
          pos++;
        case 2:
          f(arr[pos]);
          pos++;
        case 1:
          f(arr[pos]);
          pos++;
        }
      }
  };
  
  
  var $duff = function (init, f, its) {
        
        its = its || 10;
        
        var ret = "$duff.out = function (arr) {"
                + "var len = arr.length,"
                + "pos = 0;"
                  + init.toString()
                + "switch (len % " + its + ") {",
                
                i;
        
        f = f.toString();
        f = f.replace(/(param)/g, "arr[pos++]");
        
        for (i = (its -1); i > 0; i -= 1) {
                ret += "case " + i + ": " + f + ";";
        }
        
        ret += "case 0: } while (pos < len) { ";
        
        for (i = 0; i < its; i += 1) {
                ret += f + ";";
        }
        
        ret += "}};";
        
        eval(ret);
        
        return $duff.out;
  };
  
  var composed = $duff("var max = 0;", "if (param > max) { max = param; }");
  
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
Rolled
var i, max = 0,
    len = data.length;

for (i = 0; i < len; i += 1) {
  if (data[i] > max) {
    max = data[i];
  }
}
ready
Unrolled
var i, max = 0,
    len = data.length;

for (i = 0; i < len; i += 10) {
  if (data[i] > max) {
    max = data[i];
  }
  if (data[i + 1] > max) {
    max = data[i + 1];
  }
  if (data[i + 2] > max) {
    max = data[i + 2];
  }
  if (data[i + 3] > max) {
    max = data[i + 3];
  }
  if (data[i + 4] > max) {
    max = data[i + 4];
  }
  if (data[i + 5] > max) {
    max = data[i + 5];
  }
  if (data[i + 6] > max) {
    max = data[i + 6];
  }
  if (data[i + 7] > max) {
    max = data[i + 7];
  }
  if (data[i + 8] > max) {
    max = data[i + 8];
  }
  if (data[i + 9] > max) {
    max = data[i + 9];
  }
}
ready
Duff-style
var max = 0;
duffForEach(data, function(item) {
  if (item > max) {
    max = item;
  }
});
ready
Duff-style + Eval
composed(data);
ready

Revisions

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