Improve conversation query performance.

For the conversation query at least, we stopped joining on the
attachments tables, and instead get attachments on a page-by-page basis.
This commit is contained in:
Greyson Parrelli
2021-06-16 18:26:24 -04:00
committed by Cody Henthorne
parent 263ddb0d1e
commit fa26fb6b8b
6 changed files with 259 additions and 107 deletions

View File

@@ -9,14 +9,17 @@ import com.annimon.stream.Stream;
import org.signal.core.util.logging.Log;
import org.signal.paging.PagedDataSource;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.conversation.ConversationData.MessageRequestData;
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.model.InMemoryMessageRecord;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.Util;
import java.util.ArrayList;
import java.util.Collection;
@@ -24,6 +27,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Core data source for loading an individual conversation.
@@ -58,16 +62,18 @@ class ConversationDataSource implements PagedDataSource<ConversationMessage> {
@Override
public @NonNull List<ConversationMessage> load(int start, int length, @NonNull CancellationSignal cancellationSignal) {
Stopwatch stopwatch = new Stopwatch("load(" + start + ", " + length + "), thread " + threadId);
MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context);
List<MessageRecord> records = new ArrayList<>(length);
MentionHelper mentionHelper = new MentionHelper();
Stopwatch stopwatch = new Stopwatch("load(" + start + ", " + length + "), thread " + threadId);
MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context);
List<MessageRecord> records = new ArrayList<>(length);
MentionHelper mentionHelper = new MentionHelper();
AttachmentHelper attachmentHelper = new AttachmentHelper();
try (MmsSmsDatabase.Reader reader = MmsSmsDatabase.readerFor(db.getConversation(threadId, start, length))) {
MessageRecord record;
while ((record = reader.getNext()) != null && !cancellationSignal.isCanceled()) {
records.add(record);
mentionHelper.add(record);
attachmentHelper.add(record);
}
}
@@ -85,6 +91,12 @@ class ConversationDataSource implements PagedDataSource<ConversationMessage> {
stopwatch.split("mentions");
attachmentHelper.fetchAttachments(context);
stopwatch.split("attachments");
records = attachmentHelper.buildUpdatedModels(context, records);
List<ConversationMessage> messages = Stream.of(records)
.map(m -> ConversationMessageFactory.createWithUnresolvedData(context, m, mentionHelper.getMentions(m.getId())))
.toList();
@@ -114,4 +126,37 @@ class ConversationDataSource implements PagedDataSource<ConversationMessage> {
return messageIdToMentions.get(id);
}
}
private static class AttachmentHelper {
private Collection<Long> messageIds = new LinkedList<>();
private Map<Long, List<DatabaseAttachment>> messageIdToAttachments = new HashMap<>();
void add(MessageRecord record) {
if (record.isMms()) {
messageIds.add(record.getId());
}
}
void fetchAttachments(Context context) {
messageIdToAttachments = DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessages(messageIds);
}
@NonNull List<MessageRecord> buildUpdatedModels(@NonNull Context context, @NonNull List<MessageRecord> records) {
return records.stream()
.map(record -> {
if (record instanceof MediaMmsMessageRecord) {
List<DatabaseAttachment> attachments = messageIdToAttachments.get(record.getId());
if (Util.hasItems(attachments)) {
return ((MediaMmsMessageRecord) record).withAttachments(context, attachments);
}
}
return record;
})
.collect(Collectors.toList());
}
}
}