فهرست منبع

observer benchmarks and tests

Evan You 12 سال پیش
والد
کامیت
b9f2c1ac39
2فایلهای تغییر یافته به همراه366 افزوده شده و 16 حذف شده
  1. 306 0
      benchmarks/observer.js
  2. 60 16
      test/unit/observer.js

+ 306 - 0
benchmarks/observer.js

@@ -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()
+  }
+)

+ 60 - 16
test/unit/observer.js

@@ -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 () {