Implemented more efficient garbage collectior
from worst case of O(n) -> O(1) - where n is the number of insertions in a list So this is a huge improvement, I guess :)
This commit is contained in:
parent
38bf398709
commit
39dc2317b7
@ -208,6 +208,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
|||||||
yield* this.os.iterate(this, null, null, function * (o) {
|
yield* this.os.iterate(this, null, null, function * (o) {
|
||||||
o = Y.utils.copyObject(o)
|
o = Y.utils.copyObject(o)
|
||||||
delete o.origin
|
delete o.origin
|
||||||
|
delete o.originOf
|
||||||
db1.push(o)
|
db1.push(o)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -222,6 +223,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
|||||||
yield* this.os.iterate(this, null, null, function * (o) {
|
yield* this.os.iterate(this, null, null, function * (o) {
|
||||||
o = Y.utils.copyObject(o)
|
o = Y.utils.copyObject(o)
|
||||||
delete o.origin
|
delete o.origin
|
||||||
|
delete o.originOf
|
||||||
expect(db1[count++]).toEqual(o)
|
expect(db1[count++]).toEqual(o)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -126,6 +126,19 @@ module.exports = function (Y/* :any */) {
|
|||||||
execute: function *(op) {
|
execute: function *(op) {
|
||||||
var i // loop counter
|
var i // loop counter
|
||||||
var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
|
var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
|
||||||
|
|
||||||
|
if (op.origin != null) {
|
||||||
|
// we save in origin that op originates in it
|
||||||
|
// we need that later when we eventually garbage collect origin (see transaction)
|
||||||
|
var origin = yield* this.getOperation(op.origin)
|
||||||
|
if (origin.originOf == null) {
|
||||||
|
origin.originOf = []
|
||||||
|
}
|
||||||
|
origin.originOf.push(op.id)
|
||||||
|
yield* this.setOperation(origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we begin to insert op in the list of insertions..
|
||||||
var o
|
var o
|
||||||
var parent
|
var parent
|
||||||
var start
|
var start
|
||||||
|
@ -362,23 +362,31 @@ module.exports = function (Y/* :any */) {
|
|||||||
if (o.right != null) {
|
if (o.right != null) {
|
||||||
var right = yield* this.getOperation(o.right)
|
var right = yield* this.getOperation(o.right)
|
||||||
right.left = o.left
|
right.left = o.left
|
||||||
if (Y.utils.compareIds(right.origin, o.id)) { // rights origin is o
|
|
||||||
|
if (Y.utils.compareIds(right.origin, id)) { // rights origin is o
|
||||||
// find new origin of right ops
|
// find new origin of right ops
|
||||||
// origin is the first left deleted operation
|
// origin is the first left deleted operation
|
||||||
var neworigin = o.left
|
var neworigin = o.left
|
||||||
|
var neworigin_ = null
|
||||||
while (neworigin != null) {
|
while (neworigin != null) {
|
||||||
var neworigin_ = yield* this.getOperation(neworigin)
|
neworigin_ = yield* this.getOperation(neworigin)
|
||||||
if (neworigin_.deleted) {
|
if (neworigin_.deleted) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
neworigin = neworigin_.left
|
neworigin = neworigin_.left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset origin of all right ops (except first right - duh!),
|
||||||
|
|
||||||
|
/* ** The following code does not rely on the the originOf property **
|
||||||
|
I recently added originOf to all Insert Operations (see Struct.Insert.execute),
|
||||||
|
which saves which operations originate in a Insert operation.
|
||||||
|
Garbage collecting without originOf is more memory efficient, but is nearly impossible for large texts, or lists!
|
||||||
|
But I keep this code for now
|
||||||
|
```
|
||||||
// reset origin of right
|
// reset origin of right
|
||||||
right.origin = neworigin
|
right.origin = neworigin
|
||||||
|
// search until you find origin pointer to the left of o
|
||||||
// reset origin of all right ops (except first right - duh!),
|
|
||||||
// until you find origin pointer to the left of o
|
|
||||||
if (right.right != null) {
|
if (right.right != null) {
|
||||||
var i = yield* this.getOperation(right.right)
|
var i = yield* this.getOperation(right.right)
|
||||||
var ids = [o.id, o.right]
|
var ids = [o.id, o.right]
|
||||||
@ -399,9 +407,41 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* otherwise, rights origin is to the left of o,
|
```
|
||||||
then there is no right op (from o), that origins in o */
|
*/
|
||||||
yield* this.setOperation(right)
|
// ** Now the new implementation starts **
|
||||||
|
// reset neworigin of all originOf[*]
|
||||||
|
for (var _i in o.originOf) {
|
||||||
|
var originsIn = yield* this.getOperation(o.originOf[_i])
|
||||||
|
if (originsIn != null) {
|
||||||
|
originsIn.origin = neworigin
|
||||||
|
yield* this.setOperation(originsIn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (neworigin != null) {
|
||||||
|
if (neworigin_.originOf == null) {
|
||||||
|
neworigin_.originOf = o.originOf
|
||||||
|
} else {
|
||||||
|
neworigin_.originOf = o.originOf.concat(neworigin_.originOf)
|
||||||
|
}
|
||||||
|
yield* this.setOperation(neworigin_)
|
||||||
|
}
|
||||||
|
// we don't need to set right here, because
|
||||||
|
// right should be in o.originOf => it is set it the previous for loop
|
||||||
|
} else {
|
||||||
|
// we didn't need to reset the origin of right
|
||||||
|
// so we have to set right here
|
||||||
|
yield* this.setOperation(right)
|
||||||
|
}
|
||||||
|
// o may originate in another operation.
|
||||||
|
// Since o is deleted, we have to reset o.origin's `originOf` property
|
||||||
|
if (o.origin != null) {
|
||||||
|
var origin = yield* this.getOperation(o.origin)
|
||||||
|
origin.originOf = origin.originOf.filter(function (_id) {
|
||||||
|
return !Y.utils.compareIds(id, _id)
|
||||||
|
})
|
||||||
|
yield* this.setOperation(origin)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.parent != null) {
|
if (o.parent != null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user