feat: dynamic buffer panels, session persistence, counter improvements#5
Merged
feat: dynamic buffer panels, session persistence, counter improvements#5
Conversation
- Detect SF_BUFFER storages from uscope schema during trace parsing - Create one BufferPanel per detected buffer storage (dynamic count) - Remove hardcoded QueueKind enum and three fixed queue panel fields - BufferPanel shows buffer metadata (name, capacity, fields) at cursor - Empty dock when trace has no buffer declarations - QueuePanel kept as dead code for reference (no longer imported) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…stress test - Add counter_count config to GeneratorConfig - Generate counters with varied rates and burstiness patterns - 20 named counters (committed_insns, dcache_misses, etc.) + numbered overflow - Cmd+G now generates 1M instructions with 100 counters for perf testing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New uscope crate: gen-uscope — standalone binary that generates .uscope files with configurable instruction count, counter count, stages, fetch width, and RNG seed - Usage: gen-uscope -o out.uscope -n 1000000 --counters 100 - Also adds counter_count to Reflex's GeneratorConfig (used by Cmd+G) - 1M instructions + 100 counters generates in ~4s (179 MB) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…loading) - Wrap PipelineTrace in Arc to eliminate per-frame deep clones (~8GB of data was being cloned 120x/sec in paint closures) - Remove Konata parser, TraceSource trait, and TraceRegistry (use konata2uscope converter for Konata traces) - Direct parse_uscope() calls replace registry indirection - 9 Konata-specific tests removed; 21 remaining tests pass Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion) - parse_uscope() now returns (PipelineTrace, Reader, SegmentIndex) - TraceState stores Option<Reader> and SegmentIndex for future lazy queries - SegmentIndex maps segments to (start_cycle, end_cycle) ranges with segments_in_range() for viewport-to-segment lookups - Trace still loads eagerly — Reader is preserved for Phase 3+ use Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instructions are no longer parsed upfront. open_uscope() reads metadata and counters only (fast). Instructions load on demand when the viewport scrolls to a new region via ensure_segments_loaded(). - open_uscope() returns metadata-only PipelineTrace + Reader + context - load_segments() parses instructions for specific segment indices - ensure_segments_loaded() in paint callback loads visible + buffer zone - SegmentIndex.segments_in_range() finds segments for a cycle range - PipelineTrace.merge_loaded() appends and re-sorts instructions - max_cycle_override reports full trace extent before instructions load - Generator traces use eager path (no Reader) - No segment eviction yet (accumulates loaded data) - New test: lazy_load_sample_uscope verifies lazy vs eager parity Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ensure_segments_loaded: after merge_loaded re-sorts instructions, find the row matching the anchor cycle and restore scroll_row (prevents viewport jumping to random row after sort) - Minimap click: call ensure_segments_loaded for the clicked region BEFORE searching for instructions there (fixes jump-to-row-0 when clicking on an unloaded region) - Both fixes ensure clamp() is called after max_row update Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous fix forcefully reset scroll_row every time new segments loaded (via ensure_segments_loaded), which fought with the user's scroll input and caused "stuck" scrolling. Now scroll_row is only repositioned on the first load (0 → N rows transition). Normal segment loading preserves the user's current scroll position. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…amples CounterSeries now stores sparse (cycle, cumulative_value) pairs — one per segment boundary — instead of dense per-cycle Vec<u64>. This reduces counter memory from ~8GB (100 counters × 10M cycles) to ~240KB. Query methods (counter_value_at, counter_rate_at, counter_delta_at, counter_downsample_minmax) updated to work with sparse data via binary search and interpolation. This is a stepping stone — the uscope format will be extended with proper counter mipmaps next. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Compute counter mipmaps via uscope::summary::compute_counter_summary() during trace open (replays segments once, builds multi-level min/max pyramids) - Add TraceState::counter_downsample() that picks the right mipmap level based on requested resolution, falls back to sparse samples - Counter panel sparklines, heatmap, minimap trendline, and timeline overlay all use mipmap queries instead of O(cycles) scans - Counter overview rendering is now O(bucket_count) regardless of trace size Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- gen-uscope calls embed_counter_summary() after close() to write mipmaps as SECTION_COUNTER_SUMMARY inside the .uscope file - Reader auto-loads mipmaps during open() from the embedded section - Reflex uses embedded mipmaps if present, falls back to compute on load - Removed sidecar file approach entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oll loading - Minimap: render ALL cursors, not just the active one - Minimap: pipeline viewport indicator is now a 4px rounded yellow bar at the bottom with better visibility - Scroll loading: when scrolling past loaded instructions, extrapolate the cycle range from instruction density to load more segments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cator - auto_follow: snap directly when stages are >2x viewport width away from current scroll position (fixes stages not being visible after vertical scroll through lazily-loaded data) - auto_follow: considers both min and max cycle of visible rows' stages - Pipeline indicator on minimap: increased min width to 8px and height to 5px for better visibility on large traces Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…s bar - Count total instructions during open_uscope() segment replay pass (counts DA_SLOT_SET on entities storage — zero extra I/O) - Store as total_instruction_count on PipelineTrace - Status bar shows "12'328/1'000'000 instrs" when lazily loaded - Add fmt_num() for apostrophe thousand separators (e.g., 1'000'000) - Applied to instrs, cycles, rows, cursor position in status bar TODO: Make total_instruction_count a first-class field in the uscope CPU protocol header instead of counting during replay. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- load_trace_lazy: set max_row from total_instruction_count (not 0) so the scrollbar represents the full 1M-instruction trace - ensure_segments_loaded: don't reduce max_row to loaded count - Scroll extrapolation: use global instruction-to-cycle ratio (row / total_instrs * max_cycle) for better segment loading when scrolling past loaded regions - Fixes: viewport appearing "at the end" with only 24K loaded Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build a lightweight (first_cycle, entity_id) index for every instruction during open_uscope() — 12 bytes × 1M instructions = 12MB. Sorted by first_cycle, this provides exact row-to-cycle mapping for lazy loading. - Row N now corresponds to the Nth instruction in the trace globally - Scrolling to row 500K loads segments at the correct cycle - max_row = total_instruction_count (full trace coverage) - No more estimation/extrapolation — instruction_index[row] gives the exact target cycle for segment loading Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename CounterSummary → TraceSummary with instruction density mipmap - open_uscope() no longer replays segments — reads metadata + summary only - Remove instruction_index from PipelineTrace (was 12MB for 1M instructions) - Row-to-cycle mapping via TraceSummary.row_to_cycle() density prefix-sum - total_instruction_count from TraceSummary.total_instructions - Counter data from TraceSummary mipmaps (no sparse samples needed) - Build SegmentIndex from file segment table without replay - Handles missing summary gracefully (live/old traces) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The row-to-cycle mapping was always applied, even when scroll_row=0. This caused load_start=min(clicked_cycle, row_to_cycle(0))=0, loading ALL segments from the start to the clicked position on the first click. Now only uses row-to-cycle mapping when actually scrolled past loaded rows (row_end > loaded row_count). Normal minimap clicks load only the segments around the clicked cycle — 1-2 segments, not the entire trace. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Trendline uses uniform ACCENT at alpha 0.35 (was bright/dim split that created visible two-tone background) - Remove dim overlays and separate bright/dim trendline painting - Skip compute_trace_summary for large files (>100 segments) to avoid blocking on open - Remove unused counter_downsample_overview method Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ge files" This reverts commit 9aeca22.
…races" This reverts commit 5925256.
…pmap fix - Small traces (≤32K cycles): extract per-cycle counter samples at file open via segment replay for precise sparklines and minimap - Large traces: use mipmap (no upfront replay cost) - Fix f64 truncation in mipmap downsample (was accumulating as u64, truncating fractional sums to 0) - Segment loading also extracts counter samples incrementally - Minimap cache invalidates when new counter samples arrive Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Save viewport position, cursor positions, counter display modes, dock layout preset, and active tab on quit (Cmd+Q). Restore on next open. Session file stored alongside trace as .filename.session (JSON), with fallback to ~/.config/reflex/sessions/ for read-only directories. Graceful degradation: corrupt/missing sessions silently ignored. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures session is persisted even if the window is closed without Cmd+Q (e.g., clicking the red X button). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds dock_open field to session file so buffer panel visibility persists across restarts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Register all panels (Pipeline, Counter, Buffer, Log) with gpui-component's PanelRegistry for DockArea::load() support - BufferPanel::dump() now includes buffer_idx in PanelInfo - Session file includes full dock_layout (DockAreaState as JSON) - On restore, DockArea::load() reconstructs exact panel arrangement - Falls back to default layout if dock_layout is missing/corrupt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Check StorageState.valid[] before reading slot data in query_buffer_state(). Sparse storages (buffers) track per-slot validity via DA_SLOT_SET/DA_SLOT_CLEAR. Without this check, invalid slots with leftover data from previous allocations appeared occupied. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show all non-special fields after disasm in buffer slot rows. Skips entity_id (shown as disasm), Bool fields (shown as ready dot), and zero-valued fields to reduce clutter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Look up entity fields from the entities storage for each occupied buffer slot. Shows all non-zero entity fields (skipping entity_id and pc which are already shown as disasm) after the instruction text. This makes structured entity annotations like rbid, fpb_id, iq_id, dq_id, ready_time_ps visible in the buffer panel rows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… control - Column headers: Slot | Stage | Instruction | entity fields - Fixed-width columns with consistent alignment - Horizontal scroll (no text wrapping) - Field formatting: inst_bits as hex, ready_time_ps as cycles - Default-hidden fields (inst_bits) - Hidden columns persisted in session file per buffer name - Entity field names discovered dynamically from uscope schema Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instructions with RetireStatus::Flushed are dimmed in all buffer panel columns (slot, stage, disasm, entity fields) to visually distinguish them from active in-flight instructions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
counter_downsample_minmax used integer division for per-cycle rates, causing intervals with rate < 1/cycle (e.g., 1 event over 6 cycles) to display as 0. Now uses f64 rates throughout and scales to integer range at the end. Fixes sparklines not showing early counter activity. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The interval from cycle 0 to the first counter sample was assigned rate = first_value / first_cycle, spreading the first event's value across the inactive pre-reset period. Now correctly uses rate 0 for this interval since no counter events fire before the first sample. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When counter display mode is Delta (Δ), the sparkline now shows per-bucket absolute change instead of rate. Total and Rate modes continue to show the rate-based downsample. Click a counter header to cycle through T → R → Δ and see the sparkline update. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cap delta mode bucket count to cycle range so each bucket covers at least 1 cycle. Prevents thin spikes where only the bucket straddling a cycle boundary gets the delta while others show zero. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cap rate/total mode bucket count to cycle range, same as delta mode. With more buckets than cycles, integer truncation caused most buckets to have start == end, matching no intervals and showing as gaps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
209fc81 to
15a5387
Compare
- Extract BufferSlot type alias for complex tuple type - Use .rev().find() instead of .filter().last() on DoubleEndedIterator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test expected raw integer rates but counter_downsample_minmax now returns f64-scaled values. Updated to check relative ratios instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DockArea::load() can hang when session files reference panels from a different trace (mismatched buffer count). Disable full layout restore for now — placement + open state are still restored. The dock rebuilds with correct panels for the current trace. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eeks away read_segment_table seeks to the segments section offset, leaving the file cursor at an unknown position. The section table loop then re-reads the same entries forever. Fix: save cursor position before the call and re-seek to the next entry after. Also add a max iteration guard as defensive coding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
Major feature branch adding dynamic buffer visualization, session persistence, and counter display improvements.
Dynamic Buffer Panels
SF_BUFFERstorages)Reader::state_at()inst_bitsas hex,ready_time_psas cyclesStorageState.valid[])Session Persistence
.filename.session) with config dir fallbackPanelRegistry(dump()/load())Counter Display Fixes
load_segments()Other
paint_bars()renderer for all counter visualizationsTest Plan