Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Commit

Permalink
Merge pull request #614 from mojit0/develop-perf
Browse files Browse the repository at this point in the history
Improve copy performance.
  • Loading branch information
mojit0 committed Oct 11, 2012
2 parents fe79b9a + 198fc77 commit 7a79647
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 131 deletions.
2 changes: 1 addition & 1 deletion lib/app/addons/rs/config.server.js
Expand Up @@ -103,7 +103,7 @@ YUI.add('addon-rs-config', function(Y, NAME) {
json, json,
ycb; ycb;


ctx = store.mergeRecursive(store.getStaticContext(), ctx); ctx = store.blendStaticContext(ctx);


if (!this._ycbCache[fullPath]) { if (!this._ycbCache[fullPath]) {
this._ycbCache[fullPath] = {}; this._ycbCache[fullPath] = {};
Expand Down
91 changes: 86 additions & 5 deletions lib/app/autoload/util.common.js
Expand Up @@ -193,24 +193,27 @@ YUI.add('mojito-util', function(Y) {


copy: function(oldObj) { copy: function(oldObj) {
var newObj, var newObj,
key; key,
len,
copy = Y.mojito.util.copy;


if (!oldObj || typeof oldObj !== 'object') { if (!oldObj || typeof oldObj !== 'object') {
return oldObj; return oldObj;
} }


if ('[object Array]' === Object.prototype.toString.apply(oldObj)) { if (Y.Lang.isArray(oldObj)) {
newObj = []; newObj = [];
for (key = 0; key < oldObj.length; key += 1) { len = oldObj.length;
newObj[key] = Y.mojito.util.copy(oldObj[key]); for (key = 0; key < len; key += 1) {
newObj[key] = copy(oldObj[key]);
} }
return newObj; return newObj;
} }


newObj = {}; newObj = {};
for (key in oldObj) { for (key in oldObj) {
if (oldObj.hasOwnProperty(key)) { if (oldObj.hasOwnProperty(key)) {
newObj[key] = Y.mojito.util.copy(oldObj[key]); newObj[key] = copy(oldObj[key]);
} }
} }
return newObj; return newObj;
Expand All @@ -224,6 +227,84 @@ YUI.add('mojito-util', function(Y) {
}, },




/**
* Blends a source base object and an overlay object to create a new
* object containing the recursively merged values of the two. This is
* similar to performing a copy and then a mergeRecursive operation but
* is intended to be more performant by avoiding duplicate work.
* @param {Object} base The base object. Properties in this object may
* be overwritten by those in overlay.
* @param {Object} extension The "overlay" object. Properties in this
* object are always found in the result.
* @return {Object} A new object containing the blended values.
*/
blend: function(base, overlay) {

var tmp,
dest,
i,
slot,
slotType,
copy = Y.mojito.util.copy,
blend = Y.mojito.util.blend;

// Protect from bad input data.
if (base === null || base === undefined) {
return copy(overlay);
}
if (overlay === null || overlay === undefined) {
return copy(base);
}

if (Y.Lang.isArray(overlay)) {
if (!Y.Lang.isArray(base)) {
throw new Error('Type mismatch for object merge.');
}

tmp = base.slice(0);
tmp.push.apply(tmp, overlay);
dest = Y.Array.unique(tmp);
tmp.length = 0;
} else {
dest = {};
for (i in overlay) {
if (overlay.hasOwnProperty(i)) {
if (base.hasOwnProperty(i)) {
// "Conflicting" property. A recursive merge of the
// value is required if it's a complex object.
slot = overlay[i];
slotType = typeof slot;
if ((slotType === 'object') &&
(slot !== null)) {
// Complex, not null.
dest[i] = blend(base[i], overlay[i]);
} else {
// Simple value or null. Overlay value wins.
dest[i] = overlay[i];
}
} else {
// Unique to the overlay object, no merge needed.
dest[i] = copy(overlay[i]);
}
}
}

// Verify we didn't miss properties in the base. Anything
// missing from the destination object should be copied.
// Anything already there would have been merged in the previous
// loop.
for (i in base) {
if (base.hasOwnProperty(i)) {
if (!dest.hasOwnProperty(i)) {
dest[i] = copy(base[i]);
}
}
}
}
return dest;
},


/** /**
* Recursively merge properties of two objects * Recursively merge properties of two objects
* @method mergeRecursive * @method mergeRecursive
Expand Down
29 changes: 0 additions & 29 deletions lib/app/commands/test.js
Expand Up @@ -277,35 +277,6 @@ function merge() {
} }




/**
* Perform a deep merge.
* @param {Object} dest The destination object.
* @param {Object} src The source object.
* @return {Object} The merged object.
*/
function mergeRecursive(dest, src) {
var p;

for (p in src) {
if (src.hasOwnProperty(p)) {
try {
// Property in destination object set; update its value.
if (src[p].constructor === Object) {
dest[p] = mergeRecursive(dest[p], src[p]);
} else {
dest[p] = src[p];
}
} catch (e) {
// Property in destination object not set; create it and set its
// value.
dest[p] = src[p];
}
}
}
return dest;
}


function preProcessor() { function preProcessor() {


var filepath, var filepath,
Expand Down
3 changes: 1 addition & 2 deletions lib/management/yui-module-configurator.js
Expand Up @@ -118,8 +118,7 @@ module.exports = function(dir, excludes) {
return modules; return modules;
} }


// array test copied from Y.Lang.isArray() if (Y.Lang.isArray(dir))
if ('[object Array]' !== Object.prototype.toString.call(dir)) {
dir = [dir]; dir = [dir];
} }


Expand Down
69 changes: 23 additions & 46 deletions lib/store.server.js
Expand Up @@ -287,6 +287,17 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
}, },




/**
* Returns the context provided blended with the static
* (non-runtime-sensitive) context.
* @method blendStaticContext
* @param {object} ctx The context to blend.
* @return {object} the context
*/
blendStaticContext: function(ctx) {
return Y.mojito.util.blend(this._config.context, ctx);
},

/** /**
* Returns the static (non-runtime-sensitive) context * Returns the static (non-runtime-sensitive) context
* @method getStaticContext * @method getStaticContext
Expand Down Expand Up @@ -334,12 +345,9 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
return Y.mojito.util.copy(this._appConfigCache[key]); return Y.mojito.util.copy(this._appConfigCache[key]);
} }


// start with the base
appConfig = Y.mojito.util.copy(this._fwConfig.appConfigBase);

// apply the read values from the file
ycb = this.config.readConfigYCB(this._libs.path.join(this._config.root, 'application.json'), ctx); ycb = this.config.readConfigYCB(this._libs.path.join(this._config.root, 'application.json'), ctx);
this.mergeRecursive(appConfig, ycb);
appConfig = Y.mojito.util.blend(this._fwConfig.appConfigBase, ycb);


this._appConfigCache[key] = appConfig; this._appConfigCache[key] = appConfig;


Expand Down Expand Up @@ -523,10 +531,12 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
spec, spec,
typeDetails, typeDetails,
config, config,
perf; perf,
newInst;


if (cacheValue) { if (cacheValue) {
cb(null, Y.mojito.util.mergeRecursive(Y.mojito.util.copy(cacheValue), instance)); newInst = Y.mojito.util.blend(cacheValue, instance);
cb(null, newInst);
return; return;
} }


Expand Down Expand Up @@ -558,13 +568,12 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
perf.done(); perf.done();
} }
if (spec.defaults && spec.defaults.config) { if (spec.defaults && spec.defaults.config) {
config = Y.mojito.util.copy(spec.defaults.config); config = Y.mojito.util.blend(spec.defaults.config, spec.config);
this.mergeRecursive(config, spec.config);
spec.config = config; spec.config = config;
} }


this._expandInstanceCache[env][cacheKey] = spec; this._expandInstanceCache[env][cacheKey] = spec;
cb(null, Y.mojito.util.mergeRecursive(Y.mojito.util.copy(spec), instance)); cb(null, Y.mojito.util.blend(spec, instance));
}, },




Expand Down Expand Up @@ -821,41 +830,6 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
return urls; return urls;
}, },


/**
* Recursively merge one object onto another.
* [original implementation](http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically/383245#383245)
*
* @method mergeRecursive
* @param {object} dest object to merge into
* @param {object} src object to merge onto "dest"
* @param {boolean} typeMatch controls whether a non-object in the src is
* allowed to clobber a non-object in the dest (if a different type)
* @return {object} the modified "dest" object is also returned directly
*/
mergeRecursive: function(dest, src, typeMatch) {
var p;
for (p in src) {
if (src.hasOwnProperty(p)) {
// Property in destination object set; update its value.
if (src[p] && src[p].constructor === Object) {
if (!dest[p]) {
dest[p] = {};
}
dest[p] = this.mergeRecursive(dest[p], src[p]);
} else {
if (dest[p] && typeMatch) {
if (typeof dest[p] === typeof src[p]) {
dest[p] = src[p];
}
} else {
dest[p] = src[p];
}
}
}
}
return dest;
},



//==================================================================== //====================================================================
// CALLBACK METHODS // CALLBACK METHODS
Expand Down Expand Up @@ -1468,7 +1442,10 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
} }


delete spec.base; delete spec.base;
return this.mergeRecursive(this._expandSpec(env, ctx, base), spec); return Y.mojito.util.mergeRecursive(
this._expandSpec(env, ctx, base),
spec
);
}, },




Expand Down
24 changes: 0 additions & 24 deletions lib/tests/autoload/app/addons/rs/config-tests.server.js
Expand Up @@ -36,30 +36,6 @@ YUI.add('mojito-addon-rs-config-tests', function(Y, NAME) {
return this._config.context || {}; return this._config.context || {};
}, },


mergeRecursive: function(dest, src, typeMatch) {
var p;
for (p in src) {
if (src.hasOwnProperty(p)) {
// Property in destination object set; update its value.
if (src[p] && src[p].constructor === Object) {
if (!dest[p]) {
dest[p] = {};
}
dest[p] = this.mergeRecursive(dest[p], src[p]);
} else {
if (dest[p] && typeMatch) {
if (typeof dest[p] === typeof src[p]) {
dest[p] = src[p];
}
} else {
dest[p] = src[p];
}
}
}
}
return dest;
},

findResourceVersionByConvention: function(source, mojitType) { findResourceVersionByConvention: function(source, mojitType) {
// no-op // no-op
}, },
Expand Down
28 changes: 4 additions & 24 deletions tests/unit/lib/app/addons/rs/test-config.server.js
Expand Up @@ -3,8 +3,8 @@
* Copyrights licensed under the New BSD License. * Copyrights licensed under the New BSD License.
* See the accompanying LICENSE file for terms. * See the accompanying LICENSE file for terms.
*/ */
YUI().use('addon-rs-config', 'base', 'oop', 'test', function(Y) { YUI().use('addon-rs-config', 'mojito-util', 'base', 'oop', 'test', function(Y) {

var suite = new YUITest.TestSuite('mojito-addon-rs-config-tests'), var suite = new YUITest.TestSuite('mojito-addon-rs-config-tests'),
libfs = require('fs'), libfs = require('fs'),
libpath = require('path'), libpath = require('path'),
Expand Down Expand Up @@ -36,28 +36,8 @@ YUI().use('addon-rs-config', 'base', 'oop', 'test', function(Y) {
return this._config.context || {}; return this._config.context || {};
}, },


mergeRecursive: function(dest, src, typeMatch) { blendStaticContext: function(ctx) {
var p; return Y.mojito.util.blend(this._config.context, ctx);
for (p in src) {
if (src.hasOwnProperty(p)) {
// Property in destination object set; update its value.
if (src[p] && src[p].constructor === Object) {
if (!dest[p]) {
dest[p] = {};
}
dest[p] = this.mergeRecursive(dest[p], src[p]);
} else {
if (dest[p] && typeMatch) {
if (typeof dest[p] === typeof src[p]) {
dest[p] = src[p];
}
} else {
dest[p] = src[p];
}
}
}
}
return dest;
}, },


findResourceVersionByConvention: function(source, mojitType) { findResourceVersionByConvention: function(source, mojitType) {
Expand Down

0 comments on commit 7a79647

Please sign in to comment.