358 lines
9.0 KiB
JavaScript
358 lines
9.0 KiB
JavaScript
/*
|
|
* Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
* Code distributed by Google as part of the polymer project is also
|
|
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
*/
|
|
|
|
(function(global) {
|
|
'use strict';
|
|
|
|
var createObject = ('__proto__' in {}) ?
|
|
function(obj) { return obj; } :
|
|
function(obj) {
|
|
var proto = obj.__proto__;
|
|
if (!proto)
|
|
return obj;
|
|
var newObject = Object.create(proto);
|
|
Object.getOwnPropertyNames(obj).forEach(function(name) {
|
|
Object.defineProperty(newObject, name,
|
|
Object.getOwnPropertyDescriptor(obj, name));
|
|
});
|
|
return newObject;
|
|
};
|
|
|
|
function ObservationBenchmark(objectCount) {
|
|
Benchmark.call(this);
|
|
this.objectCount = objectCount;
|
|
}
|
|
|
|
ObservationBenchmark.prototype = createObject({
|
|
__proto__: Benchmark.prototype,
|
|
|
|
setup: function() {
|
|
this.mutations = 0;
|
|
|
|
if (this.objects)
|
|
return;
|
|
|
|
this.objects = [];
|
|
this.observers = [];
|
|
this.objectIndex = 0;
|
|
|
|
while (this.objects.length < this.objectCount) {
|
|
var obj = this.newObject();
|
|
this.objects.push(obj);
|
|
var observer = this.newObserver(obj);
|
|
observer.open(this.observerCallback, this);
|
|
this.observers.push(observer);
|
|
}
|
|
},
|
|
|
|
test: function(mutationCount) {
|
|
while (mutationCount > 0) {
|
|
var obj = this.objects[this.objectIndex];
|
|
mutationCount -= this.mutateObject(obj);
|
|
this.mutations++;
|
|
this.objectIndex++;
|
|
if (this.objectIndex == this.objects.length) {
|
|
this.objectIndex = 0;
|
|
}
|
|
}
|
|
},
|
|
|
|
cleanup: function() {
|
|
if (this.mutations !== 0)
|
|
alert('Error: mutationCount == ' + this.mutationCount);
|
|
|
|
this.mutations = 0;
|
|
},
|
|
|
|
dispose: function() {
|
|
this.objects = null;
|
|
while (this.observers.length) {
|
|
this.observers.pop().close();
|
|
}
|
|
this.observers = null;
|
|
if (Observer._allObserversCount != 0) {
|
|
alert('Observers leaked');
|
|
}
|
|
},
|
|
|
|
observerCallback: function() {
|
|
this.mutations--;
|
|
}
|
|
});
|
|
|
|
function SetupObservationBenchmark(objectCount) {
|
|
Benchmark.call(this);
|
|
this.objectCount = objectCount;
|
|
}
|
|
|
|
SetupObservationBenchmark.prototype = createObject({
|
|
__proto__: Benchmark.prototype,
|
|
|
|
setup: function() {
|
|
this.mutations = 0;
|
|
this.objects = [];
|
|
this.observers = [];
|
|
|
|
while (this.objects.length < this.objectCount) {
|
|
var obj = this.newObject();
|
|
this.objects.push(obj);
|
|
}
|
|
},
|
|
|
|
test: function() {
|
|
for (var i = 0; i < this.objects.length; i++) {
|
|
var obj = this.objects[i];
|
|
var observer = this.newObserver(obj);
|
|
observer.open(this.observerCallback, this);
|
|
this.observers.push(observer);
|
|
}
|
|
},
|
|
|
|
cleanup: function() {
|
|
while (this.observers.length) {
|
|
this.observers.pop().close();
|
|
}
|
|
if (Observer._allObserversCount != 0) {
|
|
alert('Observers leaked');
|
|
}
|
|
this.objects = null;
|
|
this.observers = null;
|
|
|
|
},
|
|
|
|
dispose: function() {
|
|
}
|
|
});
|
|
|
|
function ObjectBenchmark(config, objectCount) {
|
|
ObservationBenchmark.call(this, objectCount);
|
|
this.properties = [];
|
|
for (var i = 0; i < ObjectBenchmark.propertyCount; i++) {
|
|
this.properties.push(String.fromCharCode(97 + i));
|
|
}
|
|
}
|
|
|
|
ObjectBenchmark.configs = [];
|
|
ObjectBenchmark.propertyCount = 15;
|
|
|
|
ObjectBenchmark.prototype = createObject({
|
|
__proto__: ObservationBenchmark.prototype,
|
|
|
|
newObject: function() {
|
|
var obj = {};
|
|
for (var j = 0; j < ObjectBenchmark.propertyCount; j++)
|
|
obj[this.properties[j]] = j;
|
|
|
|
return obj;
|
|
},
|
|
|
|
newObserver: function(obj) {
|
|
return new ObjectObserver(obj);
|
|
},
|
|
|
|
mutateObject: function(obj) {
|
|
var size = Math.floor(ObjectBenchmark.propertyCount / 3);
|
|
for (var i = 0; i < size; i++) {
|
|
obj[this.properties[i]]++;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
});
|
|
|
|
function SetupObjectBenchmark(config, objectCount) {
|
|
SetupObservationBenchmark.call(this, objectCount);
|
|
this.properties = [];
|
|
for (var i = 0; i < ObjectBenchmark.propertyCount; i++) {
|
|
this.properties.push(String.fromCharCode(97 + i));
|
|
}
|
|
}
|
|
|
|
SetupObjectBenchmark.configs = [];
|
|
SetupObjectBenchmark.propertyCount = 15;
|
|
|
|
SetupObjectBenchmark.prototype = createObject({
|
|
__proto__: SetupObservationBenchmark.prototype,
|
|
|
|
newObject: function() {
|
|
var obj = {};
|
|
for (var j = 0; j < SetupObjectBenchmark.propertyCount; j++)
|
|
obj[this.properties[j]] = j;
|
|
|
|
return obj;
|
|
},
|
|
|
|
newObserver: function(obj) {
|
|
return new ObjectObserver(obj);
|
|
}
|
|
});
|
|
|
|
function ArrayBenchmark(config, objectCount) {
|
|
ObservationBenchmark.call(this, objectCount);
|
|
var tokens = config.split('/');
|
|
this.operation = tokens[0];
|
|
this.undo = tokens[1];
|
|
};
|
|
|
|
ArrayBenchmark.configs = ['splice', 'update', 'push/pop', 'shift/unshift'];
|
|
ArrayBenchmark.elementCount = 100;
|
|
|
|
ArrayBenchmark.prototype = createObject({
|
|
__proto__: ObservationBenchmark.prototype,
|
|
|
|
newObject: function() {
|
|
var array = [];
|
|
for (var i = 0; i < ArrayBenchmark.elementCount; i++)
|
|
array.push(i);
|
|
return array;
|
|
},
|
|
|
|
newObserver: function(array) {
|
|
return new ArrayObserver(array);
|
|
},
|
|
|
|
mutateObject: function(array) {
|
|
switch (this.operation) {
|
|
case 'update':
|
|
var mutationsMade = 0;
|
|
var size = Math.floor(ArrayBenchmark.elementCount / 10);
|
|
for (var j = 0; j < size; j++) {
|
|
array[j*size] += 1;
|
|
mutationsMade++;
|
|
}
|
|
return mutationsMade;
|
|
|
|
case 'splice':
|
|
var size = Math.floor(ArrayBenchmark.elementCount / 5);
|
|
var removed = array.splice(size, size);
|
|
Array.prototype.splice.apply(array, [size*2, 0].concat(removed));
|
|
return size * 2;
|
|
|
|
default:
|
|
var val = array[this.undo]();
|
|
array[this.operation](val + 1);
|
|
return 2;
|
|
}
|
|
}
|
|
});
|
|
|
|
function SetupArrayBenchmark(config, objectCount) {
|
|
ObservationBenchmark.call(this, objectCount);
|
|
};
|
|
|
|
SetupArrayBenchmark.configs = [];
|
|
SetupArrayBenchmark.propertyCount = 15;
|
|
|
|
SetupArrayBenchmark.prototype = createObject({
|
|
__proto__: SetupObservationBenchmark.prototype,
|
|
|
|
newObject: function() {
|
|
var array = [];
|
|
for (var i = 0; i < ArrayBenchmark.elementCount; i++)
|
|
array.push(i);
|
|
return array;
|
|
},
|
|
|
|
newObserver: function(array) {
|
|
return new ArrayObserver(array);
|
|
}
|
|
});
|
|
|
|
function PathBenchmark(config, objectCount) {
|
|
ObservationBenchmark.call(this, objectCount);
|
|
this.leaf = config === 'leaf';
|
|
this.path = Path.get('foo.bar.baz');
|
|
this.firstPathProp = Path.get(this.path[0]);
|
|
}
|
|
|
|
PathBenchmark.configs = ['leaf', 'root'];
|
|
|
|
PathBenchmark.prototype = createObject({
|
|
__proto__: ObservationBenchmark.prototype,
|
|
|
|
newPath: function(parts, value) {
|
|
var obj = {};
|
|
var ref = obj;
|
|
var prop;
|
|
for (var i = 0; i < parts.length - 1; i++) {
|
|
prop = parts[i];
|
|
ref[prop] = {};
|
|
ref = ref[prop];
|
|
}
|
|
|
|
prop = parts[parts.length - 1];
|
|
ref[prop] = value;
|
|
|
|
return obj;
|
|
},
|
|
|
|
newObject: function() {
|
|
return this.newPath(this.path, 1);
|
|
},
|
|
|
|
newObserver: function(obj) {
|
|
return new PathObserver(obj, this.path);
|
|
},
|
|
|
|
mutateObject: function(obj) {
|
|
var val = this.path.getValueFrom(obj);
|
|
if (this.leaf) {
|
|
this.path.setValueFrom(obj, val + 1);
|
|
} else {
|
|
this.firstPathProp.setValueFrom(obj, this.newPath(this.path.slice(1), val + 1));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
});
|
|
|
|
function SetupPathBenchmark(config, objectCount) {
|
|
ObservationBenchmark.call(this, objectCount);
|
|
this.path = Path.get('foo.bar.baz');
|
|
}
|
|
|
|
SetupPathBenchmark.configs = [];
|
|
|
|
SetupPathBenchmark.prototype = createObject({
|
|
__proto__: SetupObservationBenchmark.prototype,
|
|
|
|
newPath: function(parts, value) {
|
|
var obj = {};
|
|
var ref = obj;
|
|
var prop;
|
|
for (var i = 0; i < parts.length - 1; i++) {
|
|
prop = parts[i];
|
|
ref[prop] = {};
|
|
ref = ref[prop];
|
|
}
|
|
|
|
prop = parts[parts.length - 1];
|
|
ref[prop] = value;
|
|
|
|
return obj;
|
|
},
|
|
|
|
newObject: function() {
|
|
return this.newPath(this.path, 1);
|
|
},
|
|
|
|
newObserver: function(obj) {
|
|
return new PathObserver(obj, this.path);
|
|
}
|
|
});
|
|
|
|
global.ObjectBenchmark = ObjectBenchmark;
|
|
global.SetupObjectBenchmark = SetupObjectBenchmark;
|
|
global.ArrayBenchmark = ArrayBenchmark;
|
|
global.SetupArrayBenchmark = SetupArrayBenchmark;
|
|
global.PathBenchmark = PathBenchmark;
|
|
global.SetupPathBenchmark = SetupPathBenchmark;
|
|
|
|
})(this);
|