Skip to content

Instantly share code, notes, and snippets.

@niieani
Last active June 26, 2016 13:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niieani/4cae4eb22b9cb34b8e6b2d55d8a6bb52 to your computer and use it in GitHub Desktop.
Save niieani/4cae4eb22b9cb34b8e6b2d55d8a6bb52 to your computer and use it in GitHub Desktop.
Benchmark Descriptor Getting/Setting
<html>
<head>
<script src="https://wzrd.in/bundle/lodash@4.11"></script>
<script src="https://wzrd.in/bundle/platform@1.3"></script>
<script src="https://wzrd.in/bundle/benchmark@2.1"></script>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
"use strict";
var Benchmark = require('benchmark');
var suiteGet = new Benchmark.Suite;
var suiteSet = new Benchmark.Suite;
// polyfill
!function(Object, getPropertyDescriptor, getPropertyNames){
// (C) WebReflection - Mit Style License
if (!(getPropertyDescriptor in Object)) {
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
Object[getPropertyDescriptor] = function getPropertyDescriptor(o, name) {
var proto = o, descriptor;
while (proto && !(
descriptor = getOwnPropertyDescriptor(proto, name))
) proto = proto.__proto__;
return descriptor;
};
}
if (!(getPropertyNames in Object)) {
var getOwnPropertyNames = Object.getOwnPropertyNames, ObjectProto = Object.prototype, keys = Object.keys;
Object[getPropertyNames] = function getPropertyNames(o) {
var proto = o, unique = {}, names, i;
while (proto != ObjectProto) {
for (names = getOwnPropertyNames(proto), i = 0; i < names.length; i++) {
unique[names[i]] = true;
}
proto = proto.__proto__;
}
return keys(unique);
};
}
}(Object, "getPropertyDescriptor", "getPropertyNames");
///
const obj = {};
let val = 'a';
let key = 'test';
const setterCache = {};
const getterCache = {};
const setterCacheMap = new Map();
const getterCacheMap = new Map();
const proxyKeyCache = new Map();
function getA() {
return val;
}
getA.bindingGetter = function() {
return val;
}
function setA(value) {
val = value;
}
setA.bindingSetter = function(value) {
val = value;
}
Object.defineProperty(obj, key, {
get: getA,
set: setA,
enumerable: true
})
const bindingProxyPrefix = '__bindingProxy_';
const objAlt = {};
Object.defineProperty(objAlt, bindingProxyPrefix + key, {
get: getA,
set: setA,
enumerable: true
})
suiteSet
.add('Traditional set', function() {
obj[key] = 'b';
})
.add('BindingSetter no cache', function() {
let descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor && descriptor.set && descriptor.set.bindingSetter) {
descriptor.set.bindingSetter('b');
}
})
.add('BindingSetter with cache', function() {
let cache = setterCache[obj] = setterCache[obj] || {};
if (cache[key]) {
return cache[key]('b');
}
let descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor && descriptor.set && descriptor.set.bindingSetter) {
cache[key] = descriptor.set.bindingSetter;
descriptor.set.bindingSetter('b');
}
})
// add listeners
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest setting method is ' + this.filter('fastest').map('name'));
});
// add tests
suiteGet
.add('Traditional get', function() {
return obj[key];
})
.add('BindingProxy property', function() {
let proxyKey = bindingProxyPrefix + key;
return proxyKey in obj ? obj[proxyKey] : obj[key];
})
.add('BindingProxy property (cached string)', function() {
let proxyKey;
if (!(proxyKey = proxyKeyCache.get(key))) {
proxyKeyCache.set(key, bindingProxyPrefix + key);
}
return proxyKey in obj ? obj[proxyKey] : obj[key];
})
.add('BindingGetter (own)', function() {
let descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor && descriptor.get && descriptor.get.bindingGetter) {
return descriptor.get.bindingGetter();
}
})
.add('BindingGetter (all)', function() {
let descriptor = Object.getPropertyDescriptor(obj, key);
if (descriptor && descriptor.get && descriptor.get.bindingGetter) {
return descriptor.get.bindingGetter();
}
})
.add('BindingGetter with cache (Map) (own)', function() {
let getter;
let cache = getterCacheMap.get(obj);
if (cache === null) {
return obj[key];
} else if (!cache) {
cache = new Map();
getterCacheMap.set(obj, cache);
}
if (getter = cache.get(key)) {
return getter();
}
let descriptor = Object.getPropertyDescriptor(obj, key);
if (descriptor && descriptor.get && (getter = descriptor.get.bindingGetter)) {
cache.set(key, getter);
return getter();
}
cache.set(key, null);
})
.add('BindingGetter with cache (Map) (all)', function() {
let getter;
let cache = getterCacheMap.get(obj);
if (cache === null) {
return obj[key];
} else if (!cache) {
cache = new Map();
getterCacheMap.set(obj, cache);
}
if (getter = cache.get(key)) {
return getter();
}
let descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor && descriptor.get && (getter = descriptor.get.bindingGetter)) {
cache.set(key, getter);
return getter();
}
cache.set(key, null);
})
.add('BindingGetter with cache (Object) (own)', function() {
let getter;
let cache = getterCache[obj] = getterCache[obj] || {};
if (getter = cache[key]) {
return getter();
} else if (getter === null) {
return obj[key];
}
let descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor && descriptor.get && (getter = descriptor.get.bindingGetter)) {
cache[key] = getter;
return getter();
}
cache[key] = null;
})
.add('BindingGetter with cache (Object) (all)', function() {
let getter;
let cache = getterCache[obj] = getterCache[obj] || {};
if (getter = cache[key]) {
return getter();
} else if (getter === null) {
return obj[key];
}
let descriptor = Object.getPropertyDescriptor(obj, key);
if (descriptor && descriptor.get && (getter = descriptor.get.bindingGetter)) {
cache[key] = getter;
return getter();
}
cache[key] = null;
})
// add listeners
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest getting method is ' + this.filter('fastest').map('name'));
// suiteSet.run({ 'async': true });
})
.run({ 'async': true });
/* todo: add styles */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment