perf(ui): dedupe time-ago + allocation-free case-insensitive filter (audit #1-3)
Per-frame hot paths in the immediate-mode UI were allocating needlessly:
- Address filtering in the balance tab rebuilt a std::string filter per address AND
containsIgnoreCase() lower-cased two fresh copies per call — ~6×N allocations/frame
on large wallets. New util::containsIgnoreCase(string_view, string_view) is
allocation-free, and the filter is now built once outside the loop.
- Four duplicated "time ago" implementations (balance_tab_helpers, balance_recent_tx,
send_tab, transactions_tab) are consolidated into util::formatTimeAgo (localized long
form) + util::formatTimeAgoShort (compact "5s ago"), preserving each call site's exact
display style. Both use snprintf, no per-row string concatenation.
- The send-tab address-suggestion scan (a walk over the whole tx list) is memoized on the
typed text + tx count, so it no longer recomputes every frame while the user pauses.
New src/util/text_format.{h,cpp}; the two existing containsIgnoreCase/timeAgo definitions
now delegate to it. Added to both the app and test targets (test target also gains i18n.cpp,
which text_format's localized path needs).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
28
src/util/text_format.h
Normal file
28
src/util/text_format.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// DragonX Wallet - ImGui Edition
|
||||
// Copyright 2024-2026 The Hush Developers
|
||||
// Released under the GPLv3
|
||||
//
|
||||
// Small shared text helpers used across the immediate-mode UI. Centralised here so the per-frame
|
||||
// hot paths use one allocation-free implementation instead of several copies.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace dragonx {
|
||||
namespace util {
|
||||
|
||||
// Localized relative time, e.g. "5 minutes ago" (via i18n). Empty when timestamp <= 0.
|
||||
std::string formatTimeAgo(std::int64_t timestamp);
|
||||
|
||||
// Compact, non-localized relative time for tight UI: "5s ago" / "3m ago" / "2h ago" / "4d ago".
|
||||
std::string formatTimeAgoShort(std::int64_t timestamp);
|
||||
|
||||
// Case-insensitive substring test that does NOT allocate (unlike lower-casing copies + find).
|
||||
// An empty needle matches everything. Safe for per-frame filtering of large lists.
|
||||
bool containsIgnoreCase(std::string_view haystack, std::string_view needle);
|
||||
|
||||
} // namespace util
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user