Last active
June 26, 2016 13:34
-
-
Save niieani/4cae4eb22b9cb34b8e6b2d55d8a6bb52 to your computer and use it in GitHub Desktop.
Benchmark Descriptor Getting/Setting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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 }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* todo: add styles */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment