Skip to content

Commit ba406b6

Browse files
author
Greg Soltis
authored
LRU tweaks (#1961)
* Add second timer setup, use NSInterval, drop post-compaction
1 parent ba76b15 commit ba406b6

File tree

7 files changed

+30
-35
lines changed

7 files changed

+30
-35
lines changed

Firestore/Source/Core/FSTFirestoreClient.mm

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@
6767
NS_ASSUME_NONNULL_BEGIN
6868

6969
/** How long we wait to try running LRU GC after SDK initialization. */
70-
static const long FSTLruGcInitialDelay = 60 * 1000;
70+
static const NSTimeInterval FSTLruGcInitialDelay = 60;
7171
/** Minimum amount of time between GC checks, after the first one. */
72-
static const long FSTLruGcRegularDelay = 5 * 60 * 1000;
72+
static const NSTimeInterval FSTLruGcRegularDelay = 5 * 60;
7373

7474
@interface FSTFirestoreClient () {
7575
DatabaseInfo _databaseInfo;
@@ -104,8 +104,8 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
104104

105105
@implementation FSTFirestoreClient {
106106
std::unique_ptr<Executor> _userExecutor;
107-
long _initialGcDelay;
108-
long _regularGcDelay;
107+
NSTimeInterval _initialGcDelay;
108+
NSTimeInterval _regularGcDelay;
109109
BOOL _gcHasRun;
110110
_Nullable id<FSTLRUDelegate> _lruDelegate;
111111
FSTDelayedCallback *_Nullable _lruCallback;
@@ -190,7 +190,6 @@ - (void)initializeWithUser:(const User &)user settings:(FIRFirestoreSettings *)s
190190
[[FSTSerializerBeta alloc] initWithDatabaseID:&self.databaseInfo->database_id()];
191191
FSTLocalSerializer *serializer =
192192
[[FSTLocalSerializer alloc] initWithRemoteSerializer:remoteSerializer];
193-
// TODO(gsoltis): enable LRU GC once API is finalized
194193
FSTLevelDB *ldb =
195194
[[FSTLevelDB alloc] initWithDirectory:std::move(dir)
196195
serializer:serializer
@@ -244,7 +243,7 @@ - (void)initializeWithUser:(const User &)user settings:(FIRFirestoreSettings *)s
244243
* run.
245244
*/
246245
- (void)scheduleLruGarbageCollection {
247-
long delay = _gcHasRun ? _initialGcDelay : _regularGcDelay;
246+
NSTimeInterval delay = _gcHasRun ? _regularGcDelay : _initialGcDelay;
248247
_lruCallback =
249248
[_workerDispatchQueue dispatchAfterDelay:delay
250249
timerID:FSTTimerIDGarbageCollectionDelay

Firestore/Source/Local/FSTLRUGarbageCollector.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,8 @@ struct LruResults {
107107

108108
- (size_t)byteSize;
109109

110-
/** Returns the number of targets cached. */
111-
- (int32_t)targetCount;
112-
113-
/**
114-
* If available, persistence implementations should run any compaction that they can. This is done
115-
* after GC has run to allow deletes to be processed and free up space.
116-
*/
117-
- (void)runPostCompaction;
110+
/** Returns the number of targets and orphaned documents cached. */
111+
- (int32_t)sequenceNumberCount;
118112

119113
/** Access to the underlying LRU Garbage collector instance. */
120114
@property(strong, nonatomic, readonly) FSTLRUGarbageCollector *gc;

Firestore/Source/Local/FSTLRUGarbageCollector.mm

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@ - (LruResults)collectWithLiveTargets:(NSDictionary<NSNumber *, FSTQueryData *> *
103103
size_t currentSize = [self byteSize];
104104
if (currentSize < _params.minBytesThreshold) {
105105
// Not enough on disk to warrant collection. Wait another timeout cycle.
106-
LOG_DEBUG("Garbage collection skipped; Cache size %i is lower than threshold %i", currentSize,
106+
LOG_DEBUG("Garbage collection skipped; Cache size %s is lower than threshold %s", currentSize,
107107
_params.minBytesThreshold);
108108
return LruResults::DidNotRun();
109109
} else {
110+
LOG_DEBUG("Running garbage collection on cache of size: %s", currentSize);
110111
return [self runGCWithLiveTargets:liveTargets];
111112
}
112113
}
@@ -130,9 +131,6 @@ - (LruResults)runGCWithLiveTargets:(NSDictionary<NSNumber *, FSTQueryData *> *)l
130131
int numDocumentsRemoved = [self removeOrphanedDocumentsThroughSequenceNumber:upperBound];
131132
Timestamp removedDocuments = Timestamp::Now();
132133

133-
[_delegate runPostCompaction];
134-
Timestamp compactedDb = Timestamp::Now();
135-
136134
std::string desc = "LRU Garbage Collection:\n";
137135
absl::StrAppend(&desc, "\tCounted targets in ", millisecondsBetween(start, countedTargets),
138136
"ms\n");
@@ -143,16 +141,14 @@ - (LruResults)runGCWithLiveTargets:(NSDictionary<NSNumber *, FSTQueryData *> *)l
143141
millisecondsBetween(foundUpperBound, removedTargets), "ms\n");
144142
absl::StrAppend(&desc, "\tRemoved ", numDocumentsRemoved, " documents in ",
145143
millisecondsBetween(removedTargets, removedDocuments), "ms\n");
146-
absl::StrAppend(&desc, "\tCompacted leveldb database in ",
147-
millisecondsBetween(removedDocuments, compactedDb), "ms\n");
148-
absl::StrAppend(&desc, "Total duration: ", millisecondsBetween(start, compactedDb), "ms");
144+
absl::StrAppend(&desc, "Total duration: ", millisecondsBetween(start, removedDocuments), "ms");
149145
LOG_DEBUG(desc.c_str());
150146

151147
return LruResults{/* didRun= */ true, sequenceNumbers, numTargetsRemoved, numDocumentsRemoved};
152148
}
153149

154150
- (int)queryCountForPercentile:(NSUInteger)percentile {
155-
int totalCount = [_delegate targetCount];
151+
int totalCount = [_delegate sequenceNumberCount];
156152
int setSize = (int)((percentile / 100.0f) * totalCount);
157153
return setSize;
158154
}

Firestore/Source/Local/FSTLevelDB.mm

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,13 @@ - (int)removeTargetsThroughSequenceNumber:(ListenSequenceNumber)sequenceNumber
229229
return [queryCache removeQueriesThroughSequenceNumber:sequenceNumber liveQueries:liveQueries];
230230
}
231231

232-
- (int32_t)targetCount {
233-
return [_db.queryCache count];
234-
}
235-
236-
- (void)runPostCompaction {
237-
// Compacts the entire db
238-
_db.ptr->CompactRange(NULL, NULL);
232+
- (int32_t)sequenceNumberCount {
233+
__block int32_t totalCount = [_db.queryCache count];
234+
[self enumerateMutationsUsingBlock:^(const DocumentKey &key, ListenSequenceNumber sequenceNumber,
235+
BOOL *stop) {
236+
totalCount++;
237+
}];
238+
return totalCount;
239239
}
240240

241241
- (FSTLRUGarbageCollector *)gc {

Firestore/Source/Local/FSTMemoryPersistence.mm

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,13 @@ - (int)removeTargetsThroughSequenceNumber:(ListenSequenceNumber)sequenceNumber
244244
liveQueries:liveQueries];
245245
}
246246

247-
- (int32_t)targetCount {
248-
return [_persistence.queryCache count];
249-
}
250-
251-
- (void)runPostCompaction {
252-
// No-op for memory persistence.
247+
- (int32_t)sequenceNumberCount {
248+
__block int32_t totalCount = [_persistence.queryCache count];
249+
[self enumerateMutationsUsingBlock:^(const DocumentKey &key, ListenSequenceNumber sequenceNumber,
250+
BOOL *stop) {
251+
totalCount++;
252+
}];
253+
return totalCount;
253254
}
254255

255256
- (int)removeOrphanedDocumentsThroughSequenceNumber:(ListenSequenceNumber)upperBound {

Firestore/Source/Util/FSTDispatchQueue.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ + (TimerId)convertTimerId:(FSTTimerID)objcTimerID {
7272
case TimerId::WriteStreamIdle:
7373
case TimerId::WriteStreamConnectionBackoff:
7474
case TimerId::OnlineStateTimeout:
75+
case TimerId::GarbageCollectionDelay:
7576
return converted;
7677
default:
7778
HARD_FAIL("Unknown value of enum FSTTimerID.");

Firestore/core/src/firebase/firestore/util/async_queue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ enum class TimerId {
5454
* indefinitely for success or failure.
5555
*/
5656
OnlineStateTimeout,
57+
/**
58+
* A timer used to periodically attempt LRU Garbage collection
59+
*/
60+
GarbageCollectionDelay
5761
};
5862

5963
// A serial queue that executes given operations asynchronously, one at a time.

0 commit comments

Comments
 (0)