observer benchmarks and tests

This commit is contained in:
Evan You 2014-07-11 01:59:40 -04:00
parent 8bcc3834a9
commit b9f2c1ac39
2 changed files with 366 additions and 16 deletions

306
benchmarks/observer.js Normal file
View File

@ -0,0 +1,306 @@
var Observer = require('../src/observer/observer')
var Emitter = require('../src/emitter')
var OldObserver = require('../../vue/src/observer')
var sideEffect = 0
var runs = 1000
function cb () {
sideEffect++
}
var loadTime = getNano()
function getNano () {
var hr = process.hrtime()
return hr[0] * 1e9 + hr[1]
}
function now () {
return (getNano() - loadTime) / 1e6
}
function bench (desc, fac, run) {
var objs = []
for (var i = 0; i < runs; i++) {
objs.push(fac(i))
}
var s = now()
for (var i = 0; i < runs; i++) {
run(objs[i])
}
var passed = now() - s
console.log(desc + ' - ' + (16 / (passed / runs)).toFixed(2) + ' ops/frame')
}
bench(
'observe (simple object) ',
function (i) {
return {a:i}
},
function (o) {
new Observer().observe('', o)
}
)
bench(
'old observe (simple object) ',
function (i) {
return {a:i}
},
function (o) {
OldObserver.observe(o, '', new Emitter())
}
)
bench(
'observe (3 nested objects) ',
function (i) {
return {a:{b:{c:i}}}
},
function (o) {
new Observer().observe('', o)
}
)
bench(
'old observe (3 nested objects) ',
function (i) {
return {a:{b:{c:i}}}
},
function (o) {
OldObserver.observe(o, '', new Emitter())
}
)
bench(
'observe (array, 3 objects) ',
function (i) {
return [{a:i}, {a:i+1}, {a:i+2}]
},
function (o) {
new Observer().observe('', o)
}
)
bench(
'old observe (array, 3 objects) ',
function (i) {
return [{a:i}, {a:i+1}, {a:i+2}]
},
function (o) {
OldObserver.observe(o, '', new Emitter())
}
)
bench(
'observe (array, 30 objects) ',
function () {
var a = [], i = 30
while (i--) {
a.push({a:i})
}
return a
},
function (o) {
new Observer().observe('', o)
}
)
bench(
'old observe (array, 30 objects)',
function () {
var a = [], i = 30
while (i--) {
a.push({a:i})
}
return a
},
function (o) {
OldObserver.observe(o, '', new Emitter())
}
)
Observer.emitGet = true
OldObserver.shouldGet = true
bench(
'simple get ',
function () {
var a = {a:1}
var ob = new Observer()
ob.observe('', a)
ob.on('get', cb)
return a
},
function (o) {
var v = o.a
}
)
bench(
'old simple get',
function () {
var a = {a:1}
var ob = new Emitter()
OldObserver.observe(a, '', ob)
ob.on('get', cb)
return a
},
function (o) {
var v = o.a
}
)
bench(
'nested get ',
function () {
var a = {a:{b:{c:1}}}
var ob = new Observer()
ob.observe('', a)
ob.on('get', cb)
return a
},
function (o) {
var v = o.a.b.c
}
)
bench(
'old nested get',
function () {
var a = {a:{b:{c:1}}}
var ob = new Emitter()
OldObserver.observe(a, '', ob)
ob.on('get', cb)
return a
},
function (o) {
var v = o.a.b.c
}
)
Observer.emitGet = false
OldObserver.shouldGet = false
bench(
'simple set ',
function () {
var a = {a:1}
var ob = new Observer()
ob.observe('', a)
ob.on('set', cb)
return a
},
function (o) {
o.a = 12345
}
)
bench(
'old simple set',
function () {
var a = {a:1}
var ob = new Emitter()
OldObserver.observe(a, '', ob)
ob.on('set', cb)
return a
},
function (o) {
o.a = 12345
}
)
bench(
'nested set ',
function () {
var a = {a:{b:{c:1}}}
var ob = new Observer()
ob.observe('', a)
ob.on('set', cb)
return a
},
function (o) {
o.a.b.c = 2
}
)
bench(
'old nested set',
function () {
var a = {a:{b:{c:1}}}
var ob = new Emitter()
OldObserver.observe(a, '', ob)
ob.on('set', cb)
return a
},
function (o) {
o.a.b.c = 2
}
)
bench(
'array mutation (5 objects) ',
function () {
var a = [], i = 5
while (i--) {
a.push({a:i})
}
var ob = new Observer()
ob.observe('', a)
ob.on('mutation', cb)
return a
},
function (o) {
o.reverse()
}
)
bench(
'old array mutation (5 objects) ',
function () {
var a = [], i = 5
while (i--) {
a.push({a:i})
}
var ob = new Emitter()
OldObserver.observe(a, '', ob)
ob.on('mutation', cb)
return a
},
function (o) {
o.reverse()
}
)
bench(
'array mutation (50 objects) ',
function () {
var a = [], i = 50
while (i--) {
a.push({a:i})
}
var ob = new Observer()
ob.observe('', a)
ob.on('mutation', cb)
return a
},
function (o) {
o.reverse()
}
)
bench(
'old array mutation (50 objects)',
function () {
var a = [], i = 50
while (i--) {
a.push({a:i})
}
var ob = new Emitter()
OldObserver.observe(a, '', ob)
ob.on('mutation', cb)
return a
},
function (o) {
o.reverse()
}
)

View File

@ -1,18 +1,18 @@
var Observer = require('../../src/observer/observer')
var delimiter = Observer.pathDelimiter
function path (p) {
return p.replace(/\./g, '\b')
}
var u = undefined
Observer.pathDelimiter = '.'
describe('Observer', function () {
var spy
beforeEach(function () {
spy = jasmine.createSpy()
spy = jasmine.createSpy('observer')
})
it('get', function () {
Observer.emitGet = true
var obj = {
a: 1,
b: {
@ -23,13 +23,15 @@ describe('Observer', function () {
ob.on('get', spy)
var t = obj.a
expect(spy).toHaveBeenCalledWith('a', undefined, undefined)
expect(spy).toHaveBeenCalledWith('a', u, u)
expect(spy.callCount).toEqual(1)
t = obj.b.c
expect(spy).toHaveBeenCalledWith('b', undefined, undefined)
expect(spy).toHaveBeenCalledWith(path('b.c'), undefined, undefined)
expect(spy).toHaveBeenCalledWith('b', u, u)
expect(spy).toHaveBeenCalledWith('b.c', u, u)
expect(spy.callCount).toEqual(3)
Observer.emitGet = false
})
it('set', function () {
@ -43,20 +45,27 @@ describe('Observer', function () {
ob.on('set', spy)
obj.a = 3
expect(spy).toHaveBeenCalledWith('a', 3, undefined)
expect(spy).toHaveBeenCalledWith('a', 3, u)
expect(spy.callCount).toEqual(1)
obj.b.c = 4
expect(spy).toHaveBeenCalledWith(path('b.c'), 4, undefined)
expect(spy).toHaveBeenCalledWith('b.c', 4, u)
expect(spy.callCount).toEqual(2)
var newB = { c: 5 }
obj.b = newB
expect(spy).toHaveBeenCalledWith('b', newB, undefined)
expect(spy).toHaveBeenCalledWith('b', newB, u)
expect(spy.callCount).toEqual(3)
// same value set should not emit events
obj.a = 3
expect(spy.callCount).toEqual(3)
})
it('array get', function () {
Observer.emitGet = true
var obj = {
arr: [{a:1}, {a:2}]
}
@ -64,17 +73,52 @@ describe('Observer', function () {
ob.on('get', spy)
var t = obj.arr[0].a
expect(spy).toHaveBeenCalledWith(path('arr'), undefined, undefined)
expect(spy).toHaveBeenCalledWith(path('arr.0.a'), undefined, undefined)
expect(spy).toHaveBeenCalledWith('arr', u, u)
expect(spy).toHaveBeenCalledWith('arr.0.a', u, u)
expect(spy.callCount).toEqual(2)
Observer.emitGet = false
})
it('array set', function () {
// body...
var obj = {
arr: [{a:1}, {a:2}]
}
var ob = Observer.create(obj)
ob.on('set', spy)
obj.arr[0].a = 2
expect(spy).toHaveBeenCalledWith('arr.0.a', 2, u)
// set events after mutation
obj.arr.reverse()
obj.arr[0].a = 3
expect(spy).toHaveBeenCalledWith('arr.0.a', 3, u)
})
it('array mutate', function () {
// body...
var arr = [{a:1}, {a:2}]
var ob = Observer.create(arr)
ob.on('mutate', spy)
arr.push({a:3})
expect(spy.mostRecentCall.args[0]).toEqual('')
expect(spy.mostRecentCall.args[1]).toEqual(arr)
var mutation = spy.mostRecentCall.args[2]
expect(mutation).toBeDefined()
expect(mutation.method).toEqual('push')
expect(mutation.index).toEqual(2)
expect(mutation.inserted.length).toEqual(1)
expect(mutation.inserted[0]).toEqual(arr[2])
})
it('array set after mutate', function () {
var arr = [{a:1}, {a:2}]
var ob = Observer.create(arr)
ob.on('set', spy)
arr.push({a:3})
arr[2].a = 4
expect(spy).toHaveBeenCalledWith('2.a', 4, u)
})
it('object.$add', function () {