Plain JS vs Immutable vs mori (v4)

Revision 4 of this benchmark created by Dave on


Preparation HTML

<script src="http://s3-eu-west-1.amazonaws.com/kosstest/commits.js"></script>
<script src="http://s3-eu-west-1.amazonaws.com/kosstest/Immutable.js"></script>
<script src="http://s3-eu-west-1.amazonaws.com/kosstest/mori.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>

Setup

window.immutableCommits = Immutable.fromJS(commitsOrigin);
    window.moriCommits = mori.js_to_clj(commitsOrigin);

Test runner

Ready to run.

Testing in
TestOps/sec
Plain JS
// 1. Group by authors
var groupedByAuthors = {};
commitsOrigin.forEach(function(c) {
  var email = c.commit.author.email;
  (groupedByAuthors[email] || (groupedByAuthors[email] = [])).push(c);
});

// 2. Sort by authors (asc)
var sortedAuthors = Object.keys(groupedByAuthors).sort();
var result = {};
sortedAuthors.forEach(function(author) {

  // 3. Group by hours
  var groupedByHours = {};
  groupedByAuthors[author].forEach(function(c) {
    var date = new Date(c.commit.author.date);
    date.setMinutes(0);
    var hour = date.toISOString();
    (groupedByHours[hour] || (groupedByHours[hour] = [])).push(c);
  });

  // 4. Sort by hours (desc)
  var sortedHours = Object.keys(groupedByHours).sort().reverse();
  var groupedAndSortedByHours = {};
  sortedHours.forEach(function(hour) {
    var commits = [];
    groupedByHours[hour].forEach(function(c) {
      commits.push(c);
    })

    // 5. Sort by time (desc)
    var sortedByTime = commits.sort(function(a, b) {
      return a.commit.author.date > a.commit.author.date ? -1 : 1;
    });

    groupedAndSortedByHours[hour] = sortedByTime;
  });

  result[author] = groupedAndSortedByHours;
});
ready
Immutable
var commits = immutableCommits;

// 1. Group by authors
var groupedByAuthors = commits.groupBy(function(c) {
  return c.getIn(['commit', 'author', 'email']);
});

// 2. Sort by authors (asc)
var sortedAuthors = groupedByAuthors.keySeq().sort();
var result = sortedAuthors.reduce(function(acc, author) {

  // 3. Group by hours
  var groupedByHours = groupedByAuthors.get(author).groupBy(function(c) {
    var date = new Date(c.getIn(['commit', 'author', 'date']));
    date.setMinutes(0);
    return date.toISOString();
  });

  // 4. Sort by hours (desc)
  var sortedHours = groupedByHours.keySeq().sort().reverse();
  var groupedAndSortedByHours = sortedHours.reduce(function(acc, hour) {
    var commits = groupedByHours.get(hour);

    // 5. Sort by time (desc)
    var sortedByTime = commits.sortBy(function(c) {
      return c.getIn(['commit', 'author', 'date']);
    }).reverse();

    return acc.set(hour, sortedByTime);
  }, Immutable.OrderedMap());

  return acc.set(author, groupedAndSortedByHours);
}, Immutable.OrderedMap());
 
ready
mori
// 1. Group by authors
var groupedByAuthors = mori.group_by(function(c) {
  return mori.get_in(c, ['commit', 'author', 'email']);
}, moriCommits);

// 2. Sort by authors (asc)
var sortedAuthors = mori.sort(mori.keys(groupedByAuthors));
var result = mori.reduce(function(acc, author) {

  // 3. Group by hours
  var groupedByHours = mori.group_by(function(c) {
    var date = new Date(mori.get_in(c, ['commit', 'author', 'date']));
    date.setMinutes(0);
    return date.toISOString();
  }, mori.get(groupedByAuthors, author));

  // 4. Sort by hours (desc)

  var sortedHours = mori.reverse(mori.sort(mori.keys(groupedByHours)));
  var groupedAndSortedByHours = mori.reduce(function(acc, hour) {
    var commits = mori.get(groupedByHours, hour);

    // 5. Sort by time (desc)
    var sortedByTime = mori.reverse(mori.sort_by(function(c) {
      return mori.get_in(c, ['commit', 'author', 'date']);
    }, commits));

    return mori.conj(acc, mori.vector(hour, sortedByTime))
  }, mori.vector(), sortedHours);

  return mori.conj(acc, mori.vector(author, groupedAndSortedByHours));
}, mori.vector(), sortedAuthors);
 
ready
Plain JS (optimized)
var i, j, k;

// 1. Group by authors
var groupedByAuthors = {}, c, email;
for (i = 0; i < commitsOrigin.length; i++) {
  c = commitsOrigin[i];
  email = c.commit.author.email;
  (groupedByAuthors[email] || (groupedByAuthors[email] = [])).push(c);
}

// 2. Sort by authors (asc)
var sortedAuthors = Object.keys(groupedByAuthors).sort();
var result = {}, author;
for (i = 0; i < sortedAuthors.length; i++) {
  author = sortedAuthors[i];

  // 3. Group by hours
  var groupedByHours = {};
  var authorCommits = groupedByAuthors[author];
  for (j = 0; j < authorCommits.length; j++) {
    c = authorCommits[j];
    var date = new Date(c.commit.author.date);
    date.setMinutes(0);
    var hour = date.toISOString();
    (groupedByHours[hour] || (groupedByHours[hour] = [])).push(c);
  }

  // 4. Sort by hours (desc)
  var sortedHours = Object.keys(groupedByHours).sort().reverse();
  var groupedAndSortedByHours = {}, hour;
  for (j = 0; j < sortedHours.length; j++) {
    hour = sortedHours[j];

    var commits = [];
    var hourCommits = groupedByHours[hour], c;
    for (k = 0; k < hourCommits.length; k++) {
      c = hourCommits[k];
      commits.push(c);
    }

    // 5. Sort by time (desc)
    var sortedByTime = commits.sort(function(a, b) {
      return a.commit.author.date > a.commit.author.date ? -1 : 1;
    });

    groupedAndSortedByHours[hour] = sortedByTime;
  };

  result[author] = groupedAndSortedByHours;
};
 
ready
Lodash
var groupedByAuthors, reduceIterator, result, sortedAuthors;

groupedByAuthors = _.groupBy(commitsOrigin, function(c) {
  return c.commit.author.email;
});

sortedAuthors = _.keys(groupedByAuthors).sort();

reduceIterator = function(acc, author) {
  var groupedAndSortedByHours, groupedByHours, iterator, sortedHours;
  groupedByHours = _.groupBy(groupedByAuthors[author], function(c) {
    var date;
    date = new Date(c.commit.author.date);
    date.setMinutes(0);
    return date.toISOString();
  });
  sortedHours = _.keys(groupedByHours).sort().reverse();
  iterator = function(acc, hour) {
    var commits, sortedByTime;
    commits = groupedByHours[hour];
    sortedByTime = _.sortBy(commits, function(c) {
      return c.commit.author.date;
    }).reverse();
    return acc[hour] = sortedByTime;
  };
  return groupedAndSortedByHours = _.reduce(sortedHours, iterator, {});
};

result = _.reduce(sortedAuthors, reduceIterator, {});
 
ready

Revisions

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