Problem
`ImGuiApp::render_history_view()` (src/ui/imgui/imgui_history_view.cpp:77-80) converts "1 min"/"5 min" into a tick count using the CURRENT refresh interval:
```
if (history_window_idx_ == 0) window_ticks = 60'000 / refresh_ms;
else if (history_window_idx_ == 1) window_ticks = 300'000 / refresh_ms;
```
`HistorySample` carries a real `wall_time` timestamp, but none of `HistoryStore`'s query methods (`aggregate`, `get_series`, `get_metric_series`) use it — they all just take the last N samples from the deque. If the user changes the refresh interval mid-session, the deque contains a mix of old- and new-interval samples, and "last 1 min" (computed from the new interval) no longer corresponds to 60 real seconds for the older portion of that window.
Also noted in the same area (bundle, lower priority)
- `HistoryStore::get_series()` does a linear `std::find` through the requested `pids` for every `ProcessSample` in every `HistorySample` (history_store.cpp:89-99) — only called once per popup-open (not every tick), so real cost is modest, but an `unordered_set` would be strictly better.
- `HistoryStore::export_csv()` holds `mutex_` across the entire file-writing loop (history_store.cpp:212-244), briefly blocking the collector's next `record()` call for large histories.
Fix
Use `HistorySample::wall_time` cutoffs ("now - 60s") instead of tick counts for the window queries; snapshot `samples_` under the lock into a local copy before writing CSV files; swap the linear `std::find` for an `unordered_set`.
Problem
`ImGuiApp::render_history_view()` (src/ui/imgui/imgui_history_view.cpp:77-80) converts "1 min"/"5 min" into a tick count using the CURRENT refresh interval:
```
if (history_window_idx_ == 0) window_ticks = 60'000 / refresh_ms;
else if (history_window_idx_ == 1) window_ticks = 300'000 / refresh_ms;
```
`HistorySample` carries a real `wall_time` timestamp, but none of `HistoryStore`'s query methods (`aggregate`, `get_series`, `get_metric_series`) use it — they all just take the last N samples from the deque. If the user changes the refresh interval mid-session, the deque contains a mix of old- and new-interval samples, and "last 1 min" (computed from the new interval) no longer corresponds to 60 real seconds for the older portion of that window.
Also noted in the same area (bundle, lower priority)
Fix
Use `HistorySample::wall_time` cutoffs ("now - 60s") instead of tick counts for the window queries; snapshot `samples_` under the lock into a local copy before writing CSV files; swap the linear `std::find` for an `unordered_set`.