perf(daemon): answer search polls with counts instead of copies
A CLI one-off search leaves its result set in the daemon until someone forgets it, and an attached TUI made that permanent state expensive: every 100ms tick asked for the search list twice, and each answer deep-cloned every result of every search under the context lock just to sum file counts - stalling the thread that stores incoming results. Worse, any active or selected search pulled its entire result set over the socket again each tick, megabytes of JSON repeating what the window already held. search.list is now backed by search_file_counts, a walk of the cache instead of a copy of it; the TUI syncs once per tick and re-fetches a result set only when the session's file count differs from what it holds. get_search_results_count reads the same summary, so get --pick first against a daemon polls a count instead of the full set, and both session kinds now count files where the local one counted peer responses.
This commit is contained in:
@@ -156,4 +156,33 @@ impl Client {
|
||||
.map(|ctx| ctx.searches.clone())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Every registered search and how many files it has collected, without
|
||||
/// copying the result sets.
|
||||
///
|
||||
/// This is the accessor to poll. [`Client::get_all_searches`] clones every
|
||||
/// result of every search, which for a popular query is megabytes per
|
||||
/// call — a caller that only wants to know what exists and whether
|
||||
/// anything new arrived reads the counts instead.
|
||||
#[must_use]
|
||||
pub fn search_file_counts(&self) -> Vec<(String, usize)> {
|
||||
self.context
|
||||
.read_safe()
|
||||
.map(|ctx| {
|
||||
ctx.searches
|
||||
.iter()
|
||||
.map(|(query, search)| {
|
||||
(
|
||||
query.clone(),
|
||||
search
|
||||
.results
|
||||
.iter()
|
||||
.map(|result| result.files.len())
|
||||
.sum(),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user