diff --git a/fdbclient/NativeAPI.actor.cpp b/fdbclient/NativeAPI.actor.cpp index 194de863cc..c45e409d2b 100644 --- a/fdbclient/NativeAPI.actor.cpp +++ b/fdbclient/NativeAPI.actor.cpp @@ -847,7 +847,7 @@ DatabaseContext::DatabaseContext(ReferenceSHARD_STAT_SMOOTH_AMOUNT), @@ -2334,7 +2334,7 @@ void getRangeFinished(Database cx, Reference trLogInfo, doub cx->transactionBytesRead += bytes; cx->transactionKeysRead += result.size(); - + if( trLogInfo ) { trLogInfo->addLog(FdbClientLogEvents::EventGetRange(startTime, cx->clientLocality.dcId(), now()-startTime, bytes, begin.getKey(), end.getKey())); } @@ -2604,11 +2604,11 @@ Future> getRange( Database const& cx, Future } bool DatabaseContext::debugUseTags = false; -const std::vector DatabaseContext::debugTransactionTagChoices = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t" }; +const std::vector DatabaseContext::debugTransactionTagChoices = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t" }; void debugAddTags(Transaction *tr) { int numTags = deterministicRandom()->randomInt(0, CLIENT_KNOBS->MAX_TAGS_PER_TRANSACTION+1); - for(int i = 0; i < numTags; ++i) { + for(int i = 0; i < numTags; ++i) { TransactionTag tag; if(deterministicRandom()->random01() < 0.7) { tag = TransactionTagRef(deterministicRandom()->randomChoice(DatabaseContext::debugTransactionTagChoices)); @@ -3711,7 +3711,7 @@ void Transaction::setOption( FDBTransactionOptions::Option option, Optionalidentifier) - .detail("ServerTraceID", info.debugID.get().toString()); + .detail("ServerTraceID", info.debugID.get().first()); } break; @@ -3747,7 +3747,7 @@ void Transaction::setOption( FDBTransactionOptions::Option option, Optionalidentifier.empty()) { TraceEvent(SevInfo, "TransactionBeingTraced") .detail("DebugTransactionID", trLogInfo->identifier) - .detail("ServerTraceID", info.debugID.get().toString()); + .detail("ServerTraceID", info.debugID.get().first()); } break; @@ -4013,7 +4013,7 @@ Future Transaction::getReadVersion(uint32_t flags) { case TransactionPriority::DEFAULT: flags |= GetReadVersionRequest::PRIORITY_DEFAULT; ++cx->transactionDefaultReadVersions; - break; + break; case TransactionPriority::BATCH: flags |= GetReadVersionRequest::PRIORITY_BATCH; ++cx->transactionBatchReadVersions; @@ -4249,7 +4249,7 @@ ACTOR Future< StorageMetrics > extractMetrics( Future>> getReadHotRanges(Database cx, KeyRange keys) { +ACTOR Future>> getReadHotRanges(Database cx, KeyRange keys) { state Span span("NAPI:GetReadHotRanges"_loc); loop { int64_t shardLimit = 100; // Shard limit here does not really matter since this function is currently only used @@ -4277,7 +4277,7 @@ ACTOR Future>> getReadHotRanges(Database cx, K } wait(waitForAll(fReplies)); - Standalone> results; + Standalone> results; for (int i = 0; i < nLocs; i++) results.append(results.arena(), fReplies[i].get().readHotRanges.begin(), @@ -4294,7 +4294,7 @@ ACTOR Future>> getReadHotRanges(Database cx, K } } } - + ACTOR Future< std::pair, int> > waitStorageMetrics( Database cx, KeyRange keys, @@ -4386,7 +4386,7 @@ ACTOR Future>> waitDataDistributionMetricsLis } } -Future>> Transaction::getReadHotRanges(KeyRange const& keys) { +Future>> Transaction::getReadHotRanges(KeyRange const& keys) { return ::getReadHotRanges(cx, keys); } diff --git a/fdbclient/NativeAPI.actor.h b/fdbclient/NativeAPI.actor.h index a26f6b0ee5..8c52b23f6b 100644 --- a/fdbclient/NativeAPI.actor.h +++ b/fdbclient/NativeAPI.actor.h @@ -266,7 +266,7 @@ public: // Pass a negative value for `shardLimit` to indicate no limit on the shard number. Future< StorageMetrics > getStorageMetrics( KeyRange const& keys, int shardLimit ); Future< Standalone> > splitStorageMetrics( KeyRange const& keys, StorageMetrics const& limit, StorageMetrics const& estimated ); - Future>> getReadHotRanges(KeyRange const& keys); + Future>> getReadHotRanges(KeyRange const& keys); // If checkWriteConflictRanges is true, existing write conflict ranges will be searched for this key void set( const KeyRef& key, const ValueRef& value, bool addConflictRange = true ); diff --git a/fdbclient/StorageServerInterface.h b/fdbclient/StorageServerInterface.h index 7d94386d0a..af06453129 100644 --- a/fdbclient/StorageServerInterface.h +++ b/fdbclient/StorageServerInterface.h @@ -434,9 +434,30 @@ struct SplitMetricsRequest { } }; +// Should always be used inside a `Standalone`. +struct ReadHotRangeWithMetrics { + KeyRangeRef keys; + double density; + double readBandwidth; + + ReadHotRangeWithMetrics() = default; + ReadHotRangeWithMetrics(KeyRangeRef const& keys, double density, double readBandwidth) + : keys(keys), density(density), readBandwidth(readBandwidth) {} + + ReadHotRangeWithMetrics(Arena& arena, const ReadHotRangeWithMetrics& rhs) + : keys(arena, rhs.keys), density(rhs.density), readBandwidth(rhs.readBandwidth) {} + + int expectedSize() { return keys.expectedSize() + sizeof(density) + sizeof(readBandwidth); } + + template + void serialize(Ar& ar) { + serializer(ar, keys, density, readBandwidth); + } +}; + struct ReadHotSubRangeReply { constexpr static FileIdentifier file_identifier = 10424537; - Standalone> readHotRanges; + Standalone> readHotRanges; template void serialize(Ar& ar) { diff --git a/fdbserver/DataDistributionTracker.actor.cpp b/fdbserver/DataDistributionTracker.actor.cpp index 5e8574e594..f12d46659c 100644 --- a/fdbserver/DataDistributionTracker.actor.cpp +++ b/fdbserver/DataDistributionTracker.actor.cpp @@ -299,11 +299,14 @@ ACTOR Future readHotDetector(DataDistributionTracker* self) { state Transaction tr(self->cx); loop { try { - Standalone> readHotRanges = wait(tr.getReadHotRanges(keys)); + Standalone> readHotRanges = wait(tr.getReadHotRanges(keys)); for (auto& keyRange : readHotRanges) { TraceEvent("ReadHotRangeLog") - .detail("KeyRangeBegin", keyRange.begin) - .detail("KeyRangeEnd", keyRange.end); + .detail("ReadDensity", keyRange.density) + .detail("ReadBandwidth", keyRange.readBandwidth) + .detail("ReadDensityThreshold", SERVER_KNOBS->SHARD_MAX_READ_DENSITY_RATIO) + .detail("KeyRangeBegin", keyRange.keys.begin) + .detail("KeyRangeEnd", keyRange.keys.end); } break; } catch (Error& e) { diff --git a/fdbserver/Knobs.cpp b/fdbserver/Knobs.cpp index c1d151c750..763d6fbd57 100644 --- a/fdbserver/Knobs.cpp +++ b/fdbserver/Knobs.cpp @@ -144,17 +144,17 @@ void ServerKnobs::initialize(bool randomize, ClientKnobs* clientKnobs, bool isSi init( SHARD_BYTES_PER_SQRT_BYTES, 45 ); if( buggifySmallShards ) SHARD_BYTES_PER_SQRT_BYTES = 0;//Approximately 10000 bytes per shard init( MAX_SHARD_BYTES, 500000000 ); init( KEY_SERVER_SHARD_BYTES, 500000000 ); - init( SHARD_MAX_READ_DENSITY_RATIO, 2.0); + init( SHARD_MAX_READ_DENSITY_RATIO, 8.0); if (randomize && BUGGIFY) SHARD_MAX_READ_DENSITY_RATIO = 2.0; /* - The bytesRead/byteSize radio. Will be declared as read hot when larger than this. 2.0 was chosen to avoid reporting table scan as read hot. + The bytesRead/byteSize radio. Will be declared as read hot when larger than this. 8.0 was chosen to avoid reporting table scan as read hot. */ - init ( SHARD_READ_HOT_BANDWITH_MIN_PER_KSECONDS, 166667 * 1000); + init ( SHARD_READ_HOT_BANDWITH_MIN_PER_KSECONDS, 1666667 * 1000); /* - The read bandwidth of a given shard needs to be larger than this value in order to be evaluated if it's read hot. The roughly 167KB per second is calculated as following: - - Heuristic data suggests that each storage process can do max 50K read operations per second + The read bandwidth of a given shard needs to be larger than this value in order to be evaluated if it's read hot. The roughly 1.67MB per second is calculated as following: + - Heuristic data suggests that each storage process can do max 500K read operations per second - Each read has a minimum cost of EMPTY_READ_PENALTY, which is 20 bytes - - Thus that gives a minimum 1MB per second - - But to be conservative, set that number to be 1/6 of 1MB, which is roughly 166,667 bytes per second + - Thus that gives a minimum 10MB per second + - But to be conservative, set that number to be 1/6 of 10MB, which is roughly 1,666,667 bytes per second Shard with a read bandwidth smaller than this value will never be too busy to handle the reads. */ init( SHARD_MAX_BYTES_READ_PER_KSEC_JITTER, 0.1 ); diff --git a/fdbserver/RestoreController.actor.cpp b/fdbserver/RestoreController.actor.cpp index 5e09698192..d06bdf95f1 100644 --- a/fdbserver/RestoreController.actor.cpp +++ b/fdbserver/RestoreController.actor.cpp @@ -81,7 +81,7 @@ ACTOR Future sampleBackups(Reference self, RestoreC .detail("SampleID", req.id) .detail("BatchIndex", req.batchIndex) .detail("Samples", req.samples.size()); - ASSERT(req.batchIndex < self->batch.size()); + ASSERT(req.batchIndex <= self->batch.size()); // batchIndex starts from 1 Reference batch = self->batch[req.batchIndex]; if (batch->sampleMsgs.find(req.id) != batch->sampleMsgs.end()) { diff --git a/fdbserver/StorageMetrics.actor.h b/fdbserver/StorageMetrics.actor.h index 8cd887c072..46b83eccc9 100644 --- a/fdbserver/StorageMetrics.actor.h +++ b/fdbserver/StorageMetrics.actor.h @@ -419,9 +419,11 @@ struct StorageServerMetrics { // Given a read hot shard, this function will divide the shard into chunks and find those chunks whose // readBytes/sizeBytes exceeds the `readDensityRatio`. Please make sure to run unit tests // `StorageMetricsSampleTests.txt` after change made. - std::vector getReadHotRanges(KeyRangeRef shard, double readDensityRatio, int64_t baseChunkSize, - int64_t minShardReadBandwidthPerKSeconds) const { - std::vector toReturn; + std::vector getReadHotRanges(KeyRangeRef shard, double readDensityRatio, + int64_t baseChunkSize, + int64_t minShardReadBandwidthPerKSeconds) const { + std::vector toReturn; + double shardSize = (double)byteSample.getEstimate(shard); int64_t shardReadBandwidth = bytesReadSample.getEstimate(shard); if (shardReadBandwidth * SERVER_KNOBS->STORAGE_METRICS_AVERAGE_INTERVAL_PER_KSECONDS <= @@ -431,7 +433,9 @@ struct StorageServerMetrics { if (shardSize <= baseChunkSize) { // Shard is small, use it as is if (bytesReadSample.getEstimate(shard) > (readDensityRatio * shardSize)) { - toReturn.push_back(shard); + toReturn.emplace_back(shard, bytesReadSample.getEstimate(shard) / shardSize, + bytesReadSample.getEstimate(shard) / + SERVER_KNOBS->STORAGE_METRICS_AVERAGE_INTERVAL); } return toReturn; } @@ -453,14 +457,15 @@ struct StorageServerMetrics { if (bytesReadSample.getEstimate(KeyRangeRef(beginKey, *endKey)) > (readDensityRatio * std::max(baseChunkSize, byteSample.getEstimate(KeyRangeRef(beginKey, *endKey))))) { auto range = KeyRangeRef(beginKey, *endKey); - if (!toReturn.empty() && toReturn.back().end == range.begin) { + if (!toReturn.empty() && toReturn.back().keys.end == range.begin) { // in case two consecutive chunks both are over the ratio, merge them. - auto updatedTail = KeyRangeRef(toReturn.back().begin, *endKey); + range = KeyRangeRef(toReturn.back().keys.begin, *endKey); toReturn.pop_back(); - toReturn.push_back(updatedTail); - } else { - toReturn.push_back(range); } + toReturn.emplace_back( + range, + (double)bytesReadSample.getEstimate(range) / std::max(baseChunkSize, byteSample.getEstimate(range)), + bytesReadSample.getEstimate(range) / SERVER_KNOBS->STORAGE_METRICS_AVERAGE_INTERVAL); } beginKey = *endKey; endKey = byteSample.sample.index(byteSample.sample.sumTo(byteSample.sample.lower_bound(beginKey)) + @@ -471,10 +476,10 @@ struct StorageServerMetrics { void getReadHotRanges(ReadHotSubRangeRequest req) const { ReadHotSubRangeReply reply; - std::vector v = getReadHotRanges(req.keys, SERVER_KNOBS->SHARD_MAX_READ_DENSITY_RATIO, - SERVER_KNOBS->READ_HOT_SUB_RANGE_CHUNK_SIZE, - SERVER_KNOBS->SHARD_READ_HOT_BANDWITH_MIN_PER_KSECONDS); - reply.readHotRanges = VectorRef(v.data(), v.size()); + auto _ranges = getReadHotRanges(req.keys, SERVER_KNOBS->SHARD_MAX_READ_DENSITY_RATIO, + SERVER_KNOBS->READ_HOT_SUB_RANGE_CHUNK_SIZE, + SERVER_KNOBS->SHARD_READ_HOT_BANDWITH_MIN_PER_KSECONDS); + reply.readHotRanges = VectorRef(_ranges.data(), _ranges.size()); req.reply.send(reply); } @@ -518,11 +523,11 @@ TEST_CASE("/fdbserver/StorageMetricSample/readHotDetect/simple") { ssm.byteSample.sample.insert(LiteralStringRef("But"), 100 * sampleUnit); ssm.byteSample.sample.insert(LiteralStringRef("Cat"), 300 * sampleUnit); - vector t = + std::vector t = ssm.getReadHotRanges(KeyRangeRef(LiteralStringRef("A"), LiteralStringRef("C")), 2.0, 200 * sampleUnit, 0); - ASSERT(t.size() == 1 && (*t.begin()).begin == LiteralStringRef("Bah") && - (*t.begin()).end == LiteralStringRef("Bob")); + ASSERT(t.size() == 1 && (*t.begin()).keys.begin == LiteralStringRef("Bah") && + (*t.begin()).keys.end == LiteralStringRef("Bob")); return Void(); } @@ -549,12 +554,12 @@ TEST_CASE("/fdbserver/StorageMetricSample/readHotDetect/moreThanOneRange") { ssm.byteSample.sample.insert(LiteralStringRef("Cat"), 300 * sampleUnit); ssm.byteSample.sample.insert(LiteralStringRef("Dah"), 300 * sampleUnit); - vector t = + std::vector t = ssm.getReadHotRanges(KeyRangeRef(LiteralStringRef("A"), LiteralStringRef("D")), 2.0, 200 * sampleUnit, 0); - ASSERT(t.size() == 2 && (*t.begin()).begin == LiteralStringRef("Bah") && - (*t.begin()).end == LiteralStringRef("Bob")); - ASSERT(t.at(1).begin == LiteralStringRef("Cat") && t.at(1).end == LiteralStringRef("Dah")); + ASSERT(t.size() == 2 && (*t.begin()).keys.begin == LiteralStringRef("Bah") && + (*t.begin()).keys.end == LiteralStringRef("Bob")); + ASSERT(t.at(1).keys.begin == LiteralStringRef("Cat") && t.at(1).keys.end == LiteralStringRef("Dah")); return Void(); } @@ -582,12 +587,12 @@ TEST_CASE("/fdbserver/StorageMetricSample/readHotDetect/consecutiveRanges") { ssm.byteSample.sample.insert(LiteralStringRef("Cat"), 300 * sampleUnit); ssm.byteSample.sample.insert(LiteralStringRef("Dah"), 300 * sampleUnit); - vector t = + std::vector t = ssm.getReadHotRanges(KeyRangeRef(LiteralStringRef("A"), LiteralStringRef("D")), 2.0, 200 * sampleUnit, 0); - ASSERT(t.size() == 2 && (*t.begin()).begin == LiteralStringRef("Bah") && - (*t.begin()).end == LiteralStringRef("But")); - ASSERT(t.at(1).begin == LiteralStringRef("Cat") && t.at(1).end == LiteralStringRef("Dah")); + ASSERT(t.size() == 2 && (*t.begin()).keys.begin == LiteralStringRef("Bah") && + (*t.begin()).keys.end == LiteralStringRef("But")); + ASSERT(t.at(1).keys.begin == LiteralStringRef("Cat") && t.at(1).keys.end == LiteralStringRef("Dah")); return Void(); } diff --git a/fdbserver/workloads/ReadHotDetection.actor.cpp b/fdbserver/workloads/ReadHotDetection.actor.cpp index d6c589e059..1cae565d23 100644 --- a/fdbserver/workloads/ReadHotDetection.actor.cpp +++ b/fdbserver/workloads/ReadHotDetection.actor.cpp @@ -99,15 +99,15 @@ struct ReadHotDetectionWorkload : TestWorkload { // TraceEvent("RHDCheckPhaseLog") // .detail("KeyRangeSize", sm.bytes) // .detail("KeyRangeReadBandwith", sm.bytesReadPerKSecond); - Standalone> keyRanges = wait(tr.getReadHotRanges(self->wholeRange)); + Standalone> keyRanges = wait(tr.getReadHotRanges(self->wholeRange)); // TraceEvent("RHDCheckPhaseLog") // .detail("KeyRangesSize", keyRanges.size()) // .detail("ReadKey", self->readKey.printable().c_str()) // .detail("KeyRangesBackBeginKey", keyRanges.back().begin) // .detail("KeyRangesBackEndKey", keyRanges.back().end); // Loose check. - for (auto kr : keyRanges) { - if (kr.contains(self->readKey)) { + for (const auto& kr : keyRanges) { + if (kr.keys.contains(self->readKey)) { self->passed = true; } } diff --git a/versions.target b/versions.target deleted file mode 100644 index 4c151da97a..0000000000 --- a/versions.target +++ /dev/null @@ -1,7 +0,0 @@ - - - - 6.2.25 - 6.2 - -