Perf: Insert outgoing message into conversation before save completes.

This was a huge savings - e.g. 50-70% of the time between tapping send and
rendering the message takes place in the save/postWriteTransaction blocks
This commit is contained in:
Michael Kirk 2018-12-13 09:52:15 -07:00
parent 176543d2af
commit 668cc22af3
6 changed files with 42 additions and 6 deletions

View File

@ -3887,13 +3887,14 @@ typedef enum : NSUInteger {
inThread:self.thread
quotedReplyModel:self.inputToolbar.quotedReply];
} else {
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
message = [ThreadUtil enqueueMessageWithText:text
inThread:self.thread
quotedReplyModel:self.inputToolbar.quotedReply
transaction:transaction];
}];
}
[self.conversationViewModel appendUnsavedOutgoingMessage:message];
[self messageWasSent:message];

View File

@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ConversationStyle;
@class ConversationViewModel;
@class OWSQuotedReplyModel;
@class TSOutgoingMessage;
@class TSThread;
@class ThreadDynamicInteractions;
@ -101,6 +102,7 @@ typedef NS_ENUM(NSUInteger, ConversationUpdateItemType) {
- (BOOL)canLoadMoreItems;
- (nullable NSIndexPath *)ensureLoadWindowContainsQuotedReply:(OWSQuotedReplyModel *)quotedReply;
- (void)appendUnsavedOutgoingMessage:(TSOutgoingMessage *)outgoingMessage;
@end

View File

@ -12,6 +12,7 @@
#import <SignalMessaging/OWSContactOffersInteraction.h>
#import <SignalMessaging/OWSContactsManager.h>
#import <SignalMessaging/OWSUnreadIndicator.h>
#import <SignalMessaging/SignalMessaging-Swift.h>
#import <SignalMessaging/ThreadUtil.h>
#import <SignalServiceKit/OWSBlockingManager.h>
#import <SignalServiceKit/OWSPrimaryStorage.h>
@ -1491,6 +1492,33 @@ static const int kYapDatabaseRangeMinLength = 0;
return !hasError;
}
- (void)appendUnsavedOutgoingMessage:(TSOutgoingMessage *)outgoingMessage
{
// id<ConversationViewItem> viewItem = [[OutgoingUnsavedConversationViewItem alloc] initWithOutgoingMessage:outgoingMessage];
__block ConversationInteractionViewItem *viewItem;
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
viewItem =
[[ConversationInteractionViewItem alloc] initWithInteraction:outgoingMessage
isGroupThread:self.thread.isGroupThread
transaction:transaction
conversationStyle:self.delegate.conversationStyle];
}];
ConversationUpdateItem *updateItem = [[ConversationUpdateItem alloc] initWithUpdateItemType:ConversationUpdateItemType_Insert
oldIndex:0
newIndex:self.viewItems.count
viewItem:viewItem];
NSMutableArray<id <ConversationViewItem>> *viewItems = [self.viewItems mutableCopy];
[viewItems addObject:viewItem];
self.viewItems = viewItems;
ConversationUpdate *conversationUpdate = [[ConversationUpdate alloc] initWithConversationUpdateType:ConversationUpdateType_Diff
updateItems:@[updateItem]
shouldAnimateUpdates:NO];
[self.delegate conversationViewModelDidUpdate:conversationUpdate];
}
// Whenever an interaction is modified, we need to reload it from the DB
// and update the corresponding view item.
- (void)reloadInteractionForViewItem:(id<ConversationViewItem>)viewItem

View File

@ -47,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (TSOutgoingMessage *)enqueueMessageWithText:(NSString *)text
inThread:(TSThread *)thread
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
transaction:(YapDatabaseReadWriteTransaction *)transaction;
transaction:(YapDatabaseReadTransaction *)transaction;
+ (TSOutgoingMessage *)enqueueMessageWithAttachment:(SignalAttachment *)attachment
inThread:(TSThread *)thread

View File

@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (TSOutgoingMessage *)enqueueMessageWithText:(NSString *)text
inThread:(TSThread *)thread
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
transaction:(YapDatabaseReadWriteTransaction *)transaction
transaction:(YapDatabaseReadTransaction *)transaction
{
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId transaction:transaction];
@ -82,9 +82,13 @@ NS_ASSUME_NONNULL_BEGIN
expiresInSeconds:expiresInSeconds
quotedMessage:[quotedReplyModel buildQuotedMessageForSending]];
[message saveWithTransaction:transaction];
[self.messageSenderJobQueue addMessage:message transaction:transaction];
[BenchManager benchWithTitle:@"Saving outgoing message" block:^{
// To avoid blocking the send flow, we disapatch an async write from within this read transaction
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull writeTransaction) {
[message saveWithTransaction:writeTransaction];
[self.messageSenderJobQueue addMessage:message transaction:writeTransaction];
}];
}];
return message;
}

View File

@ -38,6 +38,7 @@ public class MessageSenderJobQueue: NSObject, JobQueue {
@objc(addMessage:transaction:)
public func add(message: TSOutgoingMessage, transaction: YapDatabaseReadWriteTransaction) {
message.save(with: transaction)
self.add(message: message, removeMessageAfterSending: false, transaction: transaction)
}