diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2016-03-16 21:26:15 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2016-03-16 21:26:15 +0900 |
| commit | 1d9a4a8aec2483b112f4b8ec6d8f3d2f527c05ff (patch) | |
| tree | 42b368c158a1574202de9a28efa53e497b159c49 /src/RequestGroupMan.cc | |
| parent | f0f1b8ef47c391550ff99982f1cad3dd4e1d410d (diff) | |
| parent | 60d0cb0e24974534c10f63cf6833119b6af7be2b (diff) | |
Merge branch 'oliviercommelarbre-optimize-concurrent-downloads'
Diffstat (limited to 'src/RequestGroupMan.cc')
| -rw-r--r-- | src/RequestGroupMan.cc | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc index fa7723ce..824e1ea2 100644 --- a/src/RequestGroupMan.cc +++ b/src/RequestGroupMan.cc @@ -83,6 +83,7 @@ #include "SimpleRandomizer.h" #include "array_fun.h" #include "OpenedFileCounter.h" +#include "wallclock.h" #ifdef ENABLE_BITTORRENT #include "bittorrent_helper.h" #endif // ENABLE_BITTORRENT @@ -102,8 +103,12 @@ void appendReservedGroup(RequestGroupList& list, InputIterator first, RequestGroupMan::RequestGroupMan( std::vector<std::shared_ptr<RequestGroup>> requestGroups, - int maxSimultaneousDownloads, const Option* option) - : maxSimultaneousDownloads_(maxSimultaneousDownloads), + int maxConcurrentDownloads, const Option* option) + : maxConcurrentDownloads_(maxConcurrentDownloads), + optimizeConcurrentDownloads_(false), + optimizeConcurrentDownloadsCoeffA_(5.), + optimizeConcurrentDownloadsCoeffB_(25.), + optimizationSpeed_(0), numActive_(0), option_(option), serverStatMan_(std::make_shared<ServerStatMan>()), @@ -120,12 +125,25 @@ RequestGroupMan::RequestGroupMan( this, option->getAsInt(PREF_BT_MAX_OPEN_FILES))), numStoppedTotal_(0) { + setupOptimizeConcurrentDownloads(); appendReservedGroup(reservedGroups_, requestGroups.begin(), requestGroups.end()); } RequestGroupMan::~RequestGroupMan() { openedFileCounter_->deactivate(); } +bool RequestGroupMan::setupOptimizeConcurrentDownloads(void) +{ + optimizeConcurrentDownloads_ = option_->getAsBool(PREF_OPTIMIZE_CONCURRENT_DOWNLOADS); + if (optimizeConcurrentDownloads_) { + if (option_->defined(PREF_OPTIMIZE_CONCURRENT_DOWNLOADS_COEFFA)) { + optimizeConcurrentDownloadsCoeffA_ = std::stod(option_->get(PREF_OPTIMIZE_CONCURRENT_DOWNLOADS_COEFFA)); + optimizeConcurrentDownloadsCoeffB_ = std::stod(option_->get(PREF_OPTIMIZE_CONCURRENT_DOWNLOADS_COEFFB)); + } + } + return optimizeConcurrentDownloads_; +} + bool RequestGroupMan::downloadFinished() { if (keepRunning_) { @@ -474,11 +492,14 @@ createInitialCommand(const std::shared_ptr<RequestGroup>& requestGroup, void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e) { removeStoppedGroup(e); - if (static_cast<size_t>(maxSimultaneousDownloads_) <= numActive_) { + + int maxConcurrentDownloads = optimizeConcurrentDownloads_ ? optimizeConcurrentDownloads() : maxConcurrentDownloads_; + + if (static_cast<size_t>(maxConcurrentDownloads) <= numActive_) { return; } int count = 0; - int num = maxSimultaneousDownloads_ - numActive_; + int num = maxConcurrentDownloads - numActive_; std::vector<std::shared_ptr<RequestGroup>> pending; while (count < num && (uriListParser_ || !reservedGroups_.empty())) { @@ -1005,4 +1026,49 @@ void RequestGroupMan::decreaseNumActive() --numActive_; } + +int RequestGroupMan::optimizeConcurrentDownloads() +{ + // gauge the current speed + int currentSpeed = getNetStat().calculateDownloadSpeed(); + + const auto& now = global::wallclock(); + if (currentSpeed >= optimizationSpeed_) { + optimizationSpeed_ = currentSpeed; + optimizationSpeedTimer_ = now; + } else if (std::chrono::duration_cast<std::chrono::seconds>(optimizationSpeedTimer_.difference(now)) >= 5_s) { + // we keep using the reference speed for minimum 5 seconds so reset the timer + optimizationSpeedTimer_ = now; + + // keep the reference speed as long as the speed tends to augment or to maintain itself within 10% + if (currentSpeed >= 1.1 * getNetStat().calculateNewestDownloadSpeed(5)) { + // else assume a possible congestion and record a new optimization speed by dichotomy + optimizationSpeed_ = (optimizationSpeed_ + currentSpeed)/2.; + } + } + + if (optimizationSpeed_ <= 0) { + return 1; + } + + // apply the rule + if ((maxOverallDownloadSpeedLimit_ > 0) && (optimizationSpeed_ > maxOverallDownloadSpeedLimit_)) { + optimizationSpeed_ = maxOverallDownloadSpeedLimit_; + } + int maxConcurrentDownloads = ceil( + optimizeConcurrentDownloadsCoeffA_ + + optimizeConcurrentDownloadsCoeffB_ * log10(optimizationSpeed_ * 8. / 1000000.) + ); + + // bring the value in bound between 1 and the defined maximum + maxConcurrentDownloads = std::min(std::max(1, maxConcurrentDownloads), maxConcurrentDownloads_); + + A2_LOG_DEBUG + (fmt("Max concurrent downloads optimized at %d (%lu currently active) " + "[optimization speed %sB/s, current speed %sB/s]", + maxConcurrentDownloads, numActive_, util::abbrevSize(optimizationSpeed_).c_str(), + util::abbrevSize(currentSpeed).c_str())); + + return maxConcurrentDownloads; +} } // namespace aria2 |
