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) {
|
||||
o = Y.utils.copyObject(o)
|
||||
delete o.origin
|
||||
delete o.originOf
|
||||
db1.push(o)
|
||||
})
|
||||
})
|
||||
@ -222,6 +223,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
||||
yield* this.os.iterate(this, null, null, function * (o) {
|
||||
o = Y.utils.copyObject(o)
|
||||
delete o.origin
|
||||
delete o.originOf
|
||||
expect(db1[count++]).toEqual(o)
|
||||
})
|
||||
})
|
||||
|
@ -126,6 +126,19 @@ module.exports = function (Y/* :any */) {
|
||||
execute: function *(op) {
|
||||
var i // loop counter
|
||||
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 parent
|
||||
var start
|
||||
|
@ -362,23 +362,31 @@ module.exports = function (Y/* :any */) {
|
||||
if (o.right != null) {
|
||||
var right = yield* this.getOperation(o.right)
|
||||
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
|
||||
// origin is the first left deleted operation
|
||||
var neworigin = o.left
|
||||
var neworigin_ = null
|
||||
while (neworigin != null) {
|
||||
var neworigin_ = yield* this.getOperation(neworigin)
|
||||
neworigin_ = yield* this.getOperation(neworigin)
|
||||
if (neworigin_.deleted) {
|
||||
break
|
||||
}
|
||||
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
|
||||
right.origin = neworigin
|
||||
|
||||
// reset origin of all right ops (except first right - duh!),
|
||||
// until you find origin pointer to the left of o
|
||||
// search until you find origin pointer to the left of o
|
||||
if (right.right != null) {
|
||||
var i = yield* this.getOperation(right.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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user