Compare commits

...

3 Commits

Author SHA1 Message Date
WofWca
d7a706d95b perf: make get_contacts concurrent
and `get_contacts_by_ids`.

Based on hand-testing `get_contacts` with a dummy account
with 5000 dummy contacts, this very slightly increased performance.
From 1380ms to 1325ms.
2025-02-03 15:48:53 +04:00
WofWca
aa82402151 perf: make FullChat::from_dc_chat_id concurrent
However, hand-testing get_full_chat_by_id` did not show
a significant performance increase
for a dummy group with 100 contacts.
2025-02-03 15:48:46 +04:00
WofWca
24b34106b3 perf: make Contact::from_dc_contact concurrent
However hand-testing of `get_contacts_by_ids` did not show
a significant speed increase.
2025-02-03 14:25:57 +04:00
3 changed files with 62 additions and 59 deletions

View File

@@ -1396,17 +1396,13 @@ impl CommandApi {
) -> Result<Vec<ContactObject>> {
let ctx = self.get_context(account_id).await?;
let contact_ids = Contact::get_all(&ctx, list_flags, query.as_deref()).await?;
let mut contacts: Vec<ContactObject> = Vec::with_capacity(contact_ids.len());
for id in contact_ids {
contacts.push(
ContactObject::try_from_dc_contact(
&ctx,
deltachat::contact::Contact::get_by_id(&ctx, id).await?,
)
.await?,
);
}
Ok(contacts)
let ctx_ref = &ctx;
return futures::future::try_join_all(contact_ids.into_iter().map(|id| async move {
let contact = deltachat::contact::Contact::get_by_id(ctx_ref, id).await?;
let contact_object = ContactObject::try_from_dc_contact(ctx_ref, contact).await?;
Ok(contact_object)
}))
.await;
}
async fn get_contacts_by_ids(
@@ -1416,18 +1412,15 @@ impl CommandApi {
) -> Result<HashMap<u32, ContactObject>> {
let ctx = self.get_context(account_id).await?;
let mut contacts = HashMap::with_capacity(ids.len());
for id in ids {
contacts.insert(
id,
ContactObject::try_from_dc_contact(
&ctx,
deltachat::contact::Contact::get_by_id(&ctx, ContactId::new(id)).await?,
)
.await?,
);
}
Ok(contacts)
let ctx_ref = &ctx;
return futures::future::try_join_all(ids.into_iter().map(|id| async move {
let contact =
deltachat::contact::Contact::get_by_id(ctx_ref, ContactId::new(id)).await?;
let contact_object = ContactObject::try_from_dc_contact(ctx_ref, contact).await?;
Ok((id, contact_object))
}))
.await
.map(|vec| vec.into_iter().collect());
}
async fn delete_contact(&self, account_id: u32, contact_id: u32) -> Result<()> {

View File

@@ -62,33 +62,33 @@ impl FullChat {
let rust_chat_id = ChatId::new(chat_id);
let chat = Chat::load_from_db(context, rust_chat_id).await?;
let contact_ids = get_chat_contacts(context, rust_chat_id).await?;
let past_contact_ids = get_past_chat_contacts(context, rust_chat_id).await?;
let mut contacts = Vec::with_capacity(contact_ids.len());
for contact_id in &contact_ids {
contacts.push(
ContactObject::try_from_dc_contact(
context,
Contact::get_by_id(context, *contact_id)
.await
.context("failed to load contact")?,
)
.await?,
let (
contact_ids,
past_contact_ids,
profile_image,
color,
fresh_message_counter,
ephemeral_timer,
can_send,
) = futures::try_join!(
get_chat_contacts(context, rust_chat_id),
get_past_chat_contacts(context, rust_chat_id),
chat.get_profile_image(context),
chat.get_color(context),
rust_chat_id.get_fresh_msg_cnt(context),
rust_chat_id.get_ephemeral_timer(context),
chat.can_send(context),
)?;
let contacts = futures::future::try_join_all(contact_ids.iter().map(|contact_id| async {
ContactObject::try_from_dc_contact(
context,
Contact::get_by_id(context, *contact_id)
.await
.context("failed to load contact")?,
)
}
let profile_image = match chat.get_profile_image(context).await? {
Some(path_buf) => path_buf.to_str().map(|s| s.to_owned()),
None => None,
};
let color = color_int_to_hex_string(chat.get_color(context).await?);
let fresh_message_counter = rust_chat_id.get_fresh_msg_cnt(context).await?;
let ephemeral_timer = rust_chat_id.get_ephemeral_timer(context).await?.to_u32();
let can_send = chat.can_send(context).await?;
.await
}))
.await?;
let was_seen_recently = if chat.get_type() == Chattype::Single {
match contact_ids.first() {
@@ -108,7 +108,11 @@ impl FullChat {
id: chat_id,
name: chat.name.clone(),
is_protected: chat.is_protected(),
profile_image, //BLOBS ?
//BLOBS ?
profile_image: match profile_image {
Some(path_buf) => path_buf.to_str().map(|s| s.to_owned()),
None => None,
},
archived: chat.get_visibility() == chat::ChatVisibility::Archived,
pinned: chat.get_visibility() == chat::ChatVisibility::Pinned,
chat_type: chat.get_type().to_u32().context("unknown chat type id")?,
@@ -117,14 +121,14 @@ impl FullChat {
contacts,
contact_ids: contact_ids.iter().map(|id| id.to_u32()).collect(),
past_contact_ids: past_contact_ids.iter().map(|id| id.to_u32()).collect(),
color,
color: color_int_to_hex_string(color),
fresh_message_counter,
is_contact_request: chat.is_contact_request(),
is_protection_broken: chat.is_protection_broken(),
is_device_chat: chat.is_device_talk(),
self_in_group: contact_ids.contains(&ContactId::SELF),
is_muted: chat.is_muted(),
ephemeral_timer,
ephemeral_timer: ephemeral_timer.to_u32(),
can_send,
was_seen_recently,
mailing_list_address,

View File

@@ -1,6 +1,7 @@
use anyhow::Result;
use deltachat::color;
use deltachat::context::Context;
use futures::TryFutureExt;
use serde::Serialize;
use typescript_type_def::TypeDef;
@@ -57,17 +58,22 @@ impl ContactObject {
context: &Context,
contact: deltachat::contact::Contact,
) -> Result<Self> {
let profile_image = match contact.get_profile_image(context).await? {
let profile_image = contact.get_profile_image(context).map_ok(|r| match r {
Some(path_buf) => path_buf.to_str().map(|s| s.to_owned()),
None => None,
};
let is_verified = contact.is_verified(context).await?;
let is_profile_verified = contact.is_profile_verified(context).await?;
});
let verifier_id = contact
.get_verifier_id(context)
.await?
.map(|contact_id| contact_id.to_u32());
.map_ok(|o| o.map(|contact_id| contact_id.to_u32()));
let (profile_image, is_verified, is_profile_verified, verifier_id, e2ee_avail) = futures::try_join!(
profile_image,
contact.is_verified(context),
contact.is_profile_verified(context),
verifier_id,
contact.e2ee_avail(context),
)?;
Ok(ContactObject {
address: contact.get_addr().to_owned(),
@@ -80,7 +86,7 @@ impl ContactObject {
profile_image, //BLOBS
name_and_addr: contact.get_name_n_addr(),
is_blocked: contact.is_blocked(),
e2ee_avail: contact.e2ee_avail(context).await?,
e2ee_avail,
is_verified,
is_profile_verified,
verifier_id,