perf: memoize per-frame render hot paths (console, transactions, recent lists)

Immediate-mode render functions re-run every frame; these rebuilt O(N)
state each time even when nothing changed. From a 6-lens perf audit, each
finding verified on a hot-path basis:

- Console: ConsoleModel gains revision(); the full-model filter scan and the
  glyph-by-glyph text-layout pass (BuildConsoleLayout) rebuild only when the
  model / filter / wrap-width / zoom change — previously it re-shaped up to
  10,000 lines every frame even when idle/scrolled. clear() force-invalidates
  the memo mid-render (no OOB on the just-emptied visible set).
- Transactions: the summary-card totals memoize behind the tab's existing
  FNV-1a fingerprint (also folds away a now-duplicate O(N) display-key pass).
- Send / Receive recent lists: early-exit the prefix scan (state.transactions
  is kept newest-first) instead of filtering the whole tx history every frame.
- network_refresh_service: O(new x total) txid find-and-replace -> hash map.
- Sidebar unconfirmed-tx badge cached on last_tx_update + tx count; the
  daemon-memory probe (/proc scan on Linux, popen on macOS) throttled to ~1.5s.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 22:55:04 -05:00
co-authored by Claude Opus 4.8
parent 0a042df8e0
commit d9fa00bb38
9 changed files with 238 additions and 104 deletions
+6
View File
@@ -22,6 +22,7 @@
#include "console_channel.h"
#include <cstddef>
#include <cstdint>
#include <deque>
#include <mutex>
#include <string>
@@ -76,11 +77,16 @@ public:
const ConsoleModelLine& operator[](std::size_t i) const { return lines_[i]; }
const ConsoleModelLine& back() const { return lines_.back(); }
// Monotonic counter bumped whenever the visible deque changes (drain added/evicted lines, clear,
// fold toggle). The view memoizes its per-frame filter + text-layout passes against this.
std::uint64_t revision() const { return revision_; }
private:
const std::size_t max_lines_;
std::deque<ConsoleModelLine> lines_; // visible model — main thread only
std::vector<ConsoleModelLine> pending_; // guarded by ingest_mutex_
std::mutex ingest_mutex_;
std::uint64_t revision_ = 0;
};
} // namespace ui