Add members to chats in a single sql transation (#3780)

This esp. speeds up receive_imf a bit when we recreate the member list (recreate_member_list == true).

It's a preparation for https://github.com/deltachat/deltachat-core-rust/issues/3768, which will be a one-line-fix, but recreate the member list more often, so that we want to optimize this case a bit.

It also adds a benchmark for this case. It's not that easy to make the benchmark non-flaky, but by closing all other programs and locking the CPU to 1.5GHz it worked. It is consistently a few percent faster than ./without-optim:

```
Receive messages/Receive 100 Chat-Group-Member-{Added|Removed} messages                                                                            
                        time:   [52.257 ms 52.569 ms 52.941 ms]
                        change: [-3.5301% -2.6181% -1.6697%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  4 (4.00%) high mild
  3 (3.00%) high severe
```
This commit is contained in:
Hocuri
2022-11-29 20:37:56 +01:00
committed by GitHub
parent f6a502a8e3
commit 6c4d919828
8 changed files with 127 additions and 57 deletions

View File

@@ -2563,7 +2563,7 @@ pub async fn create_group_chat(
let chat_id = ChatId::new(u32::try_from(row_id)?);
if !is_contact_in_chat(context, chat_id, ContactId::SELF).await? {
add_to_chat_contacts_table(context, chat_id, ContactId::SELF).await?;
add_to_chat_contacts_table(context, chat_id, &[ContactId::SELF]).await?;
}
context.emit_msgs_changed_without_ids();
@@ -2624,19 +2624,25 @@ pub async fn create_broadcast_list(context: &Context) -> Result<ChatId> {
Ok(chat_id)
}
/// Adds a contact to the `chats_contacts` table.
/// Adds contacts to the `chats_contacts` table.
pub(crate) async fn add_to_chat_contacts_table(
context: &Context,
chat_id: ChatId,
contact_id: ContactId,
contact_ids: &[ContactId],
) -> Result<()> {
context
.sql
.execute(
"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)",
paramsv![chat_id, contact_id],
)
.transaction(move |transaction| {
for contact_id in contact_ids {
transaction.execute(
"INSERT OR IGNORE INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)",
paramsv![chat_id, contact_id],
)?;
}
Ok(())
})
.await?;
Ok(())
}
@@ -2738,7 +2744,7 @@ pub(crate) async fn add_contact_to_chat_ex(
if is_contact_in_chat(context, chat_id, contact_id).await? {
return Ok(false);
}
add_to_chat_contacts_table(context, chat_id, contact_id).await?;
add_to_chat_contacts_table(context, chat_id, &[contact_id]).await?;
}
if chat.typ == Chattype::Group && chat.is_promoted() {
msg.viewtype = Viewtype::Text;