Merge deleted items more efficiently.

Previously deleted items were simply added to transaction._mergeStructs. But this inherently inefficient as it will splice the struct store for every item.

Now Yjs iterates over transaction.ds and tries to merge structs. It iterates from right to left so merging should be more efficient that before. But more work needs to be done.

For example we could set structs[i] = null and filter the structs after merging is done.
This commit is contained in:
Kevin Jahns
2019-04-28 17:20:35 +02:00
parent c9dda245bf
commit 20005eecdb
3 changed files with 67 additions and 24 deletions

View File

@@ -423,6 +423,8 @@ export class AbstractItem extends AbstractStruct {
gcChildren (transaction, store) { }
/**
* @todo remove transaction param
*
* @param {Transaction} transaction
* @param {StructStore} store
* @param {boolean} parentGCd
@@ -430,7 +432,9 @@ export class AbstractItem extends AbstractStruct {
* @private
*/
gc (transaction, store, parentGCd) {
this.delete(transaction) // @todo: shouldn't be necessary
if (!this.deleted) {
throw error.unexpectedCase()
}
let r
if (parentGCd) {
r = new GC(this.id, this.length)
@@ -448,7 +452,6 @@ export class AbstractItem extends AbstractStruct {
}
}
replaceStruct(store, this, r)
transaction._mergeStructs.add(r.id)
}
/**
@@ -616,7 +619,7 @@ export const computeItemParams = (transaction, store, leftid, rightid, parentid,
case GC:
break
default:
if (!parentItem.deleted) {
if (!parentItem.deleted && (left === null || left.constructor !== GC) && (right === null || right.constructor !== GC)) {
parent = parentItem.type
}
}

View File

@@ -106,11 +106,22 @@ export class ItemType extends AbstractItem {
while (item !== null) {
if (!item.deleted) {
item.delete(transaction)
} else {
// Whis will be gc'd later and we want to merge it if possible
// We try to merge all deleted items after each transaction,
// but we have no knowledge about that this needs to be merged
// since it is not in transaction.ds. Hence we add it to transaction._mergeStructs
transaction._mergeStructs.add(item.id)
}
item = item.right
}
this.type._map.forEach(item => {
item.delete(transaction)
if (!item.deleted) {
item.delete(transaction)
} else {
// same as above
transaction._mergeStructs.add(item.id)
}
})
transaction.changed.delete(this.type)
transaction.changedParentTypes.delete(this.type)