/* */ #include "SpeedCalc.h" #include #include #include "wallclock.h" namespace aria2 { namespace { constexpr auto WINDOW_TIME = 15_s; } // namespace SpeedCalc::SpeedCalc() : accumulatedLength_(0), bytesWindow_(0), maxSpeed_(0) {} void SpeedCalc::reset() { timeSlots_.clear(); start_ = global::wallclock(); accumulatedLength_ = 0; bytesWindow_ = 0; maxSpeed_ = 0; } void SpeedCalc::removeStaleTimeSlot(const Timer& now) { while (!timeSlots_.empty()) { if (timeSlots_[0].first.difference(now) <= WINDOW_TIME) { break; } bytesWindow_ -= timeSlots_[0].second; timeSlots_.pop_front(); } } int SpeedCalc::calculateSpeed() { const auto& now = global::wallclock(); removeStaleTimeSlot(now); if (timeSlots_.empty()) { return 0; } auto elapsed = std::chrono::duration_cast( timeSlots_[0].first.difference(now)).count(); if (elapsed <= 0) { elapsed = 1; } int speed = bytesWindow_ * 1000 / elapsed; maxSpeed_ = std::max(speed, maxSpeed_); return speed; } void SpeedCalc::update(size_t bytes) { const auto& now = global::wallclock(); removeStaleTimeSlot(now); if (timeSlots_.empty() || std::chrono::duration_cast( timeSlots_.back().first.difference(now)) >= 1_s) { timeSlots_.push_back(std::make_pair(now, bytes)); } else { timeSlots_.back().second += bytes; } bytesWindow_ += bytes; accumulatedLength_ += bytes; } int SpeedCalc::calculateAvgSpeed() const { auto milliElapsed = std::chrono::duration_cast( start_.difference(global::wallclock())).count(); // if milliElapsed is too small, the average speed is rubbish, better // return 0 if (milliElapsed > 4) { int speed = accumulatedLength_ * 1000 / milliElapsed; return speed; } else { return 0; } } } // namespace aria2