melib: use Vec instead of SmallVec for search results

There was no point in using SmallVec with this large a size; it was
32768 bytes, or 32KiB. Let's allocate that to the heap instead.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
This commit is contained in:
Manos Pitsidianakis 2024-11-21 11:37:22 +02:00
parent 5af6e059b7
commit 567270e177
No known key found for this signature in database
GPG key ID: 7729C7707F7E09D0
14 changed files with 28 additions and 62 deletions

View file

@ -46,7 +46,6 @@ use melib::{
utils::{fnmatch::Fnmatch, futures::sleep, random, shellexpand::ShellExpandTrait},
Contacts, SortField, SortOrder,
};
use smallvec::SmallVec;
#[cfg(feature = "sqlite3")]
use crate::command::actions::AccountAction;
@ -1286,7 +1285,7 @@ impl Account {
search_term: &str,
_sort: (SortField, SortOrder),
mailbox_hash: MailboxHash,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
let query = melib::search::Query::try_from(search_term)?;
match self.settings.conf.search_backend {
#[cfg(feature = "sqlite3")]
@ -1303,7 +1302,7 @@ impl Account {
.search(query, Some(mailbox_hash))
} else {
use melib::search::QueryTrait;
let mut ret = SmallVec::new();
let mut ret = Vec::with_capacity(512);
let envelopes = self.collection.envelopes.read().unwrap();
for &env_hash in self.collection.get_mailbox(mailbox_hash).iter() {
if let Some(envelope) = envelopes.get(&env_hash) {

View file

@ -1011,13 +1011,7 @@ pub trait ListingTrait: Component {
fn prev_entry(&mut self, context: &mut Context);
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context);
fn filter(
&mut self,
_filter_term: String,
_results: SmallVec<[EnvelopeHash; 512]>,
_context: &Context,
) {
}
fn filter(&mut self, _filter_term: String, _results: Vec<EnvelopeHash>, _context: &Context) {}
fn unfocused(&self) -> bool;
fn view_area(&self) -> Option<Area>;
fn set_modifier_active(&mut self, _new_val: bool);

View file

@ -143,9 +143,9 @@ pub struct CompactListing {
rows: RowsState<(ThreadHash, EnvelopeHash)>,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
search_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
#[allow(clippy::type_complexity)]
select_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
select_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
filter_term: String,
filtered_selection: Vec<ThreadHash>,
filtered_order: HashMap<ThreadHash, usize>,
@ -764,12 +764,7 @@ impl ListingTrait for CompactListing {
context.dirty_areas.push_back(area);
}
fn filter(
&mut self,
filter_term: String,
results: SmallVec<[EnvelopeHash; 512]>,
context: &Context,
) {
fn filter(&mut self, filter_term: String, results: Vec<EnvelopeHash>, context: &Context) {
if filter_term.is_empty() {
return;
}
@ -1374,7 +1369,7 @@ impl CompactListing {
fn select(
&mut self,
search_term: &str,
results: Result<SmallVec<[EnvelopeHash; 512]>>,
results: Result<Vec<EnvelopeHash>>,
context: &mut Context,
) {
let account = &context.accounts[&self.cursor_pos.0];

View file

@ -118,7 +118,7 @@ pub struct ConversationsListing {
error: std::result::Result<(), String>,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
search_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
filter_term: String,
filtered_selection: Vec<ThreadHash>,
filtered_order: HashMap<ThreadHash, usize>,
@ -521,12 +521,7 @@ impl ListingTrait for ConversationsListing {
context.dirty_areas.push_back(area);
}
fn filter(
&mut self,
filter_term: String,
results: SmallVec<[EnvelopeHash; 512]>,
context: &Context,
) {
fn filter(&mut self, filter_term: String, results: Vec<EnvelopeHash>, context: &Context) {
if filter_term.is_empty() {
return;
}

View file

@ -140,9 +140,9 @@ pub struct PlainListing {
data_columns: DataColumns<5>,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
search_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
#[allow(clippy::type_complexity)]
select_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
select_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
filter_term: String,
filtered_selection: Vec<EnvelopeHash>,
filtered_order: HashMap<EnvelopeHash, usize>,
@ -502,12 +502,7 @@ impl ListingTrait for PlainListing {
context.dirty_areas.push_back(area);
}
fn filter(
&mut self,
filter_term: String,
results: SmallVec<[EnvelopeHash; 512]>,
context: &Context,
) {
fn filter(&mut self, filter_term: String, results: Vec<EnvelopeHash>, context: &Context) {
if filter_term.is_empty() {
return;
}
@ -1286,7 +1281,7 @@ impl PlainListing {
fn select(
&mut self,
search_term: &str,
results: Result<SmallVec<[EnvelopeHash; 512]>>,
results: Result<Vec<EnvelopeHash>>,
context: &mut Context,
) {
let account = &context.accounts[&self.cursor_pos.0];

View file

@ -139,9 +139,9 @@ pub struct ThreadListing {
color_cache: ColorCache,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
search_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
#[allow(clippy::type_complexity)]
select_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
select_job: Option<(String, JoinHandle<Result<Vec<EnvelopeHash>>>)>,
filter_term: String,
filtered_selection: Vec<ThreadHash>,
filtered_order: HashMap<ThreadHash, usize>,
@ -671,12 +671,7 @@ impl ListingTrait for ThreadListing {
}
}
fn filter(
&mut self,
filter_term: String,
results: SmallVec<[EnvelopeHash; 512]>,
context: &Context,
) {
fn filter(&mut self, filter_term: String, results: Vec<EnvelopeHash>, context: &Context) {
if filter_term.is_empty() {
return;
}
@ -1224,7 +1219,7 @@ impl ThreadListing {
fn select(
&mut self,
search_term: &str,
results: Result<SmallVec<[EnvelopeHash; 512]>>,
results: Result<Vec<EnvelopeHash>>,
context: &mut Context,
) {
let account = &context.accounts[&self.cursor_pos.0];

View file

@ -37,7 +37,6 @@ use melib::{
utils::sqlite3::{rusqlite::params, DatabaseDescription},
Error, Result, ResultIntoError, SortField, SortOrder,
};
use smallvec::SmallVec;
const DB: DatabaseDescription = DatabaseDescription {
name: "index.db",
@ -401,7 +400,7 @@ impl AccountCache {
acc_name: Arc<str>,
query: Query,
(sort_field, sort_order): (SortField, SortOrder),
) -> Result<SmallVec<[EnvelopeHash; 512]>> {
) -> Result<Vec<EnvelopeHash>> {
let db_desc = DatabaseDescription {
identifier: Some(acc_name.to_string().into()),
..DB.clone()
@ -443,7 +442,7 @@ impl AccountCache {
.query_map([], |row| row.get::<_, EnvelopeHash>(0))
.map_err(Error::from)?
.map(|item| item.map_err(Error::from))
.collect::<Result<SmallVec<[EnvelopeHash; 512]>>>();
.collect::<Result<Vec<EnvelopeHash>>>();
x
})
.await

View file

@ -508,7 +508,7 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
&self,
query: crate::search::Query,
mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>>;
) -> ResultFuture<Vec<EnvelopeHash>>;
fn submit(
&self,

View file

@ -1307,7 +1307,7 @@ impl MailBackend for ImapType {
&self,
query: crate::search::Query,
mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
if mailbox_hash.is_none() {
return Err(Error::new(
"Cannot search without specifying mailbox on IMAP",
@ -1340,7 +1340,7 @@ impl MailBackend for ImapType {
for l in response.split_rn() {
if l.starts_with(b"* SEARCH") {
let uid_index = uid_store.uid_index.lock()?;
return Ok(SmallVec::from_iter(
return Ok(Vec::from_iter(
String::from_utf8_lossy(l[b"* SEARCH".len()..].trim())
.split_whitespace()
.map(UID::from_str)

View file

@ -626,7 +626,7 @@ impl MailBackend for JmapType {
&self,
q: crate::search::Query,
mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
let store = self.store.clone();
let connection = self.connection.clone();
let filter = if let Some(mailbox_hash) = mailbox_hash {

View file

@ -578,7 +578,7 @@ impl MailBackend for MaildirType {
&self,
_query: crate::search::Query,
_mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
Err(
Error::new("Search is unimplemented for the maildir backend.")
.set_kind(ErrorKind::NotImplemented),

View file

@ -1243,7 +1243,7 @@ impl MailBackend for MboxType {
&self,
_query: crate::search::Query,
_mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
Err(Error::new("Search is unimplemented for the mbox backend.")
.set_kind(ErrorKind::NotImplemented))
}

View file

@ -574,7 +574,7 @@ impl MailBackend for NntpType {
&self,
_query: crate::search::Query,
_mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
Err(Error::new("Searching is not supported for nntp backend.")
.set_kind(ErrorKind::NotSupported))
}

View file

@ -954,7 +954,7 @@ impl MailBackend for NotmuchDb {
&self,
melib_query: crate::search::Query,
mailbox_hash: Option<MailboxHash>,
) -> ResultFuture<SmallVec<[EnvelopeHash; 512]>> {
) -> ResultFuture<Vec<EnvelopeHash>> {
let database = Self::new_connection(
self.path.as_path(),
self.revision_uuid.clone(),
@ -963,7 +963,6 @@ impl MailBackend for NotmuchDb {
)?;
let mailboxes = self.mailboxes.clone();
Ok(Box::pin(async move {
let mut ret = SmallVec::new();
let mut query_s = if let Some(mailbox_hash) = mailbox_hash {
if let Some(m) = mailboxes.read().unwrap().get(&mailbox_hash) {
let mut s = m.query_str.clone();
@ -981,12 +980,7 @@ impl MailBackend for NotmuchDb {
};
melib_query.query_to_string(&mut query_s)?;
let query: Query = Query::new(&database, &query_s)?;
let iter = query.search()?;
for message in iter {
ret.push(message.env_hash());
}
Ok(ret)
Ok(query.search()?.map(|message| message.env_hash()).collect())
}))
}