summaryrefslogtreecommitdiff
path: root/src/RequestGroupMan.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-03-16 21:26:15 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-03-16 21:26:15 +0900
commit1d9a4a8aec2483b112f4b8ec6d8f3d2f527c05ff (patch)
tree42b368c158a1574202de9a28efa53e497b159c49 /src/RequestGroupMan.cc
parentf0f1b8ef47c391550ff99982f1cad3dd4e1d410d (diff)
parent60d0cb0e24974534c10f63cf6833119b6af7be2b (diff)
Merge branch 'oliviercommelarbre-optimize-concurrent-downloads'
Diffstat (limited to 'src/RequestGroupMan.cc')
-rw-r--r--src/RequestGroupMan.cc74
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