Skip to content

LRU tweaks #1961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions Firestore/Source/Core/FSTFirestoreClient.mm
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@
NS_ASSUME_NONNULL_BEGIN

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

@interface FSTFirestoreClient () {
DatabaseInfo _databaseInfo;
Expand Down Expand Up @@ -104,8 +104,8 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo

@implementation FSTFirestoreClient {
std::unique_ptr<Executor> _userExecutor;
long _initialGcDelay;
long _regularGcDelay;
NSTimeInterval _initialGcDelay;
NSTimeInterval _regularGcDelay;
BOOL _gcHasRun;
_Nullable id<FSTLRUDelegate> _lruDelegate;
FSTDelayedCallback *_Nullable _lruCallback;
Expand Down Expand Up @@ -190,7 +190,6 @@ - (void)initializeWithUser:(const User &)user settings:(FIRFirestoreSettings *)s
[[FSTSerializerBeta alloc] initWithDatabaseID:&self.databaseInfo->database_id()];
FSTLocalSerializer *serializer =
[[FSTLocalSerializer alloc] initWithRemoteSerializer:remoteSerializer];
// TODO(gsoltis): enable LRU GC once API is finalized
FSTLevelDB *ldb =
[[FSTLevelDB alloc] initWithDirectory:std::move(dir)
serializer:serializer
Expand Down Expand Up @@ -244,7 +243,7 @@ - (void)initializeWithUser:(const User &)user settings:(FIRFirestoreSettings *)s
* run.
*/
- (void)scheduleLruGarbageCollection {
long delay = _gcHasRun ? _initialGcDelay : _regularGcDelay;
NSTimeInterval delay = _gcHasRun ? _regularGcDelay : _initialGcDelay;
_lruCallback =
[_workerDispatchQueue dispatchAfterDelay:delay
timerID:FSTTimerIDGarbageCollectionDelay
Expand Down
10 changes: 2 additions & 8 deletions Firestore/Source/Local/FSTLRUGarbageCollector.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,8 @@ struct LruResults {

- (size_t)byteSize;

/** Returns the number of targets cached. */
- (int32_t)targetCount;

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

/** Access to the underlying LRU Garbage collector instance. */
@property(strong, nonatomic, readonly) FSTLRUGarbageCollector *gc;
Expand Down
14 changes: 5 additions & 9 deletions Firestore/Source/Local/FSTLRUGarbageCollector.mm
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,11 @@ - (LruResults)collectWithLiveTargets:(NSDictionary<NSNumber *, FSTQueryData *> *
size_t currentSize = [self byteSize];
if (currentSize < _params.minBytesThreshold) {
// Not enough on disk to warrant collection. Wait another timeout cycle.
LOG_DEBUG("Garbage collection skipped; Cache size %i is lower than threshold %i", currentSize,
_params.minBytesThreshold);
LOG_DEBUG("Garbage collection skipped; Cache size %s is lower than threshold %s",
std::to_string(currentSize), std::to_string(_params.minBytesThreshold));
return LruResults::DidNotRun();
} else {
LOG_DEBUG("Running garbage collection on cache of size: %s", std::to_string(currentSize));
return [self runGCWithLiveTargets:liveTargets];
}
}
Expand All @@ -130,9 +131,6 @@ - (LruResults)runGCWithLiveTargets:(NSDictionary<NSNumber *, FSTQueryData *> *)l
int numDocumentsRemoved = [self removeOrphanedDocumentsThroughSequenceNumber:upperBound];
Timestamp removedDocuments = Timestamp::Now();

[_delegate runPostCompaction];
Timestamp compactedDb = Timestamp::Now();

std::string desc = "LRU Garbage Collection:\n";
absl::StrAppend(&desc, "\tCounted targets in ", millisecondsBetween(start, countedTargets),
"ms\n");
Expand All @@ -143,16 +141,14 @@ - (LruResults)runGCWithLiveTargets:(NSDictionary<NSNumber *, FSTQueryData *> *)l
millisecondsBetween(foundUpperBound, removedTargets), "ms\n");
absl::StrAppend(&desc, "\tRemoved ", numDocumentsRemoved, " documents in ",
millisecondsBetween(removedTargets, removedDocuments), "ms\n");
absl::StrAppend(&desc, "\tCompacted leveldb database in ",
millisecondsBetween(removedDocuments, compactedDb), "ms\n");
absl::StrAppend(&desc, "Total duration: ", millisecondsBetween(start, compactedDb), "ms");
absl::StrAppend(&desc, "Total duration: ", millisecondsBetween(start, removedDocuments), "ms");
LOG_DEBUG(desc.c_str());

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

- (int)queryCountForPercentile:(NSUInteger)percentile {
int totalCount = [_delegate targetCount];
int totalCount = [_delegate sequenceNumberCount];
int setSize = (int)((percentile / 100.0f) * totalCount);
return setSize;
}
Expand Down
14 changes: 7 additions & 7 deletions Firestore/Source/Local/FSTLevelDB.mm
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,13 @@ - (int)removeTargetsThroughSequenceNumber:(ListenSequenceNumber)sequenceNumber
return [queryCache removeQueriesThroughSequenceNumber:sequenceNumber liveQueries:liveQueries];
}

- (int32_t)targetCount {
return [_db.queryCache count];
}

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

- (FSTLRUGarbageCollector *)gc {
Expand Down
13 changes: 7 additions & 6 deletions Firestore/Source/Local/FSTMemoryPersistence.mm
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,13 @@ - (int)removeTargetsThroughSequenceNumber:(ListenSequenceNumber)sequenceNumber
liveQueries:liveQueries];
}

- (int32_t)targetCount {
return [_persistence.queryCache count];
}

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

- (int)removeOrphanedDocumentsThroughSequenceNumber:(ListenSequenceNumber)upperBound {
Expand Down
1 change: 1 addition & 0 deletions Firestore/Source/Util/FSTDispatchQueue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ + (TimerId)convertTimerId:(FSTTimerID)objcTimerID {
case TimerId::WriteStreamIdle:
case TimerId::WriteStreamConnectionBackoff:
case TimerId::OnlineStateTimeout:
case TimerId::GarbageCollectionDelay:
return converted;
default:
HARD_FAIL("Unknown value of enum FSTTimerID.");
Expand Down
4 changes: 4 additions & 0 deletions Firestore/core/src/firebase/firestore/util/async_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ enum class TimerId {
* indefinitely for success or failure.
*/
OnlineStateTimeout,
/**
* A timer used to periodically attempt LRU Garbage collection
*/
GarbageCollectionDelay
};

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