CPU Hot Paths and Server-Side UI Work
The dashboard refresh is fixed: 476 ms → 113 ms, medians of three warm runs, against a noise floor of 13 %.
The fix is the one the lesson asks for — a DashboardSnapshot of display-ready values built once in
the service, assigned to controls that already exist — applied where the profiler said the time
actually was. See BeforeAfter.md and SnapshotDesign.md.
Run it
cd "LearnWisej-Samples/Performance and Profiling Course/Module 3/WisejPerfLab"
dotnet run -c Release -f net10.0 --urls http://localhost:5803
To see the before and after side by side, run Module 2 on 5802 at the same time and click Refresh in both.
What to click
| Action | What you should see |
|---|---|
| Warm up (discarded run), then Dashboard → Refresh | Refresh 109 ms — within the 250 ms budget 4 queries as of 11:31:45 |
| the PERF log for that run | stage Refresh / snapshot (4 aggregate queries, formatted once) 109 ms, stage Refresh / assign 0 ms — and no calls TicketFormatter.FormatRow line, because it is never called |
| Run the three scenarios ×3 | median Dashboard/Refresh = 113 ms — within the 250 ms budget, spread 13 % |
| Click Refresh twice quickly | the second click is dropped: a refresh is already running — the second click was dropped |
| Break the database → Refresh | the button comes back, the banner explains, the KPIs keep their last good values, and the PERF end record is still written with failed=DatabaseUnavailableException |
| Compare the KPI numbers with Module 2 | identical: 11,907 open, ~21,64x overdue, 90.5 d average age |
The other two scenarios are untouched and still over budget — Tickets/Search 414 ms, tree expand
158 ms. They are Modules 4, 5 and 6.
One thing here belongs to Module 4
This folder also carries Diagnostics/MemoryProbe.cs, the detail-form counters and the three buttons
Memory snapshot A / Open and close the detail form ×50 / Snapshot B and compare — with the
unfixed detail form. They are here so the before reading for Module 4 can be taken on the
code as it stood: B - A: heap +76.0 MB subscribers +50. Module 4 fixes the form and the same three
buttons report +1.1 MB subscribers 0.
What changed since Module 2
Models/DashboardSnapshot.cs new — OpenTicketsText, OverdueTicketsText, AverageAgeText, ChartRows, GeneratedAt
Services/DashboardService.cs + GetSnapshot(): 4 aggregate queries, formatted once, no entity returned
LoadAllTickets() kept but no longer called by anything
Services/TicketFormatter.cs status/priority labels are now a static lookup, not a per-call string.Format
+ FormatDay() for the chart axis
Pages/DashboardPage.cs rewritten: KPI cards built once in the constructor, values assigned,
RebuildKpiPanel deleted, _refreshing guard added
Nothing else moved. ScenarioProbe, the budget, the PERF log and the scenario definitions are
identical to Module 2, so the before/after table compares the same measurement.