defrecord ilookup switch

JavaScript performance comparison

Test case created by Francis Avila

Info

This is testing alternative ways of dispatching record field lookups to object properties. The purpose of this is to investigate alternative implementations of the case macro as this is one of the most important use cases.

These tests were prepared by compiling the following cljs file with {:optimizations :simple, :pretty-print true}:

(ns records)
(defrecord ifelse [field1 field2 field3 field4])
(defrecord switchstring [field1 field2 field3 field4])
(defrecord switchhash [field1 field2 field3 field4])

Then the -ilookup implementations of the generated javascript were replaced as follows:

The ifelse record was untouched. This does dispatch using cond, which emits chained if else conditions, which compile to chained ternary operators.

The switchstring record's ilookup implementation was replaced with the following:

records.switchstring.prototype.cljs$core$ILookup$_lookup$arity$3 = function(a, b, c) {
  if (b instanceof cljs.core.Keyword) {
    switch (b.fqn) {
      case "field1": return this.field1;
      case "field2": return this.field2;
      case "field3": return this.field3;
      case "field4": return this.field4;
    }
  }
  return cljs.core.get.call(null, this.__extmap, b, c);
};

The switchhash record's ilookup implementation was replaced with the following:

records.switchhash.prototype.cljs$core$ILookup$_lookup$arity$3 = function(a, b, c) {
  if (b instanceof cljs.core.Keyword) {
    switch (b._hash) {
      case 4034163177: return this.field1;
      case 4034163178: return this.field2;
      case 4034163179: return this.field3;
      case 4034163180: return this.field4;
    }
  }
  return cljs.core.get.call(null, this.__extmap, b, c);
};

Preparation code

<script src="https://dl.dropboxusercontent.com/u/18386249/defrecord-case-ilookup.js"></script>
<script>
Benchmark.prototype.setup = function() {
    var field1 = cljs.core.keyword("field1");
    var field2 = cljs.core.keyword("field2");
    var field3 = cljs.core.keyword("field3");
    var field4 = cljs.core.keyword("field4");
    var misskw = cljs.core.keyword("norecord");
    var badtype1 = "field1";
    var badtype2 = cljs.core.symbol("thesym");
   
    var ifelserec = new records.ifelse(1, 2, 3, 4);
    var switchstringrec = new records.switchstring(1, 2, 3, 4);
    var switchhashrec = new records.switchhash(1, 2, 3, 4);
   
    function useresult() {};
};

Benchmark.prototype.teardown = function() {
    var result2 = useresult(rfield1, rfield2, rfield3, rfield4, rmisskw, rbadtype1, rbadtype2);
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
if-else dispatch
var rfield1 = cljs.core.get(ifelserec, field1);
var rfield2 = cljs.core.get(ifelserec, field2);
var rfield3 = cljs.core.get(ifelserec, field3);
var rfield4 = cljs.core.get(ifelserec, field4);
var rmisskw = cljs.core.get(ifelserec, misskw);
var rbadtype1 = cljs.core.get(ifelserec, badtype1);
var rbadtype2 = cljs.core.get(ifelserec, badtype2);
 
pending…
string-switch dispatch
var rfield1 = cljs.core.get(switchstringrec, field1);
var rfield2 = cljs.core.get(switchstringrec, field2);
var rfield3 = cljs.core.get(switchstringrec, field3);
var rfield4 = cljs.core.get(switchstringrec, field4);
var rmisskw = cljs.core.get(switchstringrec, misskw);
var rbadtype1 = cljs.core.get(switchstringrec, badtype1);
var rbadtype2 = cljs.core.get(switchstringrec, badtype2);
 
pending…
hash-switch dispatch
var rfield1 = cljs.core.get(switchhashrec, field1);
var rfield2 = cljs.core.get(switchhashrec, field2);
var rfield3 = cljs.core.get(switchhashrec, field3);
var rfield4 = cljs.core.get(switchhashrec, field4);
var rmisskw = cljs.core.get(switchhashrec, misskw);
var rbadtype1 = cljs.core.get(switchhashrec, badtype1);
var rbadtype2 = cljs.core.get(switchhashrec, badtype2);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment