Move building of KeyRangeMap out of the loop

So that it is only done once.
This commit is contained in:
Jingyu Zhou 2020-07-08 14:14:28 -07:00
parent a187eeebee
commit d6dd88c2b9
2 changed files with 31 additions and 28 deletions

View File

@ -111,37 +111,37 @@ public:
}
Val const& operator[]( const Key& k ) { return rangeContaining(k).value(); }
Ranges ranges() { return Ranges( Iterator(map.begin()), Iterator(map.lastItem()) ); }
Ranges ranges() const { return Ranges(Iterator(map.begin()), Iterator(map.lastItem())); }
// intersectingRanges returns [begin, end] where begin <= r.begin and end >= r.end
Ranges intersectingRanges( const Range& r ) { return Ranges(rangeContaining(r.begin), Iterator(map.lower_bound(r.end))); }
Ranges intersectingRanges(const Range& r) const {
return Ranges(rangeContaining(r.begin), Iterator(map.lower_bound(r.end)));
}
// containedRanges() will return all ranges that are fully contained by the passed range (note that a range fully contains itself)
Ranges containedRanges( const Range& r ) {
Ranges containedRanges(const Range& r) const {
auto s = Iterator( map.lower_bound( r.begin ) );
if ( s.begin() >= r.end ) return Ranges(s,s);
return Ranges(s, rangeContaining(r.end));
}
template <class ComparableToKey>
Iterator rangeContaining( const ComparableToKey& k ) {
return Iterator(map.lastLessOrEqual(k));
Iterator rangeContaining(const ComparableToKey& k) const {
return Iterator(map.lastLessOrEqual(k));
}
// Returns the range containing a key infinitesimally before k, or the first range if k==Key()
template <class ComparableToKey>
Iterator rangeContainingKeyBefore( const ComparableToKey& k ) {
Iterator rangeContainingKeyBefore(const ComparableToKey& k) const {
Iterator i = map.lower_bound(k);
if ( !i->begin().size() ) return i;
--i;
return i;
}
Iterator lastItem() {
Iterator lastItem() const {
auto i = map.lastItem();
i.decrementNonEnd();
return Iterator(i);
}
int size() const { return map.size() - 1; } // We always have one range bounded by two entries
Iterator randomRange() {
return Iterator( map.index( deterministicRandom()->randomInt(0, map.size()-1) ) );
}
Iterator nthRange(int n) { return Iterator(map.index(n)); }
Iterator randomRange() const { return Iterator(map.index(deterministicRandom()->randomInt(0, map.size() - 1))); }
Iterator nthRange(int n) const { return Iterator(map.index(n)); }
bool allEqual( const Range& r, const Val& v );

View File

@ -36,8 +36,8 @@
typedef std::map<Standalone<StringRef>, std::pair<Standalone<StringRef>, uint32_t>> SerializedMutationListMap;
std::vector<UID> getApplierIDs(std::map<Key, UID>& rangeToApplier);
void splitMutation(std::map<Key, UID>* pRangeToApplier, MutationRef m, Arena& mvector_arena,
VectorRef<MutationRef>& mvector, Arena& nodeIDs_arena, VectorRef<UID>& nodeIDs);
void splitMutation(const KeyRangeMap<UID>& krMap, MutationRef m, Arena& mvector_arena, VectorRef<MutationRef>& mvector,
Arena& nodeIDs_arena, VectorRef<UID>& nodeIDs);
void _parseSerializedMutation(KeyRangeMap<Version>* pRangeVersions,
std::map<LoadingParam, VersionedMutationsMap>::iterator kvOpsIter,
SerializedMutationListMap* mutationMap,
@ -472,6 +472,19 @@ ACTOR Future<Void> handleSendMutationsRequest(RestoreSendMutationsToAppliersRequ
return Void();
}
void buildApplierRangeMap(KeyRangeMap<UID>* krMap, std::map<Key, UID>* pRangeToApplier) {
std::map<Key, UID>::iterator beginKey = pRangeToApplier->begin();
std::map<Key, UID>::iterator endKey = std::next(beginKey, 1);
while (endKey != pRangeToApplier->end()) {
krMap->insert(KeyRangeRef(beginKey->first, endKey->first), beginKey->second);
beginKey = endKey;
endKey++;
}
if (beginKey != pRangeToApplier->end()) {
krMap->insert(KeyRangeRef(beginKey->first, normalKeys.end), beginKey->second);
}
}
// Assume: kvOps data are from the same RestoreAsset.
// Input: pkvOps: versioned kv mutation for the asset in the version batch (batchIndex)
// isRangeFile: is pkvOps from range file? Let receiver (applier) know if the mutation is log mutation;
@ -516,6 +529,8 @@ ACTOR Future<Void> sendMutationsToApplier(VersionedMutationsMap* pkvOps, int bat
for (auto& applierID : applierIDs) {
applierVersionedMutationsBuffer[applierID] = VersionedMutationsVec();
}
KeyRangeMap<UID> krMap;
buildApplierRangeMap(&krMap, pRangeToApplier);
for (kvOp = kvOps.begin(); kvOp != kvOps.end(); kvOp++) {
commitVersion = kvOp->first;
ASSERT(commitVersion.version >= asset.beginVersion);
@ -528,8 +543,7 @@ ACTOR Future<Void> sendMutationsToApplier(VersionedMutationsMap* pkvOps, int bat
Standalone<VectorRef<UID>> nodeIDs;
// Because using a vector of mutations causes overhead, and the range mutation should happen rarely;
// We handle the range mutation and key mutation differently for the benefit of avoiding memory copy
splitMutation(pRangeToApplier, kvm, mvector.arena(), mvector.contents(), nodeIDs.arena(),
nodeIDs.contents());
splitMutation(krMap, kvm, mvector.arena(), mvector.contents(), nodeIDs.arena(), nodeIDs.contents());
ASSERT(mvector.size() == nodeIDs.size());
if (debugMutation("RestoreLoader", commitVersion.version, kvm)) {
@ -628,22 +642,11 @@ ACTOR Future<Void> sendMutationsToApplier(VersionedMutationsMap* pkvOps, int bat
// Splits a clear range mutation for Appliers and puts results of splitted mutations and
// Applier IDs into "mvector" and "nodeIDs" on return.
void splitMutation(std::map<Key, UID>* pRangeToApplier, MutationRef m, Arena& mvector_arena,
VectorRef<MutationRef>& mvector, Arena& nodeIDs_arena, VectorRef<UID>& nodeIDs) {
void splitMutation(const KeyRangeMap<UID>& krMap, MutationRef m, Arena& mvector_arena, VectorRef<MutationRef>& mvector,
Arena& nodeIDs_arena, VectorRef<UID>& nodeIDs) {
TraceEvent(SevDebug, "FastRestoreSplitMutation").detail("Mutation", m.toString());
ASSERT(mvector.empty());
ASSERT(nodeIDs.empty());
KeyRangeMap<UID> krMap;
std::map<Key, UID>::iterator beginKey = pRangeToApplier->begin();
std::map<Key, UID>::iterator endKey = std::next(beginKey, 1);
while (endKey != pRangeToApplier->end()) {
krMap.insert(KeyRangeRef(beginKey->first, endKey->first), beginKey->second);
beginKey = endKey;
endKey++;
}
if (beginKey != pRangeToApplier->end()) {
krMap.insert(KeyRangeRef(beginKey->first, normalKeys.end), beginKey->second);
}
auto r = krMap.intersectingRanges(KeyRangeRef(m.param1, m.param2));
for (auto i = r.begin(); i != r.end(); ++i) {
// Calculate the overlap range