Skip to content

Commit

Permalink
[Bugfix Beta] Improve performance of Mixin creation by 50% -> 60% (wh…
Browse files Browse the repository at this point in the history
…en mixins are composed of multiple mixins)

* shape Mixin correctly (properties set in constructor)
* don’t pass arguments object around
* prefer new Mixin(args, properties) internally

This isn’t really going to have much of an impact by itself, but is part of a larger push  to improve the performance of our existing object model.
  • Loading branch information
stefanpenner committed Nov 12, 2014
1 parent ac75d2d commit b76ee54
Showing 1 changed file with 37 additions and 33 deletions.
70 changes: 37 additions & 33 deletions packages/ember-metal/lib/mixin.js
Expand Up @@ -11,7 +11,6 @@
import Ember from "ember-metal/core"; // warn, assert, wrap, et;
import merge from "ember-metal/merge";
import {
map as a_map,
indexOf as a_indexOf,
forEach as a_forEach
} from "ember-metal/array";
Expand Down Expand Up @@ -76,22 +75,6 @@ function mixinsMeta(obj) {
return ret;
}

function initMixin(mixin, args) {
if (args && args.length > 0) {
mixin.mixins = a_map.call(args, function(x) {
if (x instanceof Mixin) { return x; }

// Note: Manually setup a primitive mixin here. This is the only
// way to actually get a primitive mixin. This way normal creation
// of mixins will give you combined mixins...
var mixin = new Mixin();
mixin.properties = x;
return mixin;
});
}
return mixin;
}

function isMethod(obj) {
return 'function' === typeof obj &&
obj.isMethod !== false &&
Expand Down Expand Up @@ -538,12 +521,29 @@ export function mixin(obj) {
@namespace Ember
*/
export default Mixin;
function Mixin() { return initMixin(this, arguments); }
Mixin.prototype = {
properties: null,
mixins: null,
ownerConstructor: null
};
function Mixin(args, properties) {
this.properties = properties;

var length = args && args.length;

if (length > 0) {
var m = new Array(length);

for (var i = 0; i < length; i++) {
var x = args[i];
if (x instanceof Mixin) {
m[i] = x;
} else {
m[i] = new Mixin(undefined, x);
}
}

this.mixins = m;
} else {
this.mixins = undefined;
}
this.ownerConstructor = undefined;
}

Mixin._apply = applyMixin;

Expand All @@ -566,7 +566,12 @@ Mixin.create = function() {
// ES6TODO: this relies on a global state?
Ember.anyUnprocessedMixins = true;
var M = this;
return initMixin(new M(), arguments);
var length = arguments.length;
var args = new Array(length);
for (var i = 0; i < length; i++) {
args[i] = arguments[i];
}
return new M(args, undefined);
};

var MixinPrototype = Mixin.prototype;
Expand All @@ -576,12 +581,11 @@ var MixinPrototype = Mixin.prototype;
@param arguments*
*/
MixinPrototype.reopen = function() {
var mixin, tmp;
var mixin;

if (this.properties) {
mixin = Mixin.create();
mixin.properties = this.properties;
delete this.properties;
mixin = new Mixin(undefined, this.properties);
this.properties = undefined;
this.mixins = [mixin];
} else if (!this.mixins) {
this.mixins = [];
Expand All @@ -600,9 +604,7 @@ MixinPrototype.reopen = function() {
if (mixin instanceof Mixin) {
mixins.push(mixin);
} else {
tmp = Mixin.create();
tmp.properties = mixin;
mixins.push(tmp);
mixins.push(new Mixin(undefined, mixin));
}
}

Expand Down Expand Up @@ -654,7 +656,7 @@ MixinPrototype.detect = function(obj) {
};

MixinPrototype.without = function() {
var ret = new Mixin(this);
var ret = new Mixin([this]);
ret._without = a_slice.call(arguments);
return ret;
};
Expand All @@ -679,7 +681,9 @@ MixinPrototype.keys = function() {
var ret = [];
_keys(keys, this, seen);
for(var key in keys) {
if (keys.hasOwnProperty(key)) { ret.push(key); }
if (keys.hasOwnProperty(key)) {
ret.push(key);
}
}
return ret;
};
Expand Down

0 comments on commit b76ee54

Please sign in to comment.