Repository navigation
FinOps Lite top-consumer and idle-check reads use one statement each (part of #4227) - #4243
Merged
Merged
Conversation
…fleet statement for Server Inventory idle-database check (#4227) Part of #4227's Lite parity. Measured on a seeded DuckDB before porting either: the Utilization top-consumers pair and the Server Inventory per-server loop both showed a real, repeatable win from merging (roughly 2x); the Storage Growth bounds-computed-twice pattern did not, so it's left unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
erikdarlingdata
marked this pull request as ready for review
September 25, 2026 05:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #4227.
Why
Lane V3b confirmed by inspection that Lite's FinOps tab carries the same two redundant-read patterns #4240 fixed in the Darling viewer. The coordinator also added a third item: V3a's PR #4241 folded Darling's Server Inventory idle-database check from one statement per server into one fleet statement. V3b measured Lite's twin too.
This PR measures all three patterns on a seeded DuckDB before changing anything and ports only the ones with a real, repeatable win. DuckDB is columnar and in-process. A second read over data DuckDB already cached can cost next to nothing. That differs from Postgres/TimescaleDB, where the original #4227/#4240/#4241 wins came from avoiding a second pass over a large, disk-resident hypertable. That difference held for one of the three patterns here.
What I found and measured
Seeded one DuckDB (own isolated instance, not the shared test fixture) with 50 servers and 15,000+ rows across cpu/memory/grant/size/query_stats. One focus server had a heavier load: 4,800 query_stats rows, 960 file_io_stats rows, and 4,500 index_object_stats rows over 30 daily snapshots. Timed the current code against a merged form, 5 iterations each, 3 full runs:
boundscomputed once per statement, twice total)Task.WhenAll, matches production)The Utilization and Server Inventory wins both trace mostly to halving or fleet-collapsing the
OpenConnectionAsync/read-lock-acquisition cost. Each of those methods opens its own DuckDB connection today. The Storage Growth pattern's redundant work is a cheap MAX/MIN over an already-indexedcollection_timecolumn, computed within a single connection either way. There was nothing real to save."Lite's top server count"
Not documented anywhere I found (no cap in
ServerManager, no stated limit inLite/README.md). This PR uses 50, matching the production 43-server fleet #4227 used as a round-number ceiling.Continuous aggregates
Lite has none (no TimescaleDB, no rollup views). The rollup/watermark routing #4241 added for the idle check does not apply here. The merged fleet statement reads raw tables only, the same as the per-server loop it replaces.
What changes
Lite/Services/LocalDataService.FinOps.Workload.cs:GetTopResourceConsumersByTotalAsyncandGetTopResourceConsumersByAvgAsyncbecome oneGetTopResourceConsumersAsync, returning(List<TopResourceConsumerRow> ByTotal, List<TopResourceConsumerRow> ByAvg)from one statement. Each grid keeps its own old filter. ByTotal drops a NULL database name. ByAvg drops a zero-execution database. Both filters now apply client-side from the same row set.Lite/Services/LocalDataService.FinOps.ServerProperties.cs:GetServerMetricsAsync(int serverId)becomesGetServerMetricsAsync(), returningDictionary<int, ServerMetricsRow>for every server in one statement. A server with no collected rows still gets an entry (all fields null), matching the old per-server statement's anchor row.Lite/Controls/FinOpsTab.xaml.cs:LoadServerInventoryAsynccalls the fleet statement once before the per-server fan-out. The fan-out still runs per server for the LIVE SQL query (a real network call per monitored server). Only the DuckDB overlay moved.LoadUtilizationAsynccalls the merged consumer read once.LocalDataService.FinOps.IndexObjects.cs(Storage Growth). Measured, not ported. Numbers are in the table above.Test plan
Lite.Tests/FinOpsFleetReadParityTests.cs(new): pins that the merged Utilization read keeps each old grid's NULL-name/zero-execution filter. It also pins that the fleet statement covers every server (a server with zero rows gets a slot) and flags an idle database. Both tests pass.FinOpsVerdictSourcePinTests(existing [BUG] FinOps provisioning status reports UNDER_PROVISIONED for every healthy server: the memory ratio compares Total to Target Server Memory, which converge at 1.0 #2246 source pin) still passes against the rewrittenServerProperties.cs. The pressure-signal columns and the sharedProvisioningVerdict.Evaluatecall are still there in the merged SQL/C#.dotnet build Lite.Tests/Lite.Tests.csproj: 0 warnings, 0 errors, both before and after mergingorigin/dev(fast-forward, no conflicts, touched only Darling files).Lite.Testssuite: not run. This lane hit its context checkpoint after the targeted runs above. The coordinator must run a full-suite pass before merging.CHANGELOG entry
SECTION: Fixed
ENTRY:
REF:
[FinOps Lite top-consumer and idle-check reads use one statement each (part of #4227) #4243]: FinOps Lite top-consumer and idle-check reads use one statement each (part of #4227) #4243
Generated with Claude Code
https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3