diff --git a/fdbclient/StorageServerInterface.h b/fdbclient/StorageServerInterface.h index 75c9411f18..d03676fc53 100644 --- a/fdbclient/StorageServerInterface.h +++ b/fdbclient/StorageServerInterface.h @@ -921,6 +921,22 @@ struct GetStorageMetricsRequest { }; struct StorageQueuingMetricsReply { + struct TagInfo { + constexpr static FileIdentifier file_identifier = 4528694; + TransactionTag tag; + double rate{ 0.0 }; + double fractionalBusyness{ 0.0 }; + + TagInfo() = default; + TagInfo(TransactionTag const& tag, double rate, double fractionalBusyness) + : tag(tag), rate(rate), fractionalBusyness(fractionalBusyness) {} + + template + void serialize(Ar& ar) { + serializer(ar, tag, rate, fractionalBusyness); + } + }; + constexpr static FileIdentifier file_identifier = 7633366; double localTime; int64_t instanceID; // changes if bytesDurable and bytesInput reset @@ -931,9 +947,7 @@ struct StorageQueuingMetricsReply { double cpuUsage; double diskUsage; double localRateLimit; - Optional busiestTag; - double busiestTagFractionalBusyness; - double busiestTagRate; + std::vector busiestTags; template void serialize(Ar& ar) { @@ -948,9 +962,7 @@ struct StorageQueuingMetricsReply { cpuUsage, diskUsage, localRateLimit, - busiestTag, - busiestTagFractionalBusyness, - busiestTagRate); + busiestTags); } }; diff --git a/fdbserver/Ratekeeper.actor.cpp b/fdbserver/Ratekeeper.actor.cpp index 8edb87a0fb..1d12c6f1d8 100644 --- a/fdbserver/Ratekeeper.actor.cpp +++ b/fdbserver/Ratekeeper.actor.cpp @@ -180,9 +180,7 @@ public: myQueueInfo->value.smoothLatestVersion.setTotal(reply.get().version); } - myQueueInfo->value.busiestReadTag = reply.get().busiestTag; - myQueueInfo->value.busiestReadTagFractionalBusyness = reply.get().busiestTagFractionalBusyness; - myQueueInfo->value.busiestReadTagRate = reply.get().busiestTagRate; + myQueueInfo->value.busiestReadTags = reply.get().busiestTags; } else { if (myQueueInfo->value.valid) { TraceEvent("RkStorageServerDidNotRespond", self->id).detail("StorageServer", ssi.id()); @@ -974,7 +972,7 @@ Future Ratekeeper::refreshStorageServerCommitCost() { double elapsed = now() - lastBusiestCommitTagPick; // for each SS, select the busiest commit tag from ssTrTagCommitCost for (auto it = storageQueueInfo.begin(); it != storageQueueInfo.end(); ++it) { - it->value.busiestWriteTag.reset(); + it->value.busiestWriteTags.clear(); TransactionTag busiestTag; TransactionCommitCostEstimation maxCost; double maxRate = 0, maxBusyness = 0; @@ -987,12 +985,10 @@ Future Ratekeeper::refreshStorageServerCommitCost() { } } if (maxRate > SERVER_KNOBS->MIN_TAG_WRITE_PAGES_RATE) { - it->value.busiestWriteTag = busiestTag; // TraceEvent("RefreshSSCommitCost").detail("TotalWriteCost", it->value.totalWriteCost).detail("TotalWriteOps",it->value.totalWriteOps); - ASSERT(it->value.totalWriteCosts > 0); + ASSERT_GT(it->value.totalWriteCosts, 0); maxBusyness = double(maxCost.getCostSum()) / it->value.totalWriteCosts; - it->value.busiestWriteTagFractionalBusyness = maxBusyness; - it->value.busiestWriteTagRate = maxRate; + it->value.busiestWriteTags.emplace_back(busiestTag, maxBusyness, maxRate); } TraceEvent("BusiestWriteTag", it->key) @@ -1001,7 +997,7 @@ Future Ratekeeper::refreshStorageServerCommitCost() { .detail("TagOps", maxCost.getOpsSum()) .detail("TagCost", maxCost.getCostSum()) .detail("TotalCost", it->value.totalWriteCosts) - .detail("Reported", it->value.busiestWriteTag.present()) + .detail("Reported", !it->value.busiestWriteTags.empty()) .trackLatest(it->value.busiestWriteTagEventHolder->trackingKey); // reset statistics diff --git a/fdbserver/Ratekeeper.h b/fdbserver/Ratekeeper.h index 8552eeb521..d463ac0e1d 100644 --- a/fdbserver/Ratekeeper.h +++ b/fdbserver/Ratekeeper.h @@ -58,10 +58,7 @@ struct StorageQueueInfo { Smoother smoothTotalSpace; limitReason_t limitReason; - Optional busiestReadTag, busiestWriteTag; - double busiestReadTagFractionalBusyness = 0, busiestWriteTagFractionalBusyness = 0; - double busiestReadTagRate = 0, busiestWriteTagRate = 0; - + std::vector busiestReadTags, busiestWriteTags; Reference busiestWriteTagEventHolder; // refresh periodically diff --git a/fdbserver/TagThrottler.actor.cpp b/fdbserver/TagThrottler.actor.cpp index b531c6d102..0f48695ae6 100644 --- a/fdbserver/TagThrottler.actor.cpp +++ b/fdbserver/TagThrottler.actor.cpp @@ -544,16 +544,16 @@ public: // the future if (storageQueue > SERVER_KNOBS->AUTO_TAG_THROTTLE_STORAGE_QUEUE_BYTES || storageDurabilityLag > SERVER_KNOBS->AUTO_TAG_THROTTLE_DURABILITY_LAG_VERSIONS) { - if (ss.busiestWriteTag.present()) { - return tryAutoThrottleTag(ss.busiestWriteTag.get(), - ss.busiestWriteTagRate, - ss.busiestWriteTagFractionalBusyness, - TagThrottledReason::BUSY_WRITE); + for (const auto& busiestWriteTag : ss.busiestWriteTags) { + return tryAutoThrottleTag(busiestWriteTag.tag, + busiestWriteTag.rate, + busiestWriteTag.fractionalBusyness, + TagThrottledReason::BUSY_READ); } - if (ss.busiestReadTag.present()) { - return tryAutoThrottleTag(ss.busiestReadTag.get(), - ss.busiestReadTagRate, - ss.busiestReadTagFractionalBusyness, + for (const auto& busiestReadTag : ss.busiestReadTags) { + return tryAutoThrottleTag(busiestReadTag.tag, + busiestReadTag.rate, + busiestReadTag.fractionalBusyness, TagThrottledReason::BUSY_READ); } } diff --git a/fdbserver/TransactionTagCounter.cpp b/fdbserver/TransactionTagCounter.cpp index ecebaf5fad..f9215ea7cb 100644 --- a/fdbserver/TransactionTagCounter.cpp +++ b/fdbserver/TransactionTagCounter.cpp @@ -44,11 +44,11 @@ void TransactionTagCounter::addRequest(Optional const& tags, int64_t byt void TransactionTagCounter::startNewInterval() { double elapsed = now() - intervalStart; - previousBusiestTag.reset(); + previousBusiestTags.clear(); if (intervalStart > 0 && CLIENT_KNOBS->READ_TAG_SAMPLE_RATE > 0 && elapsed > 0) { double rate = busiestTagCount / CLIENT_KNOBS->READ_TAG_SAMPLE_RATE / elapsed; if (rate > SERVER_KNOBS->MIN_TAG_READ_PAGES_RATE) { - previousBusiestTag = TagInfo(busiestTag, rate, (double)busiestTagCount / intervalTotalSampledCount); + previousBusiestTags.emplace_back(busiestTag, rate, (double)busiestTagCount / intervalTotalSampledCount); } TraceEvent("BusiestReadTag", thisServerID) @@ -56,7 +56,7 @@ void TransactionTagCounter::startNewInterval() { .detail("Tag", printable(busiestTag)) .detail("TagCost", busiestTagCount) .detail("TotalSampledCost", intervalTotalSampledCount) - .detail("Reported", previousBusiestTag.present()) + .detail("Reported", !previousBusiestTags.empty()) .trackLatest(busiestReadTagEventHolder->trackingKey); } diff --git a/fdbserver/TransactionTagCounter.h b/fdbserver/TransactionTagCounter.h index 9fb00c6146..d520259c5c 100644 --- a/fdbserver/TransactionTagCounter.h +++ b/fdbserver/TransactionTagCounter.h @@ -20,28 +20,18 @@ #pragma once +#include "fdbclient/StorageServerInterface.h" #include "fdbclient/TagThrottle.actor.h" #include "fdbserver/Knobs.h" class TransactionTagCounter { -public: - struct TagInfo { - TransactionTag tag; - double rate; - double fractionalBusyness; - - TagInfo(TransactionTag const& tag, double rate, double fractionalBusyness) - : tag(tag), rate(rate), fractionalBusyness(fractionalBusyness) {} - }; - -private: TransactionTagMap intervalCounts; int64_t intervalTotalSampledCount = 0; TransactionTag busiestTag; int64_t busiestTagCount = 0; double intervalStart = 0; - Optional previousBusiestTag; + std::vector previousBusiestTags; UID thisServerID; Reference busiestReadTagEventHolder; @@ -50,5 +40,5 @@ public: static int64_t costFunction(int64_t bytes) { return bytes / SERVER_KNOBS->READ_COST_BYTE_FACTOR + 1; } void addRequest(Optional const& tags, int64_t bytes); void startNewInterval(); - Optional getBusiestTag() const { return previousBusiestTag; } + std::vector const& getBusiestTags() const { return previousBusiestTags; } }; diff --git a/fdbserver/storageserver.actor.cpp b/fdbserver/storageserver.actor.cpp index 8701ecdce2..783f122bd1 100644 --- a/fdbserver/storageserver.actor.cpp +++ b/fdbserver/storageserver.actor.cpp @@ -3574,11 +3574,7 @@ void getQueuingMetrics(StorageServer* self, StorageQueuingMetricsRequest const& reply.diskUsage = self->diskUsage; reply.durableVersion = self->durableVersion.get(); - Optional busiestTag = self->transactionTagCounter.getBusiestTag(); - reply.busiestTag = - busiestTag.map([](TransactionTagCounter::TagInfo tagInfo) { return tagInfo.tag; }); - reply.busiestTagFractionalBusyness = busiestTag.present() ? busiestTag.get().fractionalBusyness : 0.0; - reply.busiestTagRate = busiestTag.present() ? busiestTag.get().rate : 0.0; + reply.busiestTags = self->transactionTagCounter.getBusiestTags(); req.reply.send(reply); }