Made HTTP/FTP download speed limiter more accurate

We have to do the same thing for BitTorrent.
pull/31/head
Tatsuhiro Tsujikawa 2012-10-24 00:59:32 +09:00
parent ea456001d3
commit 46bdaf0e8d
7 changed files with 17 additions and 51 deletions

View File

@ -177,7 +177,6 @@ bool DownloadCommand::executeInternal() {
getSocketRecvBuffer()->shiftBuffer(bufSize); getSocketRecvBuffer()->shiftBuffer(bufSize);
peerStat_->updateDownloadLength(bufSize); peerStat_->updateDownloadLength(bufSize);
} }
getSegmentMan()->updateDownloadSpeedFor(peerStat_);
bool segmentPartComplete = false; bool segmentPartComplete = false;
// Note that GrowSegment::complete() always returns false. // Note that GrowSegment::complete() always returns false.
if(sinkFilterOnly_) { if(sinkFilterOnly_) {

View File

@ -130,4 +130,9 @@ void PeerStat::downloadStop()
status_ = PeerStat::IDLE; status_ = PeerStat::IDLE;
} }
bool PeerStat::affectsOverallSpeed() const
{
return !downloadSpeed_.isIntervalOver();
}
} // namespace aria2 } // namespace aria2

View File

@ -149,6 +149,10 @@ public:
{ {
sessionDownloadLength_ += length; sessionDownloadLength_ += length;
} }
// Returns true if the download speed of this object still affects
// overall download speed statistics.
bool affectsOverallSpeed() const;
}; };
} // namespace aria2 } // namespace aria2

View File

@ -69,8 +69,6 @@ SegmentMan::SegmentMan
: option_(option), : option_(option),
downloadContext_(downloadContext), downloadContext_(downloadContext),
pieceStorage_(pieceStorage), pieceStorage_(pieceStorage),
lastPeerStatDlspdMapUpdated_(0),
cachedDlspd_(0),
ignoreBitfield_(downloadContext->getPieceLength(), ignoreBitfield_(downloadContext->getPieceLength(),
downloadContext->getTotalLength()) downloadContext->getTotalLength())
{ {
@ -350,13 +348,6 @@ int64_t SegmentMan::getDownloadLength() const {
void SegmentMan::registerPeerStat(const SharedHandle<PeerStat>& peerStat) void SegmentMan::registerPeerStat(const SharedHandle<PeerStat>& peerStat)
{ {
for(std::vector<SharedHandle<PeerStat> >::iterator i = peerStats_.begin(),
eoi = peerStats_.end(); i != eoi; ++i) {
if((*i)->getStatus() == PeerStat::IDLE) {
*i = peerStat;
return;
}
}
peerStats_.push_back(peerStat); peerStats_.push_back(peerStat);
} }
@ -407,38 +398,17 @@ void SegmentMan::updateFastestPeerStat(const SharedHandle<PeerStat>& peerStat)
int SegmentMan::calculateDownloadSpeed() int SegmentMan::calculateDownloadSpeed()
{ {
int speed = 0; int speed = 0;
if(lastPeerStatDlspdMapUpdated_.differenceInMillis(global::wallclock())+ for(std::vector<SharedHandle<PeerStat> >::const_iterator i =
A2_DELTA_MILLIS >= 250){ peerStats_.begin(), eoi = peerStats_.end(); i != eoi; ++i) {
lastPeerStatDlspdMapUpdated_ = global::wallclock(); // PeerStat which is IDLE but its last download speed calculation
peerStatDlspdMap_.clear(); // interval is not over must be added to the result.
for(std::vector<SharedHandle<PeerStat> >::const_iterator i = if((*i)->getStatus() == PeerStat::ACTIVE || (*i)->affectsOverallSpeed()) {
peerStats_.begin(), eoi = peerStats_.end(); i != eoi; ++i) { speed += (*i)->calculateDownloadSpeed();
if((*i)->getStatus() == PeerStat::ACTIVE) {
int s = (*i)->calculateDownloadSpeed();
peerStatDlspdMap_[(*i)->getCuid()] = s;
speed += s;
}
} }
cachedDlspd_ = speed;
} else {
speed = cachedDlspd_;
} }
return speed; return speed;
} }
void SegmentMan::updateDownloadSpeedFor(const SharedHandle<PeerStat>& pstat)
{
int newspd = pstat->calculateDownloadSpeed();
int oldSpd = peerStatDlspdMap_[pstat->getCuid()];
if(cachedDlspd_ > oldSpd) {
cachedDlspd_ -= oldSpd;
cachedDlspd_ += newspd;
} else {
cachedDlspd_ = newspd;
}
peerStatDlspdMap_[pstat->getCuid()] = newspd;
}
namespace { namespace {
class PeerStatDownloadLengthOperator { class PeerStatDownloadLengthOperator {
public: public:

View File

@ -93,13 +93,6 @@ private:
// Keep track of fastest PeerStat for each server // Keep track of fastest PeerStat for each server
std::vector<SharedHandle<PeerStat> > fastestPeerStats_; std::vector<SharedHandle<PeerStat> > fastestPeerStats_;
// key: PeerStat's cuid, value: its download speed
std::map<cuid_t, int> peerStatDlspdMap_;
Timer lastPeerStatDlspdMapUpdated_;
int cachedDlspd_;
BitfieldMan ignoreBitfield_; BitfieldMan ignoreBitfield_;
SharedHandle<Segment> checkoutSegment(cuid_t cuid, SharedHandle<Segment> checkoutSegment(cuid_t cuid,
@ -232,8 +225,6 @@ public:
*/ */
int calculateDownloadSpeed(); int calculateDownloadSpeed();
void updateDownloadSpeedFor(const SharedHandle<PeerStat>& pstat);
/** /**
* Returns the downloaded bytes in this session. * Returns the downloaded bytes in this session.
*/ */

View File

@ -51,14 +51,14 @@ private:
int64_t accumulatedLength_; int64_t accumulatedLength_;
time_t nextInterval_; time_t nextInterval_;
bool isIntervalOver() const;
bool isIntervalOver(int64_t milliElapsed) const; bool isIntervalOver(int64_t milliElapsed) const;
void changeSw(); void changeSw();
public: public:
SpeedCalc(); SpeedCalc();
bool isIntervalOver() const;
/** /**
* Returns download/upload speed in byte per sec * Returns download/upload speed in byte per sec
*/ */

View File

@ -157,9 +157,6 @@ void SegmentManTest::testRegisterPeerStat()
CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size()); CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size());
SharedHandle<PeerStat> p2(new PeerStat(0, "host2", "http")); SharedHandle<PeerStat> p2(new PeerStat(0, "host2", "http"));
segman.registerPeerStat(p2); segman.registerPeerStat(p2);
CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size());
p2->downloadStart();
segman.registerPeerStat(p1);
CPPUNIT_ASSERT_EQUAL((size_t)2, segman.getPeerStats().size()); CPPUNIT_ASSERT_EQUAL((size_t)2, segman.getPeerStats().size());
} }