perf: drop un-flatten-tree dep & optimize Tree Data utils by ~3x perf#2601
perf: drop un-flatten-tree dep & optimize Tree Data utils by ~3x perf#2601ghiscoding wants to merge 4 commits into
un-flatten-tree dep & optimize Tree Data utils by ~3x perf#2601Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2601 +/- ##
=======================================
Coverage 100.0% 100.0%
=======================================
Files 199 199
Lines 25168 25182 +14
Branches 8908 8909 +1
=======================================
+ Hits 25168 25182 +14
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
angular-slickgrid
aurelia-slickgrid
slickgrid-react
slickgrid-vue
@slickgrid-universal/angular-row-detail-plugin
@slickgrid-universal/aurelia-row-detail-plugin
@slickgrid-universal/react-row-detail-plugin
@slickgrid-universal/vue-row-detail-plugin
@slickgrid-universal/binding
@slickgrid-universal/common
@slickgrid-universal/composite-editor-component
@slickgrid-universal/custom-footer-component
@slickgrid-universal/custom-tooltip-plugin
@slickgrid-universal/empty-warning-component
@slickgrid-universal/event-pub-sub
@slickgrid-universal/excel-export
@slickgrid-universal/graphql
@slickgrid-universal/odata
@slickgrid-universal/pagination-component
@slickgrid-universal/pdf-export
@slickgrid-universal/row-detail-view-plugin
@slickgrid-universal/rxjs-observable
@slickgrid-universal/sql
@slickgrid-universal/text-export
@slickgrid-universal/utils
@slickgrid-universal/vanilla-bundle
@slickgrid-universal/vanilla-force-bundle
commit: |
|
@zewa666 another win for the AI usage... by looking at the dependency "un-flatten-tree", I found this benchmark created by a user a few years ago: https://github.com/philipstanislaus/array-to-tree-benchmarks then after asking the AI if I could switch to the more performant lib, Claude AI actually identified that we could use native code (aka drop dependency) and improve the perf by about ~3x (or 300%) with O(n) instead of O(n2)... wow this is just awesome... go ahead Claude 🚀 That's also great because that was 1 of the last package that wasn't fully ESM, which is why it was on my list of TODOs eventually. my company increased our plan to also just let me know when you're done reviewing the other 2 PRs |
un-flatten-tree dep & optimize Tree Data utilities by ~3xun-flatten-tree dep & optimize Tree Data perf by factor of ~3x
un-flatten-tree dep & optimize Tree Data perf by factor of ~3xun-flatten-tree dep & optimize Tree Data utils by ~3x perf
vibe coded with copilot using Claude Sonnet 4.6
Summary
Removes the
un-flatten-treethird-party dependency from@slickgrid-universal/commonand rewrites or optimizes all tree data utility functions for significantly better performance, particularly at scale (50k–250k nodes). This makes the Tree Data to parse about ~3x faster when converting from flat to tree and vice versa (flatten/unflatten) which is how Tree Data was implemented in SlickGrid (when using Tree Data in SlickGrid we always keep a flat data copy and its equivalent tree data).Changes
package.json
"un-flatten-tree"from dependenciesutilities.ts
flattenToParentChildArray(previously usedun-flatten-tree)nodeStack+parentStack) — avoids tuple allocation per node{ ...node }thendelete flatNode[childrenPropName]) to preserve the original hierarchical dataset intact (shared object references between flat and hierarchical arrays require this)findItemInTreeStructure(previously recursive)unflattenParentChildArrayToTreeMap— avoids prototype-chain overhead andObject.keys()allocationforEachwith indexedforloopsaddTreeLevelByMutationgetTreeDataOptionPropName()calls with directoptions.childrenPropNameaccessforEachwith indexedforloop; cachedchildrento a local variable (singleArray.isArraycheck)addTreeLevelAndAggregatorsByMutationisParentto avoid doubleArray.isArraychecktreeData.service.ts
_childrenPropName,_collapsedPropName,_hasChildrenPropName,_lazyLoadingPropName,_levelPropName) initialized once ininit()— eliminates ~20 repeatedgetTreeDataOptionPropName()call sites across the service, each of which previously chained two getter calls plus a switch statementgetTreeDataOptionPropName()lookups from:handleOnCellClick,handleOnKeyDown,toggleTreeDataCollapse,updateToggledItem,applyToggledItemStateChanges,initHierarchicalTree,recalculateTreeTotals,getItemCounttoggleAllFlatDataItems: inlined theupdateToggledItem(item, collapsing, false)body directly into the loop — eliminates one function call + twogetTreeDataOptionPropNamelookups per item during full collapse/expand of large datasetsutilities.spec.ts
unflattenParentChildArrayToTreetest expectations to matchMapinsertion order (previously relied on plain-object auto-sorting of integer keys)flattenToParentChildArraytests to reflect thatchildrenproperty is no longer present on flat items (was previously leaking through)addTreeLevelByMutation, 2 foraddTreeLevelAndAggregatorsByMutation, 2 forfindItemInTreeStructure