Skip to content

[Tree widget]: implement descendants count cache on next#1680

Merged
JonasDov merged 8 commits into
tree-widget/nextfrom
JonasD/descendantsCountCache
May 15, 2026
Merged

[Tree widget]: implement descendants count cache on next#1680
JonasDov merged 8 commits into
tree-widget/nextfrom
JonasD/descendantsCountCache

Conversation

@JonasDov
Copy link
Copy Markdown
Contributor

Implement 1st stage of #1678.

Copilot AI review requested due to automatic review settings May 15, 2026 10:15
@JonasDov JonasDov requested review from a team as code owners May 15, 2026 10:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the tree widget descendant-count cache so counts can be grouped by category and requested for either category roots or element parents, while keeping the legacy element-count API through aggregation.

Changes:

  • Reworked DescendantsCountCache request/cached value shape and query to return grouped descendant counts.
  • Restored BaseIdsCache/BaseIdsCacheImpl APIs for descendant counts and element counts.
  • Updated and expanded unit coverage, plus corrected cache references in visibility documentation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/caches/DescendantsCountCache.ts Implements grouped descendant count batching, querying, and caching.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.ts Exposes grouped descendant counts and aggregates them for element counts.
packages/itwin/tree-widget/src/test/trees/models-tree/internal/ModelsTreeIdsCache.test.ts Updates model tree count cache tests for the new query result shape.
packages/itwin/tree-widget/src/test/trees/common/internal/DescendantsCountCache.test.ts Expands cache tests to cover grouped category and element descendant count scenarios.
packages/itwin/tree-widget/docs/Visibility.md Fixes documentation references from ElementChildrenCache to ChildElementsCache.
Comments suppressed due to low confidence (2)

packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/caches/DescendantsCountCache.ts:198

  • Rows produced for root-category and element requests use SQL NULL for reqParent/reqCategory, but requests are keyed in the cache with JavaScript undefined. Storing rows under null makes the subsequent lookup for undefined miss, so the tap default path overwrites these requests with 0/empty results. Normalize nullable request keys (for example, row.reqParent ?? undefined and row.reqCategory ?? undefined) before accessing the cache maps.
              let parentEntry = modelEntry.get(row.reqParent);
              if (!parentEntry) {
                parentEntry = new Map();
                modelEntry.set(row.reqParent, parentEntry);
              }
              let categoryEntry = parentEntry.get(row.reqCategory);

packages/itwin/tree-widget/src/test/trees/models-tree/internal/ModelsTreeIdsCache.test.ts:52

  • This expected substring has the predicates in a different order than the query now generated (Category.Id IN (...) comes before Parent.Id IS NULL), so the stub rejects the intended query. Update this matcher or make it check the individual predicates independently.
      if (query.includes("Descendants") && query.includes(`Model.Id = ${modelId} AND Parent.Id IS NULL AND Category.Id IN (${categoryId}, ${categoryId2})`)) {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tree-Widget Next benchmark

Benchmark suite Current: 85e13c7 Previous: 72114e0 Deviation Status
models tree 50k 3D elements search > get search paths 1224 ms 1262 ms -3.01% 〰️
models tree 50k 3D elements search > get search paths (P95 of main thread blocks) 65 ms 62 ms 4.84% 〰️
models tree 50k 3D elements search > load hierarchy from search paths 112513 ms 110444 ms 1.87% 〰️
models tree 50k 3D elements search > load hierarchy from search paths (P95 of main thread blocks) 38 ms 40 ms -5% 〰️
models tree 50k categories > collect nodes 2992 ms 2970 ms 0.74% 〰️
models tree 50k categories > collect nodes (P95 of main thread blocks) 138 ms 102 ms 35.29% 〰️
models tree 50k categories > validate initial visibility 2572 ms 2522 ms 1.98% 〰️
models tree 50k categories > validate initial visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k categories > change visibility 90 ms 76 ms 18.42% 〰️
models tree 50k categories > change visibility (P95 of main thread blocks) 80 ms 65 ms 23.08% 〰️
models tree 50k categories > validate changed visibility 4648 ms 4626 ms 0.48% 〰️
models tree 50k categories > validate changed visibility (P95 of main thread blocks) 25 ms 25 ms 0% 🟰
models tree 50k 3D elements > collect nodes 44385 ms 44420 ms -0.08% 〰️
models tree 50k 3D elements > collect nodes (P95 of main thread blocks) 72 ms 67 ms 7.46% 〰️
models tree 50k 3D elements > validate initial visibility 2509 ms 2489 ms 0.80% 〰️
models tree 50k 3D elements > validate initial visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > change model visibility 21 ms 19 ms 10.53% 〰️
models tree 50k 3D elements > change model visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > validate changed model visibility 2593 ms 2493 ms 4.01% 〰️
models tree 50k 3D elements > validate changed model visibility (P95 of main thread blocks) 23 ms 0 ms 2300% 〰️
models tree 50k 3D elements > change category node visibility 507 ms 515 ms -1.55% 〰️
models tree 50k 3D elements > change category node visibility (P95 of main thread blocks) 52 ms 62 ms -16.13% 〰️
models tree 50k 3D elements > validate changed category visibility 2515 ms 2526 ms -0.44% 〰️
models tree 50k 3D elements > validate changed category visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > validate per-model category override 2519 ms 2475 ms 1.78% 〰️
models tree 50k 3D elements > validate per-model category override (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > change element visibility 10 ms 10 ms 0% 🟰
models tree 50k 3D elements > change element visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > validate changed element visibility 3251 ms 3187 ms 2.01% 〰️
models tree 50k 3D elements > validate changed element visibility (P95 of main thread blocks) 72 ms 73 ms -1.37% 〰️
models tree 50k 3D child elements with different categories > collect nodes 45847 ms 44439 ms 3.17% 〰️
models tree 50k 3D child elements with different categories > collect nodes (P95 of main thread blocks) 60 ms 61 ms -1.64% 〰️
models tree 50k 3D child elements with different categories > validate initial visibility 2518 ms 2459 ms 2.40% 〰️
models tree 50k 3D child elements with different categories > validate initial visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D child elements with different categories > change visibility 10 ms 10 ms 0% 🟰
models tree 50k 3D child elements with different categories > change visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D child elements with different categories > validate changed visibility 3350 ms 3219 ms 4.07% 〰️
models tree 50k 3D child elements with different categories > validate changed visibility (P95 of main thread blocks) 64 ms 57 ms 12.28% 〰️
categories tree 50k subCategories search > get search paths 1884 ms 1872 ms 0.64% 〰️
categories tree 50k subCategories search > get search paths (P95 of main thread blocks) 41 ms 43 ms -4.65% 〰️
categories tree 50k subCategories search > load hierarchy from search paths 5541 ms 5522 ms 0.34% 〰️
categories tree 50k subCategories search > load hierarchy from search paths (P95 of main thread blocks) 54 ms 49 ms 10.20% 〰️
categories tree 50k subCategories > collect nodes 6096 ms 5994 ms 1.70% 〰️
categories tree 50k subCategories > collect nodes (P95 of main thread blocks) 50 ms 51 ms -1.96% 〰️
categories tree 50k subCategories > validate initial visibility 1689 ms 1708 ms -1.11% 〰️
categories tree 50k subCategories > validate initial visibility (P95 of main thread blocks) 21 ms 21 ms 0% 🟰
categories tree 50k subCategories > change visibility 346 ms 352 ms -1.70% 〰️
categories tree 50k subCategories > change visibility (P95 of main thread blocks) 27 ms 23 ms 17.39% 〰️
categories tree 50k subCategories > validate changed visibility 1614 ms 1619 ms -0.31% 〰️
categories tree 50k subCategories > validate changed visibility (P95 of main thread blocks) 30 ms 29 ms 3.45% 〰️
categories tree 50k categories > collect nodes 2485 ms 2537 ms -2.05% 〰️
categories tree 50k categories > collect nodes (P95 of main thread blocks) 139 ms 130 ms 6.92% 〰️
categories tree 50k categories > validate initial visibility 7397 ms 7478 ms -1.08% 〰️
categories tree 50k categories > validate initial visibility (P95 of main thread blocks) 75 ms 81 ms -7.41% 〰️
categories tree 50k categories > change visibility 698 ms 708 ms -1.41% 〰️
categories tree 50k categories > change visibility (P95 of main thread blocks) 46 ms 56 ms -17.86% 〰️
categories tree 50k categories > validate changed visibility 7356 ms 7327 ms 0.40% 〰️
categories tree 50k categories > validate changed visibility (P95 of main thread blocks) 37 ms 34 ms 8.82% 〰️
classifications tree 50k classifications search > get search paths 2224 ms 2210 ms 0.63% 〰️
classifications tree 50k classifications search > get search paths (P95 of main thread blocks) 140 ms 137 ms 2.19% 〰️
classifications tree 50k classifications search > load hierarchy from search paths 69615 ms 69057 ms 0.81% 〰️
classifications tree 50k classifications search > load hierarchy from search paths (P95 of main thread blocks) 23 ms 31 ms -25.81% 〰️
classifications tree 50k classifications > collect nodes 37580 ms 37360 ms 0.59% 〰️
classifications tree 50k classifications > collect nodes (P95 of main thread blocks) 93 ms 75 ms 24% 〰️
classifications tree 50k classifications > validate initial visibility 4873 ms 4833 ms 0.83% 〰️
classifications tree 50k classifications > validate initial visibility (P95 of main thread blocks) 67 ms 59 ms 13.56% 〰️
classifications tree 50k classifications > change visibility 29 ms 31 ms -6.45% 〰️
classifications tree 50k classifications > change visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
classifications tree 50k classifications > validate changed visibility 5228 ms 5091 ms 2.69% 〰️
classifications tree 50k classifications > validate changed visibility (P95 of main thread blocks) 161 ms 90 ms 78.89% 🚨

This comment was automatically generated by workflow using github-action-benchmark.

@JonasDov JonasDov merged commit 45b95b4 into tree-widget/next May 15, 2026
11 checks passed
@JonasDov JonasDov deleted the JonasD/descendantsCountCache branch May 15, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants