From 0c1f68267962061d79823eea4a58c5cbfa90d8c8 Mon Sep 17 00:00:00 2001 From: DR-Univer Date: Thu, 31 Oct 2024 02:19:35 +0800 Subject: [PATCH] perf(formula): remove dependency for finished cal --- .../src/engine/dependency/dependency-tree.ts | 68 +++-- .../engine/dependency/formula-dependency.ts | 113 ++++---- .../src/services/calculate-formula.service.ts | 2 + .../services/dependency-manager.service.ts | 241 ++++++++---------- 4 files changed, 222 insertions(+), 202 deletions(-) diff --git a/packages/engine-formula/src/engine/dependency/dependency-tree.ts b/packages/engine-formula/src/engine/dependency/dependency-tree.ts index 6160082101f..2d76856fb81 100644 --- a/packages/engine-formula/src/engine/dependency/dependency-tree.ts +++ b/packages/engine-formula/src/engine/dependency/dependency-tree.ts @@ -69,45 +69,78 @@ class FormulaDependencyTreeCalculator { } } +type GetDirtyDataType = Nullable< + (dirtyData: IFormulaDirtyData, runtimeData: IAllRuntimeData) => { + runtimeCellData: IRuntimeUnitDataType; + dirtyRanges: IFeatureDirtyRangeType; + } +>; export type IFormulaDependencyTree = FormulaDependencyTree | FormulaDependencyTreeVirtual; export class FormulaDependencyTreeVirtual extends FormulaDependencyTreeCalculator { treeId: number; - refTree: FormulaDependencyTree; + refTree: Nullable; refOffsetX: number = 0; refOffsetY: number = 0; isCache: boolean = false; + node: Nullable; + get isVirtual() { return true; } get row() { + if (this.refTree == null) { + return -1; + } return this.refTree.row + this.refOffsetY; } get column() { + if (this.refTree == null) { + return -1; + } return this.refTree.column + this.refOffsetX; } get rowCount() { + if (this.refTree == null) { + return 0; + } return this.refTree.rowCount; } get columnCount() { + if (this.refTree == null) { + return 0; + } return this.refTree.columnCount; } get unitId() { + if (this.refTree == null) { + return ''; + } return this.refTree.unitId; } get subUnitId() { + if (this.refTree == null) { + return ''; + } return this.refTree.subUnitId; } + dispose() { + this.refTree = null; + } + get rangeList() { const unitRangeList = []; + if (this.refTree == null) { + return []; + } for (let i = 0; i < this.refTree.rangeList.length; i++) { const range = this.refTree.rangeList[i]; unitRangeList.push({ @@ -120,6 +153,13 @@ export class FormulaDependencyTreeVirtual extends FormulaDependencyTreeCalculato } get nodeData() { + if (this.refTree == null) { + return { + node: null, + refOffsetX: -1, + refOffsetY: -1, + }; + } return { node: this.refTree.node, refOffsetX: this.refOffsetX, @@ -160,6 +200,9 @@ export class FormulaDependencyTreeVirtual extends FormulaDependencyTreeCalculato } dependencySheetName(dirtyUnitSheetNameMap?: IDirtyUnitSheetNameMap) { + if (this.refTree == null) { + return false; + } return this.refTree.dependencySheetName(dirtyUnitSheetNameMap); } @@ -206,15 +249,13 @@ export class FormulaDependencyTreeVirtual extends FormulaDependencyTreeCalculato return false; } - getDirtyData: Nullable< - (dirtyData: IFormulaDirtyData, runtimeData: IAllRuntimeData) => { - runtimeCellData: IRuntimeUnitDataType; - dirtyRanges: IFeatureDirtyRangeType; - } - >; + getDirtyData: GetDirtyDataType; featureId: Nullable; get formulaId() { + if (this.refTree == null) { + return ''; + } return this.refTree.formulaId; } } @@ -226,11 +267,11 @@ export class FormulaDependencyTreeVirtual extends FormulaDependencyTreeCalculato export class FormulaDependencyTree extends FormulaDependencyTreeCalculator { treeId: number = -1; + isCache: boolean = false; + featureId: Nullable; featureDirtyRanges: IUnitRange[] = []; - isCache: boolean = false; - refOffsetX: number = 0; refOffsetY: number = 0; @@ -280,12 +321,7 @@ export class FormulaDependencyTree extends FormulaDependencyTreeCalculator { }; } - getDirtyData: Nullable< - (dirtyData: IFormulaDirtyData, runtimeData: IAllRuntimeData) => { - runtimeCellData: IRuntimeUnitDataType; - dirtyRanges: IFeatureDirtyRangeType; - } - >; + getDirtyData: GetDirtyDataType; dispose(): void { this.featureDirtyRanges = []; @@ -295,6 +331,8 @@ export class FormulaDependencyTree extends FormulaDependencyTreeCalculator { // this.nodeData?.node.dispose(); this.node = null; + + this.getDirtyData = null; } inRangeData(range: IRange) { diff --git a/packages/engine-formula/src/engine/dependency/formula-dependency.ts b/packages/engine-formula/src/engine/dependency/formula-dependency.ts index e94781818be..82e7c0f7416 100644 --- a/packages/engine-formula/src/engine/dependency/formula-dependency.ts +++ b/packages/engine-formula/src/engine/dependency/formula-dependency.ts @@ -60,6 +60,7 @@ function generateRandomDependencyTreeId(dependencyManagerService: IDependencyMan export class FormulaDependencyGenerator extends Disposable { private _formulaASTCache = new FormulaAstLRU(FORMULA_CACHE_LRU_COUNT); private _updateRangeFlattenCache = new Map>(); + private _dependencyTreeCache = new Map(); constructor( @IFormulaCurrentConfigService private readonly _currentConfigService: IFormulaCurrentConfigService, @@ -122,6 +123,8 @@ export class FormulaDependencyGenerator extends Disposable { this._runtimeService.enableCycleDependency(); } + this._dependencyTreeCache.clear(); + this._dependencyManagerService.closeKdTree(); return Promise.resolve(finalTreeList); @@ -139,7 +142,7 @@ export class FormulaDependencyGenerator extends Disposable { if (color === WHITE) { colorMap.set(currentTreeId, GRAY); - const node = this._dependencyManagerService.getTreeById(currentTreeId); + const node = this._dependencyTreeCache.get(currentTreeId); if (node == null) { colorMap.set(currentTreeId, BLACK); stack.pop(); @@ -230,10 +233,10 @@ export class FormulaDependencyGenerator extends Disposable { for (let i = 0, len = treeList.length; i < len; i++) { const tree = treeList[i]; - - if (!tree.isCache) { - this._dependencyManagerService.addDependencyRTreeCache(tree); + if (tree.isCache) { + continue; } + this._dependencyManagerService.addDependencyRTreeCache(tree); } return treeList; @@ -264,21 +267,17 @@ export class FormulaDependencyGenerator extends Disposable { featureMap.forEach((subUnitMap, _) => { subUnitMap.forEach((featureMap, _) => { featureMap.forEach((params, featureId) => { - const treeCache = this._dependencyManagerService.getFeatureFormulaDependency(params.unitId, params.subUnitId, featureId); - if (treeCache) { - treeCache.isCache = true; - return; - } - treeList.push(this._getFeatureFormulaTree(featureId, params)); + const treeId = this._dependencyManagerService.getFeatureFormulaDependency(params.unitId, params.subUnitId, featureId); + treeList.push(this._getFeatureFormulaTree(featureId, treeId, params)); }); }); }); } - private _getFeatureFormulaTree(featureId: string, params: IFeatureCalculationManagerParam) { + private _getFeatureFormulaTree(featureId: string, treeId: Nullable, params: IFeatureCalculationManagerParam) { const { unitId, subUnitId, dependencyRanges, getDirtyData } = params; - - const FDtree = new FormulaDependencyTree(generateRandomDependencyTreeId(this._dependencyManagerService)); + const treeIdNum = treeId || generateRandomDependencyTreeId(this._dependencyManagerService); + const FDtree = new FormulaDependencyTree(treeIdNum); // FDtree.unitId = unitId; // FDtree.subUnitId = subUnitId; @@ -301,6 +300,13 @@ export class FormulaDependencyGenerator extends Disposable { this._dependencyManagerService.addFeatureFormulaDependency(unitId, subUnitId, featureId, FDtree); + this._dependencyTreeCache.set(FDtree.treeId, FDtree); + + const treeCache = this._dependencyManagerService.getFeatureFormulaDependency(params.unitId, params.subUnitId, featureId); + if (treeCache) { + FDtree.isCache = true; + } + return FDtree; } @@ -313,38 +319,27 @@ export class FormulaDependencyGenerator extends Disposable { if (subComponentData == null) { continue; } - const subComponentKeys = Object.keys(subComponentData); for (const subUnitId of subComponentKeys) { const subFormulaData = subComponentData[subUnitId]; - if (subFormulaData == null) { continue; } - const subFormulaDataKeys = Object.keys(subFormulaData); for (const subFormulaDataId of subFormulaDataKeys) { const hasOtherFormula = this._dependencyManagerService.hasOtherFormulaDataMainData(subFormulaDataId); const formulaDataItem = subFormulaData[subFormulaDataId]; const { f: formulaString, ranges } = formulaDataItem; - + let isCache = false; if (hasOtherFormula) { - const treeSet = this._dependencyManagerService.getOtherFormulaDependency(unitId, subUnitId, subFormulaDataId); - if (treeSet) { - for (const treeId of treeSet) { - const tree = this._dependencyManagerService.getTreeById(treeId); - if (tree) { - tree.isCache = true; - } - } - continue; - } + isCache = true; } - const node = this._generateAstNode(unitId, formulaString); const { firstRow, firstColumn } = this._getFirstCellOfRange(ranges); - const firstFDtree = new FormulaDependencyTree(generateRandomDependencyTreeId(this._dependencyManagerService)); + const treeMatrix = this._dependencyManagerService.getOtherFormulaDependency(unitId, subUnitId, subFormulaDataId); + const firstTreeId = treeMatrix?.getValue(0, 0) || generateRandomDependencyTreeId(this._dependencyManagerService); + const firstFDtree = new FormulaDependencyTree(firstTreeId); for (let i = 0; i < ranges.length; i++) { const range = ranges[i]; @@ -361,18 +356,23 @@ export class FormulaDependencyGenerator extends Disposable { firstFDtree.subUnitId = subUnitId; firstFDtree.formulaId = subFormulaDataId; firstFDtree.type = FormulaDependencyTreeType.OTHER_FORMULA; + firstFDtree.isCache = isCache; treeList.push(firstFDtree); + this._dependencyTreeCache.set(firstFDtree.treeId, firstFDtree); this._dependencyManagerService.addOtherFormulaDependency(unitId, subUnitId, subFormulaDataId, firstFDtree); continue; } const virtual = new FormulaDependencyTreeVirtual(); - virtual.treeId = generateRandomDependencyTreeId(this._dependencyManagerService); + virtual.treeId = treeMatrix?.getValue(x, y) || generateRandomDependencyTreeId(this._dependencyManagerService); + virtual.refTree = firstFDtree; virtual.refOffsetX = x; virtual.refOffsetY = y; + virtual.isCache = isCache; this._dependencyManagerService.addOtherFormulaDependency(unitId, subUnitId, subFormulaDataId, virtual); treeList.push(virtual); + this._dependencyTreeCache.set(virtual.treeId, virtual); } } } @@ -416,17 +416,20 @@ export class FormulaDependencyGenerator extends Disposable { return true; } - const treeCache = this._dependencyManagerService.getFormulaDependency(unitId, sheetId, row, column) as FormulaDependencyTree; - if (treeCache) { - sIdCache.set(si, treeCache); - treeCache.isCache = true; - return true; + const FDtree = this._createFDtree(unitId, sheetId, row, column, unitData, formulaDataItem); + + const treeId = this._dependencyManagerService.getFormulaDependency(unitId, sheetId, row, column); + if (treeId != null) { + FDtree.treeId = treeId; + } else { + this._dependencyManagerService.addFormulaDependency(unitId, sheetId, row, column, FDtree); } - const FDtree = this._createFDtree(unitId, sheetId, row, column, unitData, formulaDataItem); sIdCache.set(si, FDtree); this._dependencyManagerService.addFormulaDependency(unitId, sheetId, row, column, FDtree); treeList.push(FDtree); + + this._dependencyTreeCache.set(FDtree.treeId, FDtree); }); matrixData.forValue((row, column, formulaDataItem) => { @@ -441,12 +444,6 @@ export class FormulaDependencyGenerator extends Disposable { return true; } - const treeCache = this._dependencyManagerService.getFormulaDependency(unitId, sheetId, row, column); - if (treeCache) { - treeCache.isCache = true; - return true; - } - let FDtree: IFormulaDependencyTree; if (si && sIdCache.has(si)) { @@ -457,9 +454,16 @@ export class FormulaDependencyGenerator extends Disposable { FDtree = this._createFDtree(unitId, sheetId, row, column, unitData, formulaDataItem); } - this._dependencyManagerService.addFormulaDependency(unitId, sheetId, row, column, FDtree); + const treeId = this._dependencyManagerService.getFormulaDependency(unitId, sheetId, row, column); + if (treeId != null) { + FDtree.treeId = treeId; + } else { + this._dependencyManagerService.addFormulaDependency(unitId, sheetId, row, column, FDtree); + } treeList.push(FDtree); + + this._dependencyTreeCache.set(FDtree.treeId, FDtree); }); sIdCache.clear(); @@ -730,13 +734,13 @@ export class FormulaDependencyGenerator extends Disposable { const existTree = new Set(); const forceCalculate = this._currentConfigService.isForceCalculate(); - const allTree: IFormulaDependencyTree[] = this._dependencyManagerService.getAllTree(); + // const allTree: IFormulaDependencyTree[] = Array.from(this._dependencyTreeCache.values()); const dirtyRanges = this._currentConfigService.getDirtyRanges(); const treeIds = this._dependencyManagerService.searchDependency(dirtyRanges); // RTree Average case is O(logN + k) - for (let i = 0, len = allTree.length; i < len; i++) { - const tree = allTree[i]; + for (const [treeId, tree] of this._dependencyTreeCache) { + // const tree = allTree[i]; /** * forceCalculate: Mandatory calculation, adding all formulas to dependencies @@ -748,17 +752,25 @@ export class FormulaDependencyGenerator extends Disposable { forceCalculate || tree.dependencySheetName(this._currentConfigService.getDirtyNameMap()) || //O(n) n=tree.rangeList.length ( - treeIds.has(tree.treeId)// O(1) + treeIds.has(treeId)// O(1) && !tree.isExcludeRange(this._currentConfigService.getExcludedRange()) //worst O(n^2), best O(n) n^2=tree.rangeList.length*excludedRange.length, excludedRange.length is usually small ) || this._includeTree(tree) //O(n) n=tree.rangeList.length - ) && !existTree.has(tree.treeId) //O(1) + ) && !existTree.has(treeId) //O(1) ) { newTreeList.push(tree); - existTree.add(tree.treeId); + existTree.add(treeId); } } + for (const [treeId, tree] of this._dependencyTreeCache) { + if (tree.isVirtual) { + continue; + } + + (tree as FormulaDependencyTree).rangeList.length = 0; + } + return newTreeList; } @@ -1009,7 +1021,7 @@ export class FormulaDependencyGenerator extends Disposable { const searchResults = this._dependencyManagerService.searchDependency(tree.toRTreeItem()); for (const parentTreeId of searchResults) { - const parentTree = this._dependencyManagerService.getTreeById(parentTreeId); + const parentTree = this._dependencyTreeCache.get(parentTreeId); if (!parentTree) { throw new Error('ParentDependencyTree object is null'); } @@ -1037,6 +1049,7 @@ export class FormulaDependencyGenerator extends Disposable { for (const tree of this._traverse(treeList)) { formulaRunList.push(tree); } + return formulaRunList.reverse(); } } diff --git a/packages/engine-formula/src/services/calculate-formula.service.ts b/packages/engine-formula/src/services/calculate-formula.service.ts index 698490f633d..edf22b657c2 100644 --- a/packages/engine-formula/src/services/calculate-formula.service.ts +++ b/packages/engine-formula/src/services/calculate-formula.service.ts @@ -333,6 +333,8 @@ export class CalculateFormulaService extends Disposable { this._runtimeService.markedAsNoFunctionsExecuted(); } + treeList.length = 0; + return this._runtimeService.getAllRuntimeData(); } diff --git a/packages/engine-formula/src/services/dependency-manager.service.ts b/packages/engine-formula/src/services/dependency-manager.service.ts index b8d1cf91513..a1673090509 100644 --- a/packages/engine-formula/src/services/dependency-manager.service.ts +++ b/packages/engine-formula/src/services/dependency-manager.service.ts @@ -14,15 +14,13 @@ * limitations under the License. */ -import type { IRTreeItem, IUnitRange, Nullable } from '@univerjs/core'; -import type { FormulaDependencyTree, FormulaDependencyTreeVirtual, IFormulaDependencyTree } from '../engine/dependency/dependency-tree'; +import type { IRange, IRTreeItem, IUnitRange, Nullable } from '@univerjs/core'; +import type { FormulaDependencyTree, IFormulaDependencyTree } from '../engine/dependency/dependency-tree'; import { createIdentifier, Disposable, ObjectMatrix, RTree } from '@univerjs/core'; export interface IDependencyManagerService { dispose(): void; - getAllTree(): IFormulaDependencyTree[]; - reset(): void; addOtherFormulaDependency(unitId: string, sheetId: string, formulaId: string, dependencyTree: IFormulaDependencyTree): void; @@ -30,16 +28,16 @@ export interface IDependencyManagerService { removeOtherFormulaDependency(unitId: string, sheetId: string, formulaId: string[]): void; hasOtherFormulaDataMainData(formulaId: string): boolean; clearOtherFormulaDependency(unitId: string, sheetId?: string): void; - getOtherFormulaDependency(unitId: string, sheetId: string, formulaId: string): Nullable>; + getOtherFormulaDependency(unitId: string, sheetId: string, formulaId: string): Nullable>; addFeatureFormulaDependency(unitId: string, sheetId: string, featureId: string, dependencyTree: FormulaDependencyTree): void; removeFeatureFormulaDependency(unitId: string, sheetId: string, featureIds: string[]): void; - getFeatureFormulaDependency(unitId: string, sheetId: string, featureId: string): Nullable; + getFeatureFormulaDependency(unitId: string, sheetId: string, featureId: string): Nullable; clearFeatureFormulaDependency(unitId: string, sheetId?: string): void; addFormulaDependency(unitId: string, sheetId: string, row: number, column: number, dependencyTree: IFormulaDependencyTree): void; removeFormulaDependency(unitId: string, sheetId: string, row: number, column: number): void; - getFormulaDependency(unitId: string, sheetId: string, row: number, column: number): Nullable; + getFormulaDependency(unitId: string, sheetId: string, row: number, column: number): Nullable; clearFormulaDependency(unitId: string, sheetId?: string): void; removeFormulaDependencyByDefinedName(unitId: string, definedName: string): void; @@ -51,8 +49,6 @@ export interface IDependencyManagerService { openKdTree(): void; closeKdTree(): void; - getTreeById(treeId: number): Nullable; - } /** @@ -62,13 +58,15 @@ export interface IDependencyManagerService { * thereby completing the calculation of the entire dependency tree. */ export class DependencyManagerService extends Disposable implements IDependencyManagerService { - private _otherFormulaData: Map>>> = new Map(); // [unitId: string]: Nullable<{ [sheetId: string]: { [formulaId: string]: Set } }>; + private _otherFormulaData: Map>>> = new Map(); // [unitId: string]: Nullable<{ [sheetId: string]: { [formulaId: string]: Set } }>; private _featureFormulaData: Map>>> = new Map(); // [unitId: string]: Nullable<{ [sheetId: string]: { [featureId: string]: Nullable } }>; private _formulaData: Map>> = new Map(); // [unitId: string]: Nullable<{ [sheetId: string]: ObjectMatrix }>; - private _allTreeMap: Map = new Map(); + private _definedNameMap: Map>> = new Map(); // unitId -> definedName -> treeId + + private _allTreeMap: Map>> = new Map(); private _otherFormulaDataMainData: Set = new Set(); @@ -80,81 +78,6 @@ export class DependencyManagerService extends Disposable implements IDependencyM this.reset(); } - /** - * Get all FormulaDependencyTree from _otherFormulaData, _featureFormulaData, _formulaData - * return FormulaDependencyTree[] - */ - getAllTree() { - // const trees: FormulaDependencyTree[] = []; - - // const resetAndPush = (item: FormulaDependencyTree) => { - // if (item) { - // item.resetState(); - // trees.push(item); - // } - // }; - - // // _otherFormulaData - // for (const unitKey in this._otherFormulaData) { - // const unit = this._otherFormulaData[unitKey]; - // if (!unit) continue; - - // for (const sheetKey in unit) { - // const sheet = unit[sheetKey]; - // for (const formulaKey in sheet) { - // if (sheet[formulaKey] == null) { - // continue; - // } - // resetAndPush(sheet[formulaKey]); - // } - // } - // } - - // // _featureFormulaData - // for (const unitKey in this._featureFormulaData) { - // const unit = this._featureFormulaData[unitKey]; - // if (!unit) continue; - - // for (const sheetKey in unit) { - // const sheet = unit[sheetKey]; - // for (const featureKey in sheet) { - // if (sheet[featureKey] == null) { - // continue; - // } - // resetAndPush(sheet[featureKey]); - // } - // } - // } - - // // _formulaData - // for (const unitKey in this._formulaData) { - // const unit = this._formulaData[unitKey]; - // if (!unit) continue; - - // for (const sheetKey in unit) { - // const sheet = unit[sheetKey]; - // sheet.forValue((row, col, item) => { - // if (item == null) { - // return true; - // } - // resetAndPush(item); - // }); - // } - // } - - const trees: IFormulaDependencyTree[] = []; - this._allTreeMap.forEach((tree) => { - tree.resetState(); - trees.push(tree); - }); - - return trees; - } - - getTreeById(treeId: number) { - return this._allTreeMap.get(treeId); - } - searchDependency(search: IUnitRange[]): Set { return this._dependencyRTreeCache.bulkSearch(search) as Set; } @@ -172,25 +95,26 @@ export class DependencyManagerService extends Disposable implements IDependencyM addOtherFormulaDependency(unitId: string, sheetId: string, formulaId: string, dependencyTree: IFormulaDependencyTree) { if (!this._otherFormulaData.has(unitId)) { - this._otherFormulaData.set(unitId, new Map>>()); + this._otherFormulaData.set(unitId, new Map>>()); } const unitMap = this._otherFormulaData.get(unitId)!; if (!unitMap.has(sheetId)) { - unitMap.set(sheetId, new Map>()); + unitMap.set(sheetId, new Map>()); } const sheetMap = unitMap.get(sheetId)!; if (!sheetMap.has(formulaId)) { - sheetMap.set(formulaId, new Set()); + sheetMap.set(formulaId, new ObjectMatrix()); } - const treeSet = sheetMap.get(formulaId)!; + const formulaMatrix = sheetMap.get(formulaId)!; + + formulaMatrix.setValue(dependencyTree.refOffsetX, dependencyTree.refOffsetY, dependencyTree.treeId); - treeSet.add(dependencyTree.treeId); - this._allTreeMap.set(dependencyTree.treeId, dependencyTree); + this._addAllTreeMap(dependencyTree); } removeOtherFormulaDependency(unitId: string, sheetId: string, formulaIds: string[]) { @@ -204,13 +128,10 @@ export class DependencyManagerService extends Disposable implements IDependencyM return; } - for (const treeId of treeSet) { - const tree = this._allTreeMap.get(treeId); - if (tree) { - this._removeDependencyRTreeCache(tree); - this._removeAllTreeMap(treeId); - } - } + treeSet.forValue((row, column, treeId) => { + this._removeDependencyRTreeCache(treeId); + this._removeAllTreeMap(treeId); + }); sheetMap.delete(formulaId); this._otherFormulaDataMainData.delete(formulaId); @@ -251,12 +172,12 @@ export class DependencyManagerService extends Disposable implements IDependencyM continue; } - for (const treeId of formulaTreeSet) { + formulaTreeSet.forValue((row, column, treeId) => { const tree = this._allTreeMap.get(treeId); if (tree) { this._removeAllTreeMap(treeId); } - } + }); this._otherFormulaDataMainData.delete(formulaId); } @@ -272,12 +193,12 @@ export class DependencyManagerService extends Disposable implements IDependencyM continue; } - for (const treeId of formulaTreeSet) { + formulaTreeSet.forValue((row, column, treeId) => { const tree = this._allTreeMap.get(treeId); if (tree) { this._removeAllTreeMap(treeId); } - } + }); this._otherFormulaDataMainData.delete(formulaId); } @@ -300,7 +221,8 @@ export class DependencyManagerService extends Disposable implements IDependencyM const sheetMap = unitMap.get(sheetId)!; sheetMap.set(featureId, dependencyTree.treeId); - this._allTreeMap.set(dependencyTree.treeId, dependencyTree); + // this._allTreeMap.set(dependencyTree.treeId, dependencyTree); + this._addAllTreeMap(dependencyTree); } removeFeatureFormulaDependency(unitId: string, sheetId: string, featureIds: string[]) { @@ -312,8 +234,8 @@ export class DependencyManagerService extends Disposable implements IDependencyM if (deleteTreeId == null) { return; } - const deleteTree = this._allTreeMap.get(deleteTreeId); - this._removeDependencyRTreeCache(deleteTree); + + this._removeDependencyRTreeCache(deleteTreeId); sheetMap.delete(featureId); this._removeAllTreeMap(deleteTreeId); @@ -351,8 +273,7 @@ export class DependencyManagerService extends Disposable implements IDependencyM } getFeatureFormulaDependency(unitId: string, sheetId: string, featureId: string) { - const treeId = this._featureFormulaData.get(unitId)?.get(sheetId)?.get(featureId); - return treeId != null ? this._allTreeMap.get(treeId) as FormulaDependencyTree : null; + return this._featureFormulaData.get(unitId)?.get(sheetId)?.get(featureId); } addFormulaDependency(unitId: string, sheetId: string, row: number, column: number, dependencyTree: IFormulaDependencyTree) { @@ -367,7 +288,8 @@ export class DependencyManagerService extends Disposable implements IDependencyM const sheetMatrix = unitMap.get(sheetId)!; sheetMatrix.setValue(row, column, dependencyTree.treeId); - this._allTreeMap.set(dependencyTree.treeId, dependencyTree); + // this._allTreeMap.set(dependencyTree.treeId, dependencyTree); + this._addAllTreeMap(dependencyTree); } removeFormulaDependency(unitId: string, sheetId: string, row: number, column: number) { @@ -379,8 +301,7 @@ export class DependencyManagerService extends Disposable implements IDependencyM return; } - const deleteTree = this._allTreeMap.get(deleteTreeId); - this._removeDependencyRTreeCache(deleteTree); + this._removeDependencyRTreeCache(deleteTreeId); sheetMatrix.realDeleteValue(row, column); this._removeAllTreeMap(deleteTreeId); @@ -421,8 +342,7 @@ export class DependencyManagerService extends Disposable implements IDependencyM } getFormulaDependency(unitId: string, sheetId: string, row: number, column: number) { - const treeId = this._formulaData.get(unitId)?.get(sheetId)?.getValue(row, column); - return treeId != null ? this._allTreeMap.get(treeId) : null; + return this._formulaData.get(unitId)?.get(sheetId)?.getValue(row, column); } addDependencyRTreeCache(tree: IFormulaDependencyTree) { @@ -456,41 +376,57 @@ export class DependencyManagerService extends Disposable implements IDependencyM this._dependencyRTreeCache.removeById(unitId, sheetId); } - private _removeDependencyRTreeCache(tree: Nullable) { - if (tree == null) { + private _removeDependencyRTreeCache(treeId: Nullable) { + if (treeId == null) { return; } - const searchRanges: IRTreeItem[] = []; - const rangeList = tree.rangeList; - for (let i = 0; i < rangeList.length; i++) { - const unitRangeWithNum = rangeList[i]; - const { unitId, sheetId, range } = unitRangeWithNum; + const treeRangeMap = this._allTreeMap.get(treeId); + + if (treeRangeMap) { + const searchRanges: IRTreeItem[] = []; + for (const [unitId, sheetMap] of treeRangeMap) { + for (const [sheetId, range] of sheetMap) { + searchRanges.push({ + unitId, + sheetId, + range, + id: treeId, + }); + } + } - searchRanges.push({ - unitId, - sheetId, - range, - id: tree.treeId, - }); + this._dependencyRTreeCache.bulkRemove(searchRanges); + } + } + + addFormulaDependencyByDefinedName(unitId: string, definedName: string, treeId: number) { + if (!this._definedNameMap.has(unitId)) { + this._definedNameMap.set(unitId, new Map>()); + } + + const unitMap = this._definedNameMap.get(unitId)!; + + if (!unitMap.has(definedName)) { + unitMap.set(definedName, new Set()); } - this._dependencyRTreeCache.bulkRemove(searchRanges); + const treeSet = unitMap.get(definedName)!; + treeSet.add(treeId); } removeFormulaDependencyByDefinedName(unitId: string, definedName: string) { - const unitMap = this._formulaData.get(unitId); + const unitMap = this._definedNameMap.get(unitId); if (unitMap) { - unitMap.forEach((sheetMatrix) => { - sheetMatrix.forValue((row, column, treeId) => { - const tree = this._allTreeMap.get(treeId); - if (tree?.nodeData.node?.hasDefinedName(definedName)) { - this._removeDependencyRTreeCache(tree); - sheetMatrix.realDeleteValue(row, column); - } - }); - }); + const treeSet = unitMap.get(definedName); + if (treeSet) { + for (const treeId of treeSet) { + this._removeDependencyRTreeCache(treeId); + this._removeAllTreeMap(treeId); + } + treeSet.clear(); + } } } @@ -508,6 +444,37 @@ export class DependencyManagerService extends Disposable implements IDependencyM } this._allTreeMap.delete(treeId); } + + private _addAllTreeMap(tree: IFormulaDependencyTree) { + const rangeList = tree.rangeList; + const oldTreeMap = this._allTreeMap.get(tree.treeId); + for (let i = 0; i < rangeList.length; i++) { + const unitRangeWithNum = rangeList[i]; + let { unitId, sheetId, range } = unitRangeWithNum; + if (!this._allTreeMap.has(tree.treeId)) { + this._allTreeMap.set(tree.treeId, new Map>()); + } + + const treeMap = this._allTreeMap.get(tree.treeId)!; + + if (!treeMap.has(unitId)) { + treeMap.set(unitId, new Map()); + } + + const oldRange = oldTreeMap?.get(unitId)?.get(sheetId); + if (oldRange) { + range = { + startRow: Math.min(range.startRow, oldRange.startRow), + startColumn: Math.min(range.startColumn, oldRange.startColumn), + endRow: Math.max(range.endRow, oldRange.endRow), + endColumn: Math.max(range.endColumn, oldRange.endColumn), + }; + } + + const unitMap = treeMap.get(unitId)!; + unitMap.set(sheetId, range); + } + } } export const IDependencyManagerService = createIdentifier(