Skip to content

Commit

Permalink
Prevent v8 deopt with a few simple tweaks.
Browse files Browse the repository at this point in the history
Benchmark script shows a roughly ~40% improvement in model creation.
  • Loading branch information
STRML committed Oct 16, 2015
1 parent 6160314 commit 3cb5355
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 14 deletions.
28 changes: 15 additions & 13 deletions ampersand-state.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use strict';
/*$AMPERSAND_VERSION*/
var uniqueId = require('lodash.uniqueid');
var assign = require('lodash.assign');
Expand Down Expand Up @@ -625,16 +626,16 @@ var dataTypes = {
if (newVal == null) {
newType = typeof null;
} else if (!isDate(newVal)) {
try {
var dateVal = new Date(newVal).valueOf();
if (isNaN(dateVal)) {
// If the newVal cant be parsed, then try parseInt first
dateVal = new Date(parseInt(newVal, 10)).valueOf();
if (isNaN(dateVal)) throw TypeError;
}
newVal = dateVal;
newType = 'date';
} catch (e) {
var err = null;
var dateVal = new Date(newVal).valueOf();
if (isNaN(dateVal)) {
// If the newVal cant be parsed, then try parseInt first
dateVal = new Date(parseInt(newVal, 10)).valueOf();
if (isNaN(dateVal)) err = true;
}
newVal = dateVal;
newType = 'date';
if (err) {
newType = typeof newVal;
}
} else {
Expand Down Expand Up @@ -725,9 +726,9 @@ var dataTypes = {
// the extend method used to extend prototypes, maintain inheritance chains for instanceof
// and allow for additions to the model definitions.
function extend(protoProps) {
/*jshint validthis:true*/
var parent = this;
var child;
var args = [].slice.call(arguments);

// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
Expand Down Expand Up @@ -762,7 +763,8 @@ function extend(protoProps) {
var omitFromExtend = [
'dataTypes', 'props', 'session', 'derived', 'collections', 'children'
];
args.forEach(function processArg(def) {
for(var i = 0; i < arguments.length; i++) {
var def = arguments[i];
if (def.dataTypes) {
forEach(def.dataTypes, function (def, name) {
child.prototype._dataTypes[name] = def;
Expand Down Expand Up @@ -794,7 +796,7 @@ function extend(protoProps) {
});
}
assign(child.prototype, omit(def, omitFromExtend));
});
}
}

// Set a convenience property in case the parent's prototype is needed
Expand Down
54 changes: 54 additions & 0 deletions benchmark/massCreate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
var State = require('../ampersand-state');

function createModel() {
var aModel = State.extend({
derived: {
foo: {
deps: ['a', 'b'],
fn: function derived () {
return this.a + this.b;
}
}
}
});
return aModel;
}

//Function that contains the pattern to be inspected
var aModel = createModel();
function benchFn() {
return new aModel({a: 1, b: 2}).foo;
}

function printStatus(fn) {
switch(%GetOptimizationStatus(fn)) {
case 1: console.log("Function is optimized"); break;
case 2: console.log("Function is not optimized"); break;
case 3: console.log("Function is always optimized"); break;
case 4: console.log("Function is never optimized"); break;
case 6: console.log("Function is maybe deoptimized"); break;
}
}

//Fill type-info
benchFn();
// 2 calls are needed to go from uninitialized -> pre-monomorphic -> monomorphic
benchFn();
benchFn();
benchFn();
benchFn();
benchFn();

%OptimizeFunctionOnNextCall(benchFn);
//The next call
benchFn();

//Check
printStatus(benchFn);


console.time('createAModel');
for (var i = 0; i < 10000;i++) {
benchFn();
}
console.timeEnd('createAModel');
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@
"test": "browserify test/index.js | tape-run | tap-spec",
"validate": "npm ls",
"start": "run-browser test/index.js",
"lint": "jshint .",
"lint": "jshint --exclude benchmark/ .",
"benchmark": "node --allow-natives-syntax benchmark/massCreate.js",
"preversion": "git checkout master && git pull && npm ls",
"publish-patch": "npm run preversion && npm version patch && git push origin master --tags && npm publish",
"publish-minor": "npm run preversion && npm version minor && git push origin master --tags && npm publish",
Expand Down

0 comments on commit 3cb5355

Please sign in to comment.