Check request duration when adding sessions.

This commit is contained in:
John Preston 2019-12-05 16:38:28 +03:00
parent e426f2895b
commit 7fb24d77c0
2 changed files with 47 additions and 17 deletions

View File

@ -18,7 +18,8 @@ namespace Storage {
namespace { namespace {
constexpr auto kKillSessionTimeout = 15 * crl::time(1000); constexpr auto kKillSessionTimeout = 15 * crl::time(1000);
constexpr auto kMaxWaitedInSession = 2 * 1024 * 1024; constexpr auto kStartWaitedInSession = 4 * kDownloadPartSize;
constexpr auto kMaxWaitedInSession = 16 * kDownloadPartSize;
constexpr auto kStartSessionsCount = 1; constexpr auto kStartSessionsCount = 1;
constexpr auto kMaxSessionsCount = 8; constexpr auto kMaxSessionsCount = 8;
constexpr auto kMaxTrackedSessionRemoves = 64; constexpr auto kMaxTrackedSessionRemoves = 64;
@ -28,10 +29,13 @@ constexpr auto kMaxTrackedSuccesses = kRetryAddSessionSuccesses
* kMaxTrackedSessionRemoves; * kMaxTrackedSessionRemoves;
constexpr auto kRemoveSessionAfterTimeouts = 2; constexpr auto kRemoveSessionAfterTimeouts = 2;
constexpr auto kResetDownloadPrioritiesTimeout = crl::time(200); constexpr auto kResetDownloadPrioritiesTimeout = crl::time(200);
constexpr auto kGrowMaxWaitedDurationThreshold = crl::time(500);
constexpr auto kGrowSessionsDurationThreshold = crl::time(500);
constexpr auto kBadRequestDurationThreshold = crl::time(2000);
// Each session remove by timeouts we wait for time // Each (session remove by timeouts) we wait for time:
// kRetryAddSessionTimeout * max(removesCount, kMaxTrackedSessionRemoves) // kRetryAddSessionTimeout * max(removesCount, kMaxTrackedSessionRemoves)
// and for successes in all remaining sessions // and for successes in all remaining sessions:
// kRetryAddSessionSuccesses * max(removesCount, kMaxTrackedSessionRemoves) // kRetryAddSessionSuccesses * max(removesCount, kMaxTrackedSessionRemoves)
} // namespace } // namespace
@ -77,7 +81,7 @@ auto DownloadManagerMtproto::Queue::nextTask() const -> Task* {
} }
DownloadManagerMtproto::DcSessionBalanceData::DcSessionBalanceData() DownloadManagerMtproto::DcSessionBalanceData::DcSessionBalanceData()
: maxWaitedAmount(kDownloadPartSize) { : maxWaitedAmount(kStartWaitedInSession) {
} }
DownloadManagerMtproto::DcBalanceData::DcBalanceData() DownloadManagerMtproto::DcBalanceData::DcBalanceData()
@ -184,19 +188,44 @@ void DownloadManagerMtproto::changeRequestedAmount(
} }
} }
void DownloadManagerMtproto::requestSucceeded(MTP::DcId dcId, int index) { void DownloadManagerMtproto::requestSucceeded(
MTP::DcId dcId,
int index,
crl::time duration) {
using namespace rpl::mappers; using namespace rpl::mappers;
DEBUG_LOG(("Download (%1,%2) request done.").arg(dcId).arg(index)); DEBUG_LOG(("Download (%1,%2) request done, duration %3."
).arg(dcId
).arg(index
).arg(duration));
const auto i = _balanceData.find(dcId); const auto i = _balanceData.find(dcId);
Assert(i != end(_balanceData)); Assert(i != end(_balanceData));
auto &dc = i->second; auto &dc = i->second;
Assert(index < dc.sessions.size()); Assert(index < dc.sessions.size());
auto &data = dc.sessions[index]; auto &data = dc.sessions[index];
data.successes = std::min(data.successes + 1, kMaxTrackedSuccesses); const auto guard = gsl::finally([&] {
checkSendNext(dcId, _queues[dcId]);
});
const auto parts = data.maxWaitedAmount / kDownloadPartSize;
if (duration < kGrowMaxWaitedDurationThreshold * parts) {
if (data.maxWaitedAmount < kMaxWaitedInSession) {
data.maxWaitedAmount = std::min( data.maxWaitedAmount = std::min(
data.maxWaitedAmount + kDownloadPartSize, data.maxWaitedAmount + kDownloadPartSize,
kMaxWaitedInSession); kMaxWaitedInSession);
DEBUG_LOG(("Download (%1,%2) increased max waited amount %3."
).arg(dcId
).arg(index
).arg(data.maxWaitedAmount));
}
}
if (duration >= kBadRequestDurationThreshold * parts) {
DEBUG_LOG(("Duration too large, signaling time out."));
sessionTimedOut(dcId, index);
return;
} else if (duration >= kGrowSessionsDurationThreshold * parts) {
return;
}
data.successes = std::min(data.successes + 1, kMaxTrackedSuccesses);
const auto notEnough = ranges::find_if( const auto notEnough = ranges::find_if(
dc.sessions, dc.sessions,
_1 < (dc.sessionRemoveTimes + 1) * kRetryAddSessionSuccesses, _1 < (dc.sessionRemoveTimes + 1) * kRetryAddSessionSuccesses,
@ -222,7 +251,6 @@ void DownloadManagerMtproto::requestSucceeded(MTP::DcId dcId, int index) {
).arg(dcId ).arg(dcId
).arg(dc.sessions.size())); ).arg(dc.sessions.size()));
dc.sessions.emplace_back(); dc.sessions.emplace_back();
checkSendNext(dcId, _queues[dcId]);
} }
void DownloadManagerMtproto::sessionTimedOut(MTP::DcId dcId, int index) { void DownloadManagerMtproto::sessionTimedOut(MTP::DcId dcId, int index) {
@ -588,8 +616,6 @@ void DownloadMtprotoTask::getCdnFileHashesDone(
mtpRequestId requestId) { mtpRequestId requestId) {
Expects(_cdnHashesRequestId == requestId); Expects(_cdnHashesRequestId == requestId);
_cdnHashesRequestId = 0;
const auto requestData = finishSentRequest( const auto requestData = finishSentRequest(
requestId, requestId,
FinishRequestReason::Redirect); FinishRequestReason::Redirect);
@ -648,6 +674,8 @@ void DownloadMtprotoTask::placeSentRequest(
requestData.offset, requestData.offset,
requestId); requestId);
i->second.sent = crl::now();
Ensures(ok1 && ok2); Ensures(ok1 && ok2);
} }
@ -658,6 +686,9 @@ auto DownloadMtprotoTask::finishSentRequest(
auto it = _sentRequests.find(requestId); auto it = _sentRequests.find(requestId);
Assert(it != _sentRequests.cend()); Assert(it != _sentRequests.cend());
if (_cdnHashesRequestId == requestId) {
_cdnHashesRequestId = 0;
}
const auto result = it->second; const auto result = it->second;
_owner->changeRequestedAmount( _owner->changeRequestedAmount(
dcId(), dcId(),
@ -667,7 +698,8 @@ auto DownloadMtprotoTask::finishSentRequest(
const auto ok = _requestByOffset.remove(result.offset); const auto ok = _requestByOffset.remove(result.offset);
if (reason == FinishRequestReason::Success) { if (reason == FinishRequestReason::Success) {
_owner->requestSucceeded(dcId(), result.dcIndex); const auto duration = crl::now() - result.sent;
_owner->requestSucceeded(dcId(), result.dcIndex, duration);
} }
Ensures(ok); Ensures(ok);
@ -755,9 +787,6 @@ bool DownloadMtprotoTask::cdnPartFailed(
return false; return false;
} }
if (requestId == _cdnHashesRequestId) {
_cdnHashesRequestId = 0;
}
if (error.type() == qstr("FILE_TOKEN_INVALID") if (error.type() == qstr("FILE_TOKEN_INVALID")
|| error.type() == qstr("REQUEST_TOKEN_INVALID")) { || error.type() == qstr("REQUEST_TOKEN_INVALID")) {
const auto requestData = finishSentRequest( const auto requestData = finishSentRequest(

View File

@ -43,7 +43,7 @@ public:
} }
void changeRequestedAmount(MTP::DcId dcId, int index, int delta); void changeRequestedAmount(MTP::DcId dcId, int index, int delta);
void requestSucceeded(MTP::DcId dcId, int index); void requestSucceeded(MTP::DcId dcId, int index, crl::time duration);
private: private:
class Queue final { class Queue final {
@ -153,6 +153,7 @@ private:
struct RequestData { struct RequestData {
int offset = 0; int offset = 0;
int dcIndex = 0; int dcIndex = 0;
crl::time sent = 0;
inline bool operator<(const RequestData &other) const { inline bool operator<(const RequestData &other) const {
return offset < other.offset; return offset < other.offset;