Skip to content

Commit 62333fe

Browse files
committed
[BP] MB-59817 [2/2]: Warmup active vbuckets before other
...to prioritise DGM workload efficiency over faster failover. Change-Id: I23769fd43394e47d223903d04c768bcef8e5a25a Reviewed-on: https://review.couchbase.org/c/kv_engine/+/201959 Tested-by: Pavlos Georgiou <[email protected]> Reviewed-by: Dave Rigby <[email protected]> Well-Formed: Restriction Checker
1 parent 44b3932 commit 62333fe

File tree

3 files changed

+45
-60
lines changed

3 files changed

+45
-60
lines changed

engines/ep/src/warmup.cc

Lines changed: 18 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@
3434
#include <platform/timeutils.h>
3535
#include <statistics/cbstat_collector.h>
3636
#include <utilities/logtags.h>
37-
#include <array>
3837
#include <limits>
3938
#include <memory>
4039
#include <optional>
41-
#include <random>
4240
#include <string>
4341
#include <utility>
4442

@@ -2047,70 +2045,30 @@ uint16_t Warmup::getNumKVStores() {
20472045
}
20482046

20492047
void Warmup::populateShardVbStates() {
2050-
uint16_t numKvs = getNumKVStores();
2051-
2052-
for (size_t i = 0; i < numKvs; i++) {
2053-
std::vector<vbucket_state*> kvStoreVbStates =
2054-
store.getRWUnderlyingByShard(i)->listPersistedVbuckets();
2055-
for (uint16_t j = 0; j < kvStoreVbStates.size(); j++) {
2056-
if (!kvStoreVbStates[j]) {
2048+
const uint16_t numShards = getNumKVStores();
2049+
for (uint16_t shardIdx = 0; shardIdx < numShards; ++shardIdx) {
2050+
const std::vector<vbucket_state*> curShardStates =
2051+
store.getRWUnderlyingByShard(shardIdx)->listPersistedVbuckets();
2052+
auto& statesMap = shardVbStates[shardIdx];
2053+
auto& statesVec = shardVbIds[shardIdx];
2054+
2055+
for (uint16_t vbIdx = 0; vbIdx < curShardStates.size(); ++vbIdx) {
2056+
if (!curShardStates[vbIdx]) {
20572057
continue;
20582058
}
2059-
auto vb = (j * numKvs) + i;
2060-
std::map<Vbid, vbucket_state>& shardVB =
2061-
shardVbStates[vb % store.vbMap.getNumShards()];
2062-
shardVB.insert(std::pair<Vbid, vbucket_state>(
2063-
Vbid(vb), *(kvStoreVbStates[j])));
2059+
const Vbid vbid(vbIdx * numShards + shardIdx);
2060+
statesMap.insert({vbid, *curShardStates[vbIdx]});
20642061
}
2065-
}
20662062

2067-
for (size_t i = 0; i < store.vbMap.shards.size(); i++) {
2068-
std::vector<Vbid> activeVBs, otherVBs;
2069-
std::map<Vbid, vbucket_state>::const_iterator it;
2070-
for (auto shardIt : shardVbStates[i]) {
2071-
Vbid vbid = shardIt.first;
2072-
vbucket_state vbs = shardIt.second;
2073-
if (vbs.transition.state == vbucket_state_active) {
2074-
activeVBs.push_back(vbid);
2075-
} else {
2076-
otherVBs.push_back(vbid);
2063+
// First push all active vbuckets and then the rest
2064+
for (const auto& item : statesMap) {
2065+
if (item.second.transition.state == vbucket_state_active) {
2066+
statesVec.push_back(item.first);
20772067
}
20782068
}
2079-
2080-
// Push one active VB to the front.
2081-
// When the ratio of RAM to VBucket is poor (big vbuckets) this will
2082-
// ensure we at least bring active data in before replicas eat RAM.
2083-
if (!activeVBs.empty()) {
2084-
shardVbIds[i].push_back(activeVBs.back());
2085-
activeVBs.pop_back();
2086-
}
2087-
2088-
// Now the VB lottery can begin.
2089-
// Generate a psudeo random, weighted list of active/replica vbuckets.
2090-
// The random seed is the shard ID so that re-running warmup
2091-
// for the same shard and vbucket set always gives the same output and keeps
2092-
// nodes of the cluster more equal after a warmup.
2093-
2094-
std::mt19937 twister(i);
2095-
// Give 'true' (aka active) 60% of the time
2096-
// Give 'false' (aka other) 40% of the time.
2097-
std::bernoulli_distribution distribute(0.6);
2098-
std::array<std::vector<Vbid>*, 2> activeReplicaSource = {
2099-
{&activeVBs, &otherVBs}};
2100-
2101-
while (!activeVBs.empty() || !otherVBs.empty()) {
2102-
const bool active = distribute(twister);
2103-
int num = active ? 0 : 1;
2104-
if (!activeReplicaSource[num]->empty()) {
2105-
shardVbIds[i].push_back(activeReplicaSource[num]->back());
2106-
activeReplicaSource[num]->pop_back();
2107-
} else {
2108-
// Once active or replica set is empty, just drain the other one.
2109-
num = num ^ 1;
2110-
while (!activeReplicaSource[num]->empty()) {
2111-
shardVbIds[i].push_back(activeReplicaSource[num]->back());
2112-
activeReplicaSource[num]->pop_back();
2113-
}
2069+
for (const auto& item : statesMap) {
2070+
if (item.second.transition.state != vbucket_state_active) {
2071+
statesVec.push_back(item.first);
21142072
}
21152073
}
21162074
}

engines/ep/src/warmup.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ class Warmup {
323323
return "running";
324324
}
325325

326+
const std::vector<std::vector<Vbid>>& getShardVbIds() const {
327+
return shardVbIds;
328+
}
329+
326330
/**
327331
* Testing hook which if set is called every time warmup transitions to
328332
* a new state.

engines/ep/tests/module_tests/evp_store_warmup_test.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,29 @@ TEST_F(WarmupOrderTest, pauseResumeVisit) {
777777
EXPECT_EQ(visitor.visited, toVisit);
778778
}
779779

780+
/// Test that all the active vbuckets in a shard are loaded first
781+
TEST_F(WarmupOrderTest, populateShardVbStates) {
782+
resetEngineAndEnableWarmup();
783+
runReadersUntilWarmedUp();
784+
const auto* warmup = store->getWarmup();
785+
ASSERT_TRUE(warmup);
786+
for (const auto& shard : warmup->getShardVbIds()) {
787+
EXPECT_EQ(16, shard.size());
788+
bool seenNotActive = false;
789+
for (const auto& vbid : shard) {
790+
const auto vb = store->getVBucket(vbid);
791+
ASSERT_TRUE(vb);
792+
const auto state = vb->getState();
793+
if (seenNotActive) {
794+
EXPECT_NE(vbucket_state_active, state);
795+
}
796+
if (state != vbucket_state_active) {
797+
seenNotActive = true;
798+
}
799+
}
800+
}
801+
}
802+
780803
// Test fixture for Durability-related Warmup tests.
781804
class DurabilityWarmupTest : public DurabilityKVBucketTest {
782805
protected:

0 commit comments

Comments
 (0)