gc more efficiently
This commit is contained in:
@@ -3,7 +3,7 @@ import {
|
||||
findIndexSS,
|
||||
createID,
|
||||
getState,
|
||||
AbstractItem, StructStore, Transaction, ID // eslint-disable-line
|
||||
AbstractStruct, AbstractItem, StructStore, Transaction, ID // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as math from 'lib0/math.js'
|
||||
@@ -11,9 +11,6 @@ import * as map from 'lib0/map.js'
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
import * as decoding from 'lib0/decoding.js'
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class DeleteItem {
|
||||
/**
|
||||
* @param {number} clock
|
||||
@@ -37,8 +34,6 @@ class DeleteItem {
|
||||
* - This DeleteSet is send to other clients
|
||||
* - We do not create a DeleteSet when we send a sync message. The DeleteSet message is created directly from StructStore
|
||||
* - We read a DeleteSet as part of a sync/update message. In this case the DeleteSet is already sorted and merged.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export class DeleteSet {
|
||||
constructor () {
|
||||
@@ -50,6 +45,33 @@ export class DeleteSet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all structs that were deleted.
|
||||
*
|
||||
* This function expects that the deletes structs are not deleted. Hence, you can
|
||||
* probably only use it in type observes and `afterTransaction` events. But not
|
||||
* in `afterTransactionCleanup`.
|
||||
*
|
||||
* @param {DeleteSet} ds
|
||||
* @param {StructStore} store
|
||||
* @param {function(AbstractStruct):void} f
|
||||
*
|
||||
* @function
|
||||
*/
|
||||
export const iterateDeletedStructs = (ds, store, f) =>
|
||||
ds.clients.forEach((deletes, clientid) => {
|
||||
const structs = /** @type {Array<AbstractStruct>} */ (store.clients.get(clientid))
|
||||
for (let i = 0; i < deletes.length; i++) {
|
||||
const del = deletes[i]
|
||||
let index = findIndexSS(structs, del.clock)
|
||||
let struct
|
||||
do {
|
||||
struct = structs[index++]
|
||||
f(struct)
|
||||
} while (index < structs.length && structs[index].id.clock < del.clock + del.len)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* @param {Array<DeleteItem>} dis
|
||||
* @param {number} clock
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
import {
|
||||
DeleteSet,
|
||||
isDeleted,
|
||||
AbstractItem // eslint-disable-line
|
||||
DeleteSet, AbstractItem // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
export class Snapshot {
|
||||
@@ -17,7 +16,7 @@ export class Snapshot {
|
||||
* @type {DeleteSet}
|
||||
* @private
|
||||
*/
|
||||
this.ds = new DeleteSet()
|
||||
this.ds = ds
|
||||
/**
|
||||
* State Map
|
||||
* @type {Map<number,number>}
|
||||
|
||||
@@ -181,9 +181,14 @@ export const transact = (y, f) => {
|
||||
if (deleteItem.clock + deleteItem.len <= struct.id.clock) {
|
||||
break
|
||||
}
|
||||
if (struct.deleted && struct instanceof AbstractItem && (struct.constructor !== ItemDeleted || (struct.parent._item !== null && struct.parent._item.deleted))) {
|
||||
// check if we can GC
|
||||
struct.gc(transaction, store)
|
||||
if (struct.deleted && struct instanceof AbstractItem) {
|
||||
if (struct.constructor !== ItemDeleted || (struct.parent._item !== null && struct.parent._item.deleted)) {
|
||||
// check if we can GC
|
||||
struct.gc(transaction, store)
|
||||
} else {
|
||||
// otherwise only gc children (if there are any)
|
||||
struct.gcChildren(transaction, store)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getState,
|
||||
findRootTypeKey,
|
||||
AbstractItem,
|
||||
ItemType,
|
||||
ID, StructStore, Y, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -240,7 +241,13 @@ export const createAbsolutePositionFromCursor = (cursor, y) => {
|
||||
if (tname !== null) {
|
||||
type = y.get(tname)
|
||||
} else if (typeID !== null) {
|
||||
type = getItemType(store, typeID).type
|
||||
const struct = getItemType(store, typeID)
|
||||
if (struct instanceof ItemType) {
|
||||
type = struct.type
|
||||
} else {
|
||||
// struct is garbage collected
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
throw error.unexpectedCase()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user