Data Controls and Large UI Surfaces
The two biggest surfaces in the app are gone:
- The ticket grid is virtual.
Tickets/Search990 ms → 125 ms; the click issues 3 statements instead of 5,001, and the session holds a page of rows instead of the result. - The customer tree loads a level at a time.
Customers/LoadTree510 ms → 62 ms (3,201 statements → 3),Customers/ExpandNode158 ms → 9 ms.
Both are now inside budget. Evidence and the payload discussion: LargeSurfaces.md.
Run it
cd "LearnWisej-Samples/Performance and Profiling Course/Module 5/WisejPerfLab"
dotnet run -c Release -f net10.0 --urls http://localhost:5805
Module 4 on 5804 is the before.
What to click
| Action | What you should see |
|---|---|
| Tickets → Search tickets | 5,000 rows … 125 ms — within the 300 ms budget, and a moment later 1 page(s) held 1 fetch(es) 201 statements as the grid asks for the rows it is showing |
| scroll the grid to the middle | another fetch, another page — never a query per cell |
| Tickets → Redraw | a repaint: no query, no row objects |
| Customers → Load the customer tree | 8 root nodes 3 SQL statements 62 ms — within the 150 ms budget, each branch labelled (20 below) |
| Customers → Expand the first branch | 20 children 3 SQL statements 9 ms — and expanding it again costs nothing, the children are already there |
| Break the database → search | empty grid, banner, failed=DatabaseUnavailableException |
| Break the database → expand a fresh branch | the node says (children unavailable) and keeps its placeholder |
| Run the three scenarios ×3 | all three medians inside budget for the first time in the course |
What changed since Module 4
Models/TicketGridRow.cs new — the six displayed columns, formatted; no entity reaches the UI
Models/TicketRow.cs deleted (replaced by TicketGridRow)
Models/TicketDisplayRow.cs deleted — its last caller went with TicketFormatter.FormatRow
Models/CustomerNodeRow.cs + ChildCount, and a label that carries the count placeholder
Services/TicketQueryService.cs new — Count(filter) and GetPage(filter, first, count)
Services/TicketSearchService.cs deleted
Services/TicketPageCache.cs new — the page cache behind CellValueNeeded
Services/CustomerTreeService.cs rewritten — GetRoots() / GetChildren(id), 3 grouped statements a level
Services/TicketFormatter.cs FormatRow deleted; + FormatMoment
Pages/TicketGridPage.cs virtual mode: RowCount from a count query, CellValueNeeded + DataRead
Pages/CustomerTreePage.cs roots only, placeholder children, load on expand
Forms/TicketDetailForm.cs takes a TicketGridRow
Startup.cs registers TicketQueryService
TicketFormatter.FormatRow — the function at the top of the Module 2 hot path, called 50,000 times
per refresh — no longer exists. Module 3 took the dashboard off it, Module 5 took the grid off it, and
the last caller went with them. That is the normal ending for a hot function: not making it faster, not
calling it.
Known simplifications
- Update byte counts are not in the docs, because every update here travels over the WebSocket and
the Performance API does not report its frames.
LargeSurfaces.mdsays how to read them in the browser's Network panel, and what was measured instead. - The export still blocks the request thread and still writes the file a line at a time. Module 6.