Skip to content

feat(log-viewer): show the Call Tree in lv-grid - #1167

Merged
lcottercertinia merged 41 commits into
mainfrom
feat-call-tree-lv-grid
Oct 16, 2026
Merged

lcottercertinia merged 41 commits into
mainfrom
feat-call-tree-lv-grid

Conversation

@lukecotter

@lukecotter lukecotter commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

What

The Call Tree's three views (Time Order, Aggregated and Bottom-Up) now use lv-grid, the grid from #1166. The Call Tree's Tabulator tables are deleted. There is no setting to go back.

The Bottom-Up Tabulator table stays, because the Analysis view uses it. The Analysis, Database and inspector grids stay on Tabulator. Each gets its own change later.

User-visible changes

  • The Call Tree is much faster on large logs. The numbers are below.
  • Cmd/Ctrl+C copies the table in every view. The copy holds the shown columns, tab-separated, and every row that passes the filters, closed rows too. Before, only Bottom-Up copied, and only its top-level rows.
  • Bottom-Up ungroup no longer overflows the stack.
  • The category tint setting changes an open Call Tree at once.
  • A row picked in the inspector scrolls into view only when it is off screen, as before.

Numbers

Measured on a 95 MB log of 580,091 rows: the median of 5 runs, and first render the median of 3 loads. Each cell gives the time in ms, then the longest task in ms.

Action Tabulator lv-grid
Time Order, sort by self time 473 · 525 166 · 0
Time Order, expand all 254 · 655 74 · 0
Time Order, find 641 · 17,639 500 · 0
Time Order, drag a column wider 60 of 60 frames dropped 0 dropped
Time Order, heap after all runs 477 MB 31 MB
Bottom-Up, group by type 2,500 · 2,636 296 · 0
Bottom-Up, sort by total time 373 · 392 18 · 0
Aggregated (965 rows), every action 17–47 17–34

All the tables, with the method, are on the results page.

Known:

  • First render has one long task in every view, 179–187 ms. It is the garbage collection after the parse, and Tabulator has it too.
  • In Aggregated, the synchronous tree build adds to that task: 344 ms, where Tabulator takes 334 ms.
  • Earlier runs saw a 52–123 ms task in Bottom-Up group by, but only in some runs. It did not show in these 5 runs, and its cause is not known.

Screenshots

Dark Light
Call Tree, dark Call Tree, light

The three views, Time Order, Aggregated and Bottom-Up:

Three views, dark
Three views, light

Commits

Each commit is one concern, so a review by commit is easiest.

  1. Time Order and Bottom-Up on lv-grid, then a steady scroll bar (estimated row heights from line counts).
  2. Aggregated on lv-grid, and its bench with a Tabulator baseline recorded before the delete.
  3. Copy in every view.
  4. The colorize setting applies to an open grid.
  5. Reveal keeps the scroll when the row is in view (goTo takes scrollIfVisible).
  6. Remove the Call Tree's Tabulator tables and the helpers only they used.
  7. Docs, the screenshot script, and new screenshots in lana/assets/1_24.
  8. CHANGELOG.

Checks

  • pnpm lint passes, and jest passes, 2904 of 2904.
  • Anchoring, in Playwright, in all three views: after a toggle, sort, sort again, clear sort, filter off or filter on, the row in view stays at the same pixel in every frame. Four clicks on a twisty with no mouse move toggle it each time.
  • Checked by hand in the dev host: find, the inspector both ways, go to row, the Name link, copy, the column menu, the colorize setting, and a light and a dark theme.

Stacked on #1166.

Known open items

  • filterOn long task on the 580k-row bench log. In 1 of 5 runs, Time Order filterOn shows one 55–85 ms task. A Chrome trace shows it is a V8 full garbage collection (MajorGC), with no grid code in the task. The collection falls in whatever step runs when the heap fills.
  • Follow-ups from review, not in this PR:
    • Number the find marks from the store's count, not from the DOM text, so a cell no longer has to mark its find text.
    • Give a row filter a cache key in the grid store, so a host does not have to keep its filter objects.
    • Use one cancel mechanism in the Call Tree for the view switch, the visibility wait and the builds.

@lukecotter
lukecotter added this pull request to stack #1168 October 9, 2026 14:54
@lukecotter lukecotter changed the title feat call tree lv grid feat(log-viewer): show the Call Tree in lv-grid Oct 9, 2026
Comment thread log-viewer/bench/grid/main.ts Fixed
Comment thread log-viewer/bench/grid/main.ts Fixed
Comment thread log-viewer/bench/grid/main.ts Fixed
Comment thread log-viewer/bench/grid/main.ts Fixed
Comment thread log-viewer/bench/grid/main.ts Fixed
Comment thread log-viewer/bench/grid/main.ts Fixed
@lukecotter
lukecotter force-pushed the feat-call-tree-lv-grid branch from 7886ae9 to e8cdbcb Compare October 9, 2026 23:26
@lukecotter
lukecotter force-pushed the feat-call-tree-lv-grid branch from e8cdbcb to 544221b Compare October 16, 2026 09:10
Base automatically changed from feat-grid-spike to main October 16, 2026 09:26
@lcottercertinia
lcottercertinia marked this pull request as ready for review October 16, 2026 09:45
… in lv-grid

The Time Order and Bottom-Up views of the Call Tree now use lv-grid in
place of Tabulator. Aggregated stays on Tabulator until the next step.

- The view creates, wires and removes the 2 grids. The Bottom-Up build
  stops when a later build replaced it while it waited for its tree.
- Filters, find, go to row, expand and collapse all, the column menu
  and the row menu work on the grids.
- The inspector works both ways: select, hover, mark, reveal and clear.
- A sort, a filter or a group-by change resets the search.
- Bottom-Up keeps its group-by through a rebuild.
- lv-grid gets deselect(), for the inspector's clear.

The 7 view lifetime tests now check the grids. The overtaken-build test
fails when the Bottom-Up guard is removed.
…rolling

The scroll bar thumb moved while the user scrolled the Call Tree. The
grid took each row as 24px until it was drawn, and a measured row
changed the total height.

- A row with a twisty was 2px taller than a leaf: the chevron took a
  16px line. It now takes the text's line, so every 1-line row is the
  same height.
- The grid learns the 1-line height from the rows it measures. It only
  goes down, so a row that the column width wraps cannot raise it.
- lv-grid takes rowLines, a row's lines of text, and measures the line
  height once from a hidden cell. A tall row then has its height before
  it is drawn. Bottom-Up uses it; Time Order does not, because counting
  580k rows on each sort, filter and expand cost a 62-71ms task.

Sample log, change in scroll height over a full scroll: Time Order from
-6.0% to +1.9%, Bottom-Up from +15% to +6.6%. Rows taller than their
lines, wrapped names and laid-out queries, are still measured.

Bench at 580k rows, back to back with and without the change: no
difference beyond noise in either view, 0 of 120 fling frames dropped.
The Aggregated view now uses lv-grid, as Time Order and Bottom-Up do.
The columns, totals, filters, find, inspector link and reveal are the same
as before. The tree is built from the same aggregated rows.

The Tabulator code paths in the view are removed. The Tabulator table
files stay until a later commit deletes them.
Add the Aggregated table to the grid bench, as Tabulator and as lv-grid.
Record the Tabulator baseline at 580k rows before its table is deleted.
Cmd/Ctrl+C on the Call Tree grid copies the shown columns, tab-separated.
It copies every row that passes the filters, with its children, open or
not. This is true in Time Order, Aggregated and Bottom-Up. Before, only
Bottom-Up copied, and only its top-level rows.
…Tree grid

The Call Tree grid read the setting only when it was built. A change to
the setting now tints or clears the grids that are open, with no rebuild.
… row in view

A row picked in the inspector moved to the middle of the Call Tree, even
when it was already in view. Now the Call Tree scrolls only when the
whole row is not in view, as it did before the grid change.

lv-grid's goTo takes scrollIfVisible for this.
The Call Tree's Time Order and Aggregated views use lv-grid now, so their
Tabulator tables go. So do the helpers that only they used: the top-down
bucket walk and the self-sum heap footers.

The Bottom-Up Tabulator table stays, because the Analysis view uses it.

The grid bench keeps the Tabulator figures for Time Order and Aggregated
in baseline/, and runs the lv-grid contender by default.
Cmd/Ctrl+C copies every Call Tree view, Home and End go to the first and
last row, and left and right move to the parent and the first child.
A row picked in the inspector scrolls into view only when it is off
screen.
…enshot script

The Call Tree no longer uses Tabulator, so the script expands rows by their
twisty and finds the SOQL row by its row class. It opens the rows from the
bottom up, because the grid reuses row elements as rows open.

The shots now go to lana/assets/1_24, the folder of the next release.
Take the Call Tree screenshots again, dark and light, from the lv-grid
Call Tree, and put them in lana/assets/1_24 for the next release. The
Call Tree page and the README use them.
Measured on a 95 MB log of 580,091 rows, against the Tabulator tables.
The grid now starts a tree copy with a Level column, so the Call Tree copy
tests expect it in all three views. The docs and the changelog say so.
The Aggregated build ran in one task, which blocked the window for up to
350ms on a large log. It now runs in slices, as the Bottom-Up build does.
When a detach destroys the grids, an abort signal stops the Aggregated or
Bottom-Up build that is still running.
After go to row, the keys and copy did not work until a click on the grid.
lv-grid now has a focus() that moves focus to its rows, and go to row calls
it without a scroll.
Each filter update made new filter objects, and the grid keeps its filter
work per object, so it did all that work again. The view now keeps a filter
object while its input stays the same.
…of view

Each step to the next match centred the row, also when it was already in
view. A match in view now keeps the scroll, as go to row does.
…alues

Find marks did not agree with the count on time, governor and query cells.
Find now searches what each cell shows: the value without its percent, the
rounded Gov %, and the formatted query, kept once per query. Copy and export
write the query as the log has it and the full Gov %.
…b e2e test

The test waited for a Tabulator row, which the Call Tree no longer has.
@lcottercertinia
lcottercertinia merged commit 2da4a83 into main Oct 16, 2026
10 checks passed
@lcottercertinia
lcottercertinia deleted the feat-call-tree-lv-grid branch October 16, 2026 11:43
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