Skip to content

Commit 7c4a12f

Browse files
author
Greg Soltis
authored
Implement byteSize methods on lru delegates for use in GC threshold (#1893)
Implement byteSize methods on lru delegates for use in GC threshold
1 parent 4e067e5 commit 7c4a12f

13 files changed

+154
-19
lines changed

Firestore/Example/Tests/Local/FSTLRUGarbageCollectorTests.mm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,28 @@ - (void)testRemoveTargetsThenGC {
639639
});
640640
[_persistence shutdown];
641641
}
642+
643+
- (void)testGetsSize {
644+
if ([self isTestBaseClass]) return;
645+
646+
[self newTestResources];
647+
648+
size_t initialSize = [_gc byteSize];
649+
650+
_persistence.run("fill cache", [&]() {
651+
// Simulate a bunch of ack'd mutations
652+
for (int i = 0; i < 50; i++) {
653+
FSTDocument *doc = [self cacheADocumentInTransaction];
654+
[self markDocumentEligibleForGCInTransaction:doc.key];
655+
}
656+
});
657+
658+
size_t finalSize = [_gc byteSize];
659+
XCTAssertGreaterThan(finalSize, initialSize);
660+
661+
[_persistence shutdown];
662+
}
663+
642664
@end
643665

644666
NS_ASSUME_NONNULL_END

Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.mm

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@
3838

3939
@implementation FSTPersistenceTestHelpers
4040

41+
+ (FSTLocalSerializer *)localSerializer {
42+
// This owns the DatabaseIds since we do not have FirestoreClient instance to own them.
43+
static DatabaseId database_id{"p", "d"};
44+
45+
FSTSerializerBeta *remoteSerializer = [[FSTSerializerBeta alloc] initWithDatabaseID:&database_id];
46+
return [[FSTLocalSerializer alloc] initWithRemoteSerializer:remoteSerializer];
47+
}
48+
4149
+ (Path)levelDBDir {
4250
Path dir = util::TempDir().AppendUtf8("FSTPersistenceTestHelpers");
4351

@@ -53,12 +61,7 @@ + (Path)levelDBDir {
5361
}
5462

5563
+ (FSTLevelDB *)levelDBPersistenceWithDir:(Path)dir {
56-
// This owns the DatabaseIds since we do not have FirestoreClient instance to own them.
57-
static DatabaseId database_id{"p", "d"};
58-
59-
FSTSerializerBeta *remoteSerializer = [[FSTSerializerBeta alloc] initWithDatabaseID:&database_id];
60-
FSTLocalSerializer *serializer =
61-
[[FSTLocalSerializer alloc] initWithRemoteSerializer:remoteSerializer];
64+
FSTLocalSerializer *serializer = [self localSerializer];
6265
FSTLevelDB *db = [[FSTLevelDB alloc] initWithDirectory:std::move(dir) serializer:serializer];
6366
Status status = [db start];
6467
if (!status.ok()) {
@@ -85,7 +88,9 @@ + (FSTMemoryPersistence *)eagerGCMemoryPersistence {
8588
}
8689

8790
+ (FSTMemoryPersistence *)lruMemoryPersistence {
88-
FSTMemoryPersistence *persistence = [FSTMemoryPersistence persistenceWithLRUGC];
91+
FSTLocalSerializer *serializer = [self localSerializer];
92+
FSTMemoryPersistence *persistence =
93+
[FSTMemoryPersistence persistenceWithLRUGCAndSerializer:serializer];
8994
Status status = [persistence start];
9095
if (!status.ok()) {
9196
[NSException raise:NSInternalInconsistencyException

Firestore/Source/Local/FSTLRUGarbageCollector.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ extern const firebase::firestore::model::ListenSequenceNumber kFSTListenSequence
6161
(firebase::firestore::model::ListenSequenceNumber)sequenceNumber
6262
liveQueries:(NSDictionary<NSNumber *, FSTQueryData *> *)liveQueries;
6363

64+
- (size_t)byteSize;
65+
6466
/** Access to the underlying LRU Garbage collector instance. */
6567
@property(strong, nonatomic, readonly) FSTLRUGarbageCollector *gc;
6668

@@ -103,4 +105,6 @@ extern const firebase::firestore::model::ListenSequenceNumber kFSTListenSequence
103105
- (int)removeOrphanedDocumentsThroughSequenceNumber:
104106
(firebase::firestore::model::ListenSequenceNumber)sequenceNumber;
105107

108+
- (size_t)byteSize;
109+
106110
@end

Firestore/Source/Local/FSTLRUGarbageCollector.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,8 @@ - (int)removeOrphanedDocumentsThroughSequenceNumber:(ListenSequenceNumber)sequen
119119
return [_delegate removeOrphanedDocumentsThroughSequenceNumber:sequenceNumber];
120120
}
121121

122+
- (size_t)byteSize {
123+
return [_delegate byteSize];
124+
}
125+
122126
@end

Firestore/Source/Local/FSTLevelDB.mm

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@
7777

7878
static const char *kReservedPathComponent = "firestore";
7979

80+
@interface FSTLevelDB ()
81+
82+
- (size_t)byteSize;
83+
84+
@property(nonatomic, assign, getter=isStarted) BOOL started;
85+
@property(nonatomic, strong, readonly) FSTLocalSerializer *serializer;
86+
87+
@end
88+
8089
/**
8190
* Provides LRU functionality for leveldb persistence.
8291
*
@@ -234,12 +243,9 @@ - (void)limboDocumentUpdated:(const DocumentKey &)key {
234243
[self writeSentinelForKey:key];
235244
}
236245

237-
@end
238-
239-
@interface FSTLevelDB ()
240-
241-
@property(nonatomic, assign, getter=isStarted) BOOL started;
242-
@property(nonatomic, strong, readonly) FSTLocalSerializer *serializer;
246+
- (size_t)byteSize {
247+
return [_db byteSize];
248+
}
243249

244250
@end
245251

@@ -290,6 +296,19 @@ - (instancetype)initWithDirectory:(Path)directory serializer:(FSTLocalSerializer
290296
return self;
291297
}
292298

299+
- (size_t)byteSize {
300+
off_t count = 0;
301+
auto iter = util::DirectoryIterator::Create(_directory);
302+
for (; iter->Valid(); iter->Next()) {
303+
off_t fileSize = util::FileSize(iter->file()).ValueOrDie();
304+
count += fileSize;
305+
}
306+
HARD_ASSERT(iter->status().ok(), "Failed to iterate leveldb directory: %s",
307+
iter->status().error_message().c_str());
308+
HARD_ASSERT(count <= SIZE_MAX, "Overflowed counting bytes cached");
309+
return count;
310+
}
311+
293312
- (const std::set<std::string> &)users {
294313
return _users;
295314
}

Firestore/Source/Local/FSTMemoryMutationQueue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
NS_ASSUME_NONNULL_BEGIN
2323

24+
@class FSTLocalSerializer;
25+
2426
@interface FSTMemoryMutationQueue : NSObject <FSTMutationQueue>
2527

2628
- (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence NS_DESIGNATED_INITIALIZER;
@@ -32,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN
3234
*/
3335
- (BOOL)containsKey:(const firebase::firestore::model::DocumentKey &)key;
3436

37+
- (size_t)byteSizeWithSerializer:(FSTLocalSerializer *)serializer;
38+
3539
@end
3640

3741
NS_ASSUME_NONNULL_END

Firestore/Source/Local/FSTMemoryMutationQueue.mm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616

1717
#import "Firestore/Source/Local/FSTMemoryMutationQueue.h"
1818

19+
#import <Protobuf/GPBProtocolBuffers.h>
20+
1921
#include <set>
2022

23+
#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h"
2124
#import "Firestore/Source/Core/FSTQuery.h"
2225
#import "Firestore/Source/Local/FSTDocumentReference.h"
2326
#import "Firestore/Source/Local/FSTMemoryPersistence.h"
@@ -466,6 +469,14 @@ - (NSUInteger)indexOfExistingBatchID:(BatchId)batchID action:(NSString *)action
466469
return (NSUInteger)index;
467470
}
468471

472+
- (size_t)byteSizeWithSerializer:(FSTLocalSerializer *)serializer {
473+
size_t count = 0;
474+
for (FSTMutationBatch *batch in self.queue) {
475+
count += [[[serializer encodedMutationBatch:batch] data] length];
476+
};
477+
return count;
478+
}
479+
469480
@end
470481

471482
NS_ASSUME_NONNULL_END

Firestore/Source/Local/FSTMemoryPersistence.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#import <Foundation/Foundation.h>
1818

1919
#import "Firestore/Source/Local/FSTLRUGarbageCollector.h"
20+
#import "Firestore/Source/Local/FSTLocalSerializer.h"
2021
#import "Firestore/Source/Local/FSTPersistence.h"
2122
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
2223
#include "Firestore/core/src/firebase/firestore/model/types.h"
@@ -31,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
3132

3233
+ (instancetype)persistenceWithEagerGC;
3334

34-
+ (instancetype)persistenceWithLRUGC;
35+
+ (instancetype)persistenceWithLRUGCAndSerializer:(FSTLocalSerializer *)serializer;
3536

3637
@end
3738

@@ -50,7 +51,8 @@ NS_ASSUME_NONNULL_BEGIN
5051
@interface FSTMemoryLRUReferenceDelegate
5152
: NSObject <FSTReferenceDelegate, FSTLRUDelegate, FSTTransactional>
5253

53-
- (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence;
54+
- (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence
55+
serializer:(FSTLocalSerializer *)serializer;
5456

5557
- (BOOL)isPinnedAtSequenceNumber:(firebase::firestore::model::ListenSequenceNumber)upperBound
5658
document:(const firebase::firestore::model::DocumentKey &)key;

Firestore/Source/Local/FSTMemoryPersistence.mm

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444

4545
@interface FSTMemoryPersistence ()
4646

47+
- (FSTMemoryQueryCache *)queryCache;
48+
49+
- (FSTMemoryRemoteDocumentCache *)remoteDocumentCache;
50+
4751
@property(nonatomic, readonly) MutationQueues &mutationQueues;
4852

4953
@property(nonatomic, assign, getter=isStarted) BOOL started;
@@ -79,10 +83,10 @@ + (instancetype)persistenceWithEagerGC {
7983
return persistence;
8084
}
8185

82-
+ (instancetype)persistenceWithLRUGC {
86+
+ (instancetype)persistenceWithLRUGCAndSerializer:(FSTLocalSerializer *)serializer {
8387
FSTMemoryPersistence *persistence = [[FSTMemoryPersistence alloc] init];
8488
persistence.referenceDelegate =
85-
[[FSTMemoryLRUReferenceDelegate alloc] initWithPersistence:persistence];
89+
[[FSTMemoryLRUReferenceDelegate alloc] initWithPersistence:persistence serializer:serializer];
8690
return persistence;
8791
}
8892

@@ -136,7 +140,7 @@ - (ListenSequenceNumber)currentSequenceNumber {
136140
return queue;
137141
}
138142

139-
- (id<FSTQueryCache>)queryCache {
143+
- (FSTMemoryQueryCache *)queryCache {
140144
return _queryCache;
141145
}
142146

@@ -155,9 +159,11 @@ @implementation FSTMemoryLRUReferenceDelegate {
155159
FSTLRUGarbageCollector *_gc;
156160
FSTListenSequence *_listenSequence;
157161
ListenSequenceNumber _currentSequenceNumber;
162+
FSTLocalSerializer *_serializer;
158163
}
159164

160-
- (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence {
165+
- (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence
166+
serializer:(FSTLocalSerializer *)serializer {
161167
if (self = [super init]) {
162168
_persistence = persistence;
163169
_gc =
@@ -167,6 +173,7 @@ - (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence {
167173
ListenSequenceNumber highestSequenceNumber =
168174
_persistence.queryCache.highestListenSequenceNumber;
169175
_listenSequence = [[FSTListenSequence alloc] initStartingAfter:highestSequenceNumber];
176+
_serializer = serializer;
170177
}
171178
return self;
172179
}
@@ -274,6 +281,20 @@ - (BOOL)isPinnedAtSequenceNumber:(ListenSequenceNumber)upperBound
274281
return NO;
275282
}
276283

284+
- (size_t)byteSize {
285+
// Note that this method is only used for testing because this delegate is only
286+
// used for testing. The algorithm here (loop through everything, serialize it
287+
// and count bytes) is inefficient and inexact, but won't run in production.
288+
size_t count = 0;
289+
count += [_persistence.queryCache byteSizeWithSerializer:_serializer];
290+
count += [_persistence.remoteDocumentCache byteSizeWithSerializer:_serializer];
291+
const MutationQueues &queues = [_persistence mutationQueues];
292+
for (auto it = queues.begin(); it != queues.end(); ++it) {
293+
count += [it->second byteSizeWithSerializer:_serializer];
294+
}
295+
return count;
296+
}
297+
277298
@end
278299

279300
@implementation FSTMemoryEagerReferenceDelegate {

Firestore/Source/Local/FSTMemoryQueryCache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
NS_ASSUME_NONNULL_BEGIN
2222

23+
@class FSTLocalSerializer;
2324
@class FSTMemoryPersistence;
2425

2526
/**
@@ -32,6 +33,8 @@ NS_ASSUME_NONNULL_BEGIN
3233

3334
- (instancetype)init NS_UNAVAILABLE;
3435

36+
- (size_t)byteSizeWithSerializer:(FSTLocalSerializer *)serializer;
37+
3538
@end
3639

3740
NS_ASSUME_NONNULL_END

Firestore/Source/Local/FSTMemoryQueryCache.mm

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616

1717
#import "Firestore/Source/Local/FSTMemoryQueryCache.h"
1818

19+
#import <Protobuf/GPBProtocolBuffers.h>
20+
1921
#include <utility>
2022

23+
#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
2124
#import "Firestore/Source/Core/FSTQuery.h"
2225
#import "Firestore/Source/Local/FSTMemoryPersistence.h"
2326
#import "Firestore/Source/Local/FSTQueryData.h"
@@ -168,6 +171,15 @@ - (BOOL)containsKey:(const firebase::firestore::model::DocumentKey &)key {
168171
return [self.references containsKey:key];
169172
}
170173

174+
- (size_t)byteSizeWithSerializer:(FSTLocalSerializer *)serializer {
175+
__block size_t count = 0;
176+
[self.queries
177+
enumerateKeysAndObjectsUsingBlock:^(FSTQuery *key, FSTQueryData *queryData, BOOL *stop) {
178+
count += [[[serializer encodedQueryData:queryData] data] length];
179+
}];
180+
return count;
181+
}
182+
171183
@end
172184

173185
NS_ASSUME_NONNULL_END

Firestore/Source/Local/FSTMemoryRemoteDocumentCache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
NS_ASSUME_NONNULL_BEGIN
2424

25+
@class FSTLocalSerializer;
2526
@class FSTMemoryLRUReferenceDelegate;
2627

2728
@interface FSTMemoryRemoteDocumentCache : NSObject <FSTRemoteDocumentCache>
@@ -31,6 +32,8 @@ NS_ASSUME_NONNULL_BEGIN
3132
- (int)removeOrphanedDocuments:(FSTMemoryLRUReferenceDelegate *)referenceDelegate
3233
throughSequenceNumber:(firebase::firestore::model::ListenSequenceNumber)upperBound;
3334

35+
- (size_t)byteSizeWithSerializer:(FSTLocalSerializer *)serializer;
36+
3437
@end
3538

3639
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)