Use a single ui connection to share cache.

Primarly two things:
1. using an extension for the first time per connection is slow
2. fetching the same objects (e.g. if you leave/re-enter the same
conversation)

// FREEBIE
pull/1/head
Michael Kirk 7 years ago
parent ddd39fcd3d
commit 00f8ea4ff8

@ -80,6 +80,7 @@
#import <SignalServiceKit/OWSMessageManager.h> #import <SignalServiceKit/OWSMessageManager.h>
#import <SignalServiceKit/OWSMessageSender.h> #import <SignalServiceKit/OWSMessageSender.h>
#import <SignalServiceKit/OWSMessageUtils.h> #import <SignalServiceKit/OWSMessageUtils.h>
#import <SignalServiceKit/OWSPrimaryStorage.h>
#import <SignalServiceKit/OWSReadReceiptManager.h> #import <SignalServiceKit/OWSReadReceiptManager.h>
#import <SignalServiceKit/OWSVerificationStateChangeMessage.h> #import <SignalServiceKit/OWSVerificationStateChangeMessage.h>
#import <SignalServiceKit/SignalRecipient.h> #import <SignalServiceKit/SignalRecipient.h>
@ -312,13 +313,17 @@ typedef enum : NSUInteger {
name:UIContentSizeCategoryDidChangeNotification name:UIContentSizeCategoryDidChangeNotification
object:nil]; object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(yapDatabaseModified:) selector:@selector(uiDatabaseDidUpdateExternally:)
name:YapDatabaseModifiedNotification name:OWSUIDatabaseConnectionDidUpdateExternallyNotification
object:OWSPrimaryStorage.sharedManager.dbNotificationObject]; object:OWSPrimaryStorage.sharedManager.dbNotificationObject];
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(yapDatabaseModifiedExternally:) selector:@selector(uiDatabaseWillUpdate:)
name:YapDatabaseModifiedExternallyNotification name:OWSUIDatabaseConnectionWillUpdateNotification
object:nil]; object:OWSPrimaryStorage.sharedManager.dbNotificationObject];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(uiDatabaseDidUpdate:)
name:OWSUIDatabaseConnectionDidUpdateNotification
object:OWSPrimaryStorage.sharedManager.dbNotificationObject];
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:) selector:@selector(applicationWillEnterForeground:)
name:OWSApplicationWillEnterForegroundNotification name:OWSApplicationWillEnterForegroundNotification
@ -3114,14 +3119,7 @@ typedef enum : NSUInteger {
- (YapDatabaseConnection *)uiDatabaseConnection - (YapDatabaseConnection *)uiDatabaseConnection
{ {
NSAssert([NSThread isMainThread], @"Must access uiDatabaseConnection on main thread!"); return OWSPrimaryStorage.sharedManager.uiDatabaseConnection;
if (!_uiDatabaseConnection) {
_uiDatabaseConnection = [self.primaryStorage newDatabaseConnection];
// Increase object cache limit. Default is 250.
_uiDatabaseConnection.objectCacheLimit = 500;
[_uiDatabaseConnection beginLongLivedReadTransaction];
}
return _uiDatabaseConnection;
} }
- (YapDatabaseConnection *)editingDatabaseConnection - (YapDatabaseConnection *)editingDatabaseConnection
@ -3132,7 +3130,7 @@ typedef enum : NSUInteger {
return _editingDatabaseConnection; return _editingDatabaseConnection;
} }
- (void)yapDatabaseModifiedExternally:(NSNotification *)notification - (void)uiDatabaseDidUpdateExternally:(NSNotification *)notification
{ {
OWSAssertIsOnMainThread(); OWSAssertIsOnMainThread();
@ -3149,20 +3147,8 @@ typedef enum : NSUInteger {
} }
} }
- (void)yapDatabaseModified:(NSNotification *)notification - (void)uiDatabaseWillUpdate:(NSNotification *)notification
{ {
OWSAssertIsOnMainThread();
// Currently, we update thread and message state every time
// the database is modified. That doesn't seem optimal, but
// in practice it's efficient enough.
if (!self.shouldObserveDBModifications) {
return;
}
DDLogVerbose(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
// HACK to work around radar #28167779 // HACK to work around radar #28167779
// "UICollectionView performBatchUpdates can trigger a crash if the collection view is flagged for layout" // "UICollectionView performBatchUpdates can trigger a crash if the collection view is flagged for layout"
// more: https://github.com/PSPDFKit-labs/radar.apple.com/tree/master/28167779%20-%20CollectionViewBatchingIssue // more: https://github.com/PSPDFKit-labs/radar.apple.com/tree/master/28167779%20-%20CollectionViewBatchingIssue
@ -3173,11 +3159,21 @@ typedef enum : NSUInteger {
// view items before they are updated. // view items before they are updated.
[self.collectionView layoutIfNeeded]; [self.collectionView layoutIfNeeded];
// ENDHACK to work around radar #28167779 // ENDHACK to work around radar #28167779
}
- (void)uiDatabaseDidUpdate:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
// We need to `beginLongLivedReadTransaction` before we update our if (!self.shouldObserveDBModifications) {
// models in order to jump to the most recent commit. return;
NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction]; }
DDLogVerbose(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
NSArray *notifications = notification.userInfo[OWSUIDatabaseConnectionNotificationsKey];
OWSAssert([notifications isKindOfClass:[NSArray class]]);
[self updateBackButtonUnreadCount]; [self updateBackButtonUnreadCount];
[self updateNavigationBarSubtitleLabel]; [self updateNavigationBarSubtitleLabel];
@ -4660,10 +4656,6 @@ typedef enum : NSUInteger {
if (self.messageMappings != nil) { if (self.messageMappings != nil) {
// Before we begin observing database modifications, make sure // Before we begin observing database modifications, make sure
// our mapping and table state is up-to-date. // our mapping and table state is up-to-date.
//
// We need to `beginLongLivedReadTransaction` before we update our
// mapping in order to jump to the most recent commit.
[self.uiDatabaseConnection beginLongLivedReadTransaction];
[self extendRangeToIncludeUnobservedItems]; [self extendRangeToIncludeUnobservedItems];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction]; [self.messageMappings updateWithTransaction:transaction];

@ -6,14 +6,22 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
extern NSString *const OWSUIDatabaseConnectionWillUpdateNotification;
extern NSString *const OWSUIDatabaseConnectionDidUpdateNotification;
extern NSString *const OWSUIDatabaseConnectionWillUpdateExternallyNotification;
extern NSString *const OWSUIDatabaseConnectionDidUpdateExternallyNotification;
extern NSString *const OWSUIDatabaseConnectionNotificationsKey;
@interface OWSPrimaryStorage : OWSStorage @interface OWSPrimaryStorage : OWSStorage
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
+ (instancetype)sharedManager NS_SWIFT_NAME(shared()); + (instancetype)sharedManager NS_SWIFT_NAME(shared());
- (YapDatabaseConnection *)dbReadConnection; @property (nonatomic, readonly) YapDatabaseConnection *uiDatabaseConnection;
- (YapDatabaseConnection *)dbReadWriteConnection; @property (nonatomic, readonly) YapDatabaseConnection *dbReadConnection;
@property (nonatomic, readonly) YapDatabaseConnection *dbReadWriteConnection;
+ (YapDatabaseConnection *)dbReadConnection; + (YapDatabaseConnection *)dbReadConnection;
+ (YapDatabaseConnection *)dbReadWriteConnection; + (YapDatabaseConnection *)dbReadWriteConnection;

@ -19,6 +19,12 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
NSString *const OWSUIDatabaseConnectionWillUpdateNotification = @"OWSUIDatabaseConnectionWillUpdateNotification";
NSString *const OWSUIDatabaseConnectionDidUpdateNotification = @"OWSUIDatabaseConnectionDidUpdateNotification";
NSString *const OWSUIDatabaseConnectionWillUpdateExternallyNotification = @"OWSUIDatabaseConnectionWillUpdateExternallyNotification";
NSString *const OWSUIDatabaseConnectionDidUpdateExternallyNotification = @"OWSUIDatabaseConnectionDidUpdateExternallyNotification";
NSString *const OWSUIDatabaseConnectionNotificationsKey = @"OWSUIDatabaseConnectionNotificationsKey";
NSString *const OWSPrimaryStorageExceptionName_CouldNotCreateDatabaseDirectory NSString *const OWSPrimaryStorageExceptionName_CouldNotCreateDatabaseDirectory
= @"TSStorageManagerExceptionName_CouldNotCreateDatabaseDirectory"; = @"TSStorageManagerExceptionName_CouldNotCreateDatabaseDirectory";
@ -86,9 +92,6 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
@interface OWSPrimaryStorage () @interface OWSPrimaryStorage ()
@property (nonatomic, readonly, nullable) YapDatabaseConnection *dbReadConnection;
@property (nonatomic, readonly, nullable) YapDatabaseConnection *dbReadWriteConnection;
@property (atomic) BOOL areAsyncRegistrationsComplete; @property (atomic) BOOL areAsyncRegistrationsComplete;
@property (atomic) BOOL areSyncRegistrationsComplete; @property (atomic) BOOL areSyncRegistrationsComplete;
@ -98,6 +101,8 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
@implementation OWSPrimaryStorage @implementation OWSPrimaryStorage
@synthesize uiDatabaseConnection = _uiDatabaseConnection;
+ (instancetype)sharedManager + (instancetype)sharedManager
{ {
static OWSPrimaryStorage *sharedManager = nil; static OWSPrimaryStorage *sharedManager = nil;
@ -119,8 +124,22 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
if (self) { if (self) {
[self loadDatabase]; [self loadDatabase];
_dbReadConnection = self.newDatabaseConnection; _dbReadConnection = [self newDatabaseConnection];
_dbReadWriteConnection = self.newDatabaseConnection; _dbReadWriteConnection = [self newDatabaseConnection];
_uiDatabaseConnection = [self newDatabaseConnection];
// Increase object cache limit. Default is 250.
_uiDatabaseConnection.objectCacheLimit = 500;
[_uiDatabaseConnection beginLongLivedReadTransaction];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(yapDatabaseModified:)
name:YapDatabaseModifiedNotification
object:self.dbNotificationObject];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(yapDatabaseModifiedExternally:)
name:YapDatabaseModifiedExternallyNotification
object:nil];
OWSSingletonAssert(); OWSSingletonAssert();
} }
@ -128,6 +147,48 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
return self; return self;
} }
- (void)yapDatabaseModifiedExternally:(NSNotification *)notification
{
// Notify observers we're about to update the database connection
[[NSNotificationCenter defaultCenter] postNotificationName:OWSUIDatabaseConnectionWillUpdateExternallyNotification object:self.dbNotificationObject];
// Move uiDatabaseConnection to the latest commit.
// Do so atomically, and fetch all the notifications for each commit we jump.
NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction];
// Notify observers that the uiDatabaseConnection was updated
NSDictionary *userInfo = @{ OWSUIDatabaseConnectionNotificationsKey: notifications };
[[NSNotificationCenter defaultCenter] postNotificationName:OWSUIDatabaseConnectionDidUpdateExternallyNotification
object:self.dbNotificationObject
userInfo:userInfo];
}
- (void)yapDatabaseModified:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
DDLogVerbose(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
// Notify observers we're about to update the database connection
[[NSNotificationCenter defaultCenter] postNotificationName:OWSUIDatabaseConnectionWillUpdateNotification object:self.dbNotificationObject];
// Move uiDatabaseConnection to the latest commit.
// Do so atomically, and fetch all the notifications for each commit we jump.
NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction];
// Notify observers that the uiDatabaseConnection was updated
NSDictionary *userInfo = @{ OWSUIDatabaseConnectionNotificationsKey: notifications };
[[NSNotificationCenter defaultCenter] postNotificationName:OWSUIDatabaseConnectionDidUpdateNotification
object:self.dbNotificationObject
userInfo:userInfo];
}
- (YapDatabaseConnection *)uiDatabaseConnection
{
OWSAssertIsOnMainThread();
return _uiDatabaseConnection;
}
- (void)resetStorage - (void)resetStorage
{ {
_dbReadConnection = nil; _dbReadConnection = nil;

Loading…
Cancel
Save