/* */ #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 ^= 0x01; _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