/* */ #include "SpeedCalc.h" #include #include #include "wallclock.h" namespace aria2 { #define CHANGE_INTERVAL_SEC 15 SpeedCalc::SpeedCalc():sw_(0), maxSpeed_(0), prevSpeed_(0), accumulatedLength_(0), nextInterval_(CHANGE_INTERVAL_SEC) { std::fill(&lengthArray_[0], &lengthArray_[2], 0); } void SpeedCalc::reset() { std::fill(&lengthArray_[0], &lengthArray_[2], 0); std::fill(&cpArray_[0], &cpArray_[2], global::wallclock); sw_ = 0; maxSpeed_ = 0; prevSpeed_ = 0; start_ = global::wallclock; accumulatedLength_ = 0; nextInterval_ = CHANGE_INTERVAL_SEC; } unsigned int SpeedCalc::calculateSpeed() { int64_t milliElapsed = cpArray_[sw_].differenceInMillis(global::wallclock); if(milliElapsed) { unsigned int speed = lengthArray_[sw_]*1000/milliElapsed; prevSpeed_ = speed; maxSpeed_ = std::max(speed, maxSpeed_); if(isIntervalOver(milliElapsed)) { changeSw(); } return speed; } else { return prevSpeed_; } } void SpeedCalc::update(size_t bytes) { accumulatedLength_ += bytes; std::transform(&lengthArray_[0], &lengthArray_[2], &lengthArray_[0], std::bind1st(std::plus(), (uint64_t)bytes)); if(isIntervalOver()) { changeSw(); } } bool SpeedCalc::isIntervalOver() const { return nextInterval_ <= cpArray_[sw_].difference(global::wallclock); } bool SpeedCalc::isIntervalOver(int64_t milliElapsed) const { return nextInterval_ <= milliElapsed/1000; } void SpeedCalc::changeSw() { lengthArray_[sw_] = 0; cpArray_[sw_] = global::wallclock; sw_ ^= 0x01u; nextInterval_ = cpArray_[sw_].difference(global::wallclock)+CHANGE_INTERVAL_SEC; } unsigned int SpeedCalc::calculateAvgSpeed() const { uint64_t milliElapsed = start_.differenceInMillis(global::wallclock); // if milliElapsed is too small, the average speed is rubish, better return 0 if(milliElapsed > 4) { unsigned int speed = accumulatedLength_*1000/milliElapsed; return speed; } else { return 0; } } } // namespace aria2