Problem
When viewing stored logging sessions with large datasets (e.g., 48 hours at 1000hz = 172M+ samples per channel), the app loads all samples into memory before rendering. This doesn't scale — it causes excessive memory usage and slow load times.
After #457 and #458, the app decimates and displays a minimap overview, but still loads everything into memory first.
Goal
- Initial load: Stream through DB rows once, building a low-resolution overview without holding all data in memory
- Zoom in: Re-query the DB for only the visible time window, LTTB-decimate to ~5000 points — full fidelity in small windows (e.g., 5 seconds of a 48-hour session shows all 5000 data points)
- Memory stays bounded regardless of session size
Prior work
Implementation plan
1. Add composite DB index
Add (LoggingSessionID, TimestampTicks) index to DataSamples for efficient range queries. Use CREATE INDEX IF NOT EXISTS since the app uses Database.EnsureCreated(). If index creation fails, log a warning and continue — queries still work, just slower.
2. New SessionDataService
DB query abstraction using IDbContextFactory<LoggingContext>:
GetChannelMetadata(sessionId) — distinct channels with color/type
GetSessionBounds(sessionId) — total count, min/max ticks
StreamSamples(sessionId) — IEnumerable via AsEnumerable() for streaming (no ToList())
QueryTimeWindow(sessionId, minTicks, maxTicks, CancellationToken) — range query for zoom
Failed zoom queries should log the error and keep displaying current data — not crash.
3. New StreamingOverviewBuilder
Fed row-by-row during initial streaming pass, accumulates in bounded memory:
- 800-bucket MinMax per channel for minimap (~1600 points)
- Every-Nth-sample pre-filter → LTTB to 5000 points for main plot overview
4. Rewrite DisplayLoggingSession
- Small sessions (< 50K total samples across all channels): Load directly as today
- Large sessions: Stream once through
StreamingOverviewBuilder, populate minimap + main plot from builder output. Eliminates _allSessionPoints.
5. Debounced zoom re-query
Extend OnMainTimeAxisChanged (from #458):
- 200ms debounce timer on axis changes
- Convert visible range (ms) back to ticks
- Query visible window via
SessionDataService.QueryTimeWindow()
- LTTB-decimate result to 5000 points per channel
- Cancel stale queries via
CancellationTokenSource — dispose previous CTS when creating a new one on each zoom
6. Reset zoom → instant overview
Use cached overview data immediately, no DB query needed.
Acceptance criteria
Problem
When viewing stored logging sessions with large datasets (e.g., 48 hours at 1000hz = 172M+ samples per channel), the app loads all samples into memory before rendering. This doesn't scale — it causes excessive memory usage and slow load times.
After #457 and #458, the app decimates and displays a minimap overview, but still loads everything into memory first.
Goal
Prior work
DataPointDecimator), reused for zoom re-queryMinMaxDownsampler, becomes the full-session context viewImplementation plan
1. Add composite DB index
Add
(LoggingSessionID, TimestampTicks)index toDataSamplesfor efficient range queries. UseCREATE INDEX IF NOT EXISTSsince the app usesDatabase.EnsureCreated(). If index creation fails, log a warning and continue — queries still work, just slower.2. New
SessionDataServiceDB query abstraction using
IDbContextFactory<LoggingContext>:GetChannelMetadata(sessionId)— distinct channels with color/typeGetSessionBounds(sessionId)— total count, min/max ticksStreamSamples(sessionId)—IEnumerableviaAsEnumerable()for streaming (noToList())QueryTimeWindow(sessionId, minTicks, maxTicks, CancellationToken)— range query for zoomFailed zoom queries should log the error and keep displaying current data — not crash.
3. New
StreamingOverviewBuilderFed row-by-row during initial streaming pass, accumulates in bounded memory:
4. Rewrite
DisplayLoggingSessionStreamingOverviewBuilder, populate minimap + main plot from builder output. Eliminates_allSessionPoints.5. Debounced zoom re-query
Extend
OnMainTimeAxisChanged(from #458):SessionDataService.QueryTimeWindow()CancellationTokenSource— dispose previous CTS when creating a new one on each zoom6. Reset zoom → instant overview
Use cached overview data immediately, no DB query needed.
Acceptance criteria
StreamingOverviewBuilderandSessionDataService