Skip to content

Commit

Permalink
Reworked download/upload statistics calculation
Browse files Browse the repository at this point in the history
The old implementation calculates download/upload statistics for a
RequestGroup by summing up all PeerStat objects. For global
statistics, those are summed together. This clearly incurs runtime
penalty and we introduced some kind of caching which updates
statistics every 250ms but it did not work right.

This change removes all these aggregation code, and instead makes
RequestGroup and RequestGroupMan objects hold NetStat object and
download/upload bytes are directly calculated by thier own NetStat.
This is far more simplar than the old way and less runtime penalty and
brings more accuracy.
  • Loading branch information
tatsuhiro-t committed Oct 25, 2012
1 parent 46bdaf0 commit 0ecfa19
Show file tree
Hide file tree
Showing 38 changed files with 434 additions and 340 deletions.
2 changes: 1 addition & 1 deletion src/AbstractCommand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ void AbstractCommand::onAbort() {
// limitation of current implementation.
if(!getOption()->getAsBool(PREF_ALWAYS_RESUME) &&
fileEntry_ &&
getSegmentMan()->calculateSessionDownloadLength() == 0 &&
getDownloadContext()->getNetStat().getSessionDownloadLength() == 0 &&
!requestGroup_->p2pInvolved() &&
getDownloadContext()->getFileEntries().size() == 1) {
const int maxTries = getOption()->getAsInt(PREF_MAX_RESUME_FAILURE_TRIES);
Expand Down
2 changes: 2 additions & 0 deletions src/BtPieceMessage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ void BtPieceMessage::doReceivedAction()
RequestSlot slot = getBtMessageDispatcher()->getOutstandingRequest
(index_, begin_, blockLength_);
getPeer()->updateDownloadLength(blockLength_);
downloadContext_->updateDownloadLength(blockLength_);
if(!RequestSlot::isNull(slot)) {
getPeer()->snubbing(false);
SharedHandle<Piece> piece = getPieceStorage()->getPiece(index_);
Expand Down Expand Up @@ -188,6 +189,7 @@ void BtPieceMessage::send()
}
writtenLength = getPeerConnection()->sendPendingData();
getPeer()->updateUploadLength(writtenLength);
downloadContext_->updateUploadLength(writtenLength);
setSendingInProgress(!getPeerConnection()->sendBufferIsEmpty());
}

Expand Down
2 changes: 1 addition & 1 deletion src/BtSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ void BtSetup::setup(std::vector<Command*>& commands,
(new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO),
requestGroup->getDownloadContext()));
cri->setPieceStorage(pieceStorage);
cri->setPeerStorage(peerStorage);
cri->setBtRuntime(btRuntime);

unionCri->addSeedCriteria(cri);
}
Expand Down
6 changes: 2 additions & 4 deletions src/ConsoleStatCalc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,8 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e)

if(e->getRequestGroupMan()->countRequestGroup() > 1 &&
!e->getRequestGroupMan()->downloadFinished()) {
TransferStat stat = e->getRequestGroupMan()->calculateStat();
o << " "
<< "[TOTAL SPD:"
<< sizeFormatter(stat.getDownloadSpeed()) << "Bs" << "]";
int spd = e->getRequestGroupMan()->getNetStat().calculateDownloadSpeed();
o << " [TOTAL SPD:" << sizeFormatter(spd) << "Bs" << "]";
}

{
Expand Down
2 changes: 1 addition & 1 deletion src/DefaultBtAnnounce.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ std::string DefaultBtAnnounce::getAnnounceUrl() {
if(!btRuntime_->lessThanMinPeers() || btRuntime_->isHalt()) {
numWant = 0;
}
TransferStat stat = peerStorage_->calculateStat();
NetStat& stat = downloadContext_->getNetStat();
int64_t left =
pieceStorage_->getTotalLength()-pieceStorage_->getCompletedLength();
// Use last 8 bytes of peer ID as a key
Expand Down
2 changes: 0 additions & 2 deletions src/DefaultBtInteractive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,6 @@ size_t DefaultBtInteractive::receiveMessages() {
}
break;
case BtPieceMessage::ID:
peerStorage_->updateTransferStatFor(peer_);
// pass through
case BtRequestMessage::ID:
inactiveTimer_ = global::wallclock();
break;
Expand Down
3 changes: 0 additions & 3 deletions src/DefaultBtMessageDispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ void DefaultBtMessageDispatcher::sendMessages() {
}
}
msg->send();
if(msg->isUploading()) {
peerStorage_->updateTransferStatFor(peer_);
}
if(msg->isSendingInProgress()) {
messageQueue_.push_front(msg);
break;
Expand Down
4 changes: 2 additions & 2 deletions src/DefaultBtProgressInfoFile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ void DefaultBtProgressInfoFile::save()
uint64_t uploadLengthNL = 0;
#ifdef ENABLE_BITTORRENT
if(torrentDownload) {
TransferStat stat = peerStorage_->calculateStat();
uploadLengthNL = hton64(stat.getAllTimeUploadLength());
uploadLengthNL = hton64(btRuntime_->getUploadLengthAtStartup()+
dctx_->getNetStat().getSessionUploadLength());
}
#endif // ENABLE_BITTORRENT
WRITE_CHECK(fp, &uploadLengthNL, sizeof(uploadLengthNL));
Expand Down
77 changes: 0 additions & 77 deletions src/DefaultPeerStorage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ const size_t MAX_PEER_LIST_UPDATE = 100;

DefaultPeerStorage::DefaultPeerStorage()
: maxPeerListSize_(MAX_PEER_LIST_SIZE),
removedPeerSessionDownloadLength_(0LL),
removedPeerSessionUploadLength_(0LL),
seederStateChoke_(new BtSeederStateChoke()),
leecherStateChoke_(new BtLeecherStateChoke()),
lastTransferStatMapUpdated_(0)
Expand Down Expand Up @@ -241,76 +239,6 @@ void DefaultPeerStorage::getActivePeers
std::for_each(peers_.begin(), peers_.end(), CollectActivePeer(activePeers));
}

namespace {
TransferStat calculateStatFor(const SharedHandle<Peer>& peer)
{
TransferStat s;
s.downloadSpeed = peer->calculateDownloadSpeed();
s.uploadSpeed = peer->calculateUploadSpeed();
s.sessionDownloadLength = peer->getSessionDownloadLength();
s.sessionUploadLength = peer->getSessionUploadLength();
return s;
}
} // namespace

TransferStat DefaultPeerStorage::calculateStat()
{
TransferStat stat;
if(lastTransferStatMapUpdated_.differenceInMillis(global::wallclock())+
A2_DELTA_MILLIS >= 250) {
A2_LOG_DEBUG("Updating TransferStat of PeerStorage");
lastTransferStatMapUpdated_ = global::wallclock();
peerTransferStatMap_.clear();
std::vector<SharedHandle<Peer> > activePeers;
getActivePeers(activePeers);
for(std::vector<SharedHandle<Peer> >::const_iterator i =
activePeers.begin(), eoi = activePeers.end(); i != eoi; ++i) {
TransferStat s;
s.downloadSpeed = (*i)->calculateDownloadSpeed();
s.uploadSpeed = (*i)->calculateUploadSpeed();
s.sessionDownloadLength = (*i)->getSessionDownloadLength();
s.sessionUploadLength = (*i)->getSessionUploadLength();

peerTransferStatMap_[(*i)->getID()] = calculateStatFor(*i);
stat += s;
}
cachedTransferStat_ = stat;
} else {
stat = cachedTransferStat_;
}
stat.sessionDownloadLength += removedPeerSessionDownloadLength_;
stat.sessionUploadLength += removedPeerSessionUploadLength_;
stat.setAllTimeUploadLength(btRuntime_->getUploadLengthAtStartup()+
stat.getSessionUploadLength());
return stat;
}

void DefaultPeerStorage::updateTransferStatFor(const SharedHandle<Peer>& peer)
{
A2_LOG_DEBUG(fmt("Updating TransferStat for peer %s", peer->getID().c_str()));
std::map<std::string, TransferStat>::iterator itr =
peerTransferStatMap_.find(peer->getID());
if(itr == peerTransferStatMap_.end()) {
return;
}
cachedTransferStat_ -= (*itr).second;
TransferStat s = calculateStatFor(peer);
cachedTransferStat_ += s;
(*itr).second = s;
}

TransferStat DefaultPeerStorage::getTransferStatFor
(const SharedHandle<Peer>& peer)
{
std::map<std::string, TransferStat>::const_iterator itr =
peerTransferStatMap_.find(peer->getID());
if(itr == peerTransferStatMap_.end()) {
return TransferStat();
} else {
return (*itr).second;
}
}

bool DefaultPeerStorage::isBadPeer(const std::string& ipaddr)
{
std::map<std::string, time_t>::iterator i = badPeers_.find(ipaddr);
Expand Down Expand Up @@ -365,11 +293,6 @@ void DefaultPeerStorage::onErasingPeer(const SharedHandle<Peer>& peer) {}
void DefaultPeerStorage::onReturningPeer(const SharedHandle<Peer>& peer)
{
if(peer->isActive()) {
TransferStat removedStat(calculateStatFor(peer));
removedPeerSessionDownloadLength_ += removedStat.getSessionDownloadLength();
removedPeerSessionUploadLength_ += removedStat.getSessionUploadLength();
cachedTransferStat_ -= removedStat;

if(peer->isDisconnectedGracefully() && !peer->isIncomingPeer()) {
peer->startBadCondition();
addDroppedPeer(peer);
Expand Down
12 changes: 0 additions & 12 deletions src/DefaultPeerStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,12 @@ class DefaultPeerStorage : public PeerStorage {
size_t maxPeerListSize_;
std::deque<SharedHandle<Peer> > peers_;
std::deque<SharedHandle<Peer> > droppedPeers_;
int64_t removedPeerSessionDownloadLength_;
int64_t removedPeerSessionUploadLength_;

BtSeederStateChoke* seederStateChoke_;
BtLeecherStateChoke* leecherStateChoke_;

std::map<std::string, TransferStat> peerTransferStatMap_;

Timer lastTransferStatMapUpdated_;

TransferStat cachedTransferStat_;

std::map<std::string, time_t> badPeers_;
Timer lastBadPeerCleaned_;

Expand Down Expand Up @@ -97,12 +91,6 @@ class DefaultPeerStorage : public PeerStorage {

virtual void getActivePeers(std::vector<SharedHandle<Peer> >& peers);

virtual TransferStat calculateStat();

virtual void updateTransferStatFor(const SharedHandle<Peer>& peer);

virtual TransferStat getTransferStatFor(const SharedHandle<Peer>& peer);

virtual bool isBadPeer(const std::string& ipaddr);

virtual void addBadPeer(const std::string& ipaddr);
Expand Down
1 change: 1 addition & 0 deletions src/DownloadCommand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ bool DownloadCommand::executeInternal() {
}
getSocketRecvBuffer()->shiftBuffer(bufSize);
peerStat_->updateDownloadLength(bufSize);
getDownloadContext()->updateDownloadLength(bufSize);
}
bool segmentPartComplete = false;
// Note that GrowSegment::complete() always returns false.
Expand Down
34 changes: 24 additions & 10 deletions src/DownloadContext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "DlAbortEx.h"
#include "a2functional.h"
#include "Signature.h"
#include "RequestGroupMan.h"

namespace aria2 {

Expand All @@ -52,8 +53,7 @@ DownloadContext::DownloadContext():
knowsTotalLength_(true),
ownerRequestGroup_(0),
attrs_(MAX_CTX_ATTR),
downloadStartTime_(0),
downloadStopTime_(downloadStartTime_),
downloadStopTime_(0),
acceptMetalink_(true) {}

DownloadContext::DownloadContext(int32_t pieceLength,
Expand All @@ -64,7 +64,6 @@ DownloadContext::DownloadContext(int32_t pieceLength,
knowsTotalLength_(true),
ownerRequestGroup_(0),
attrs_(MAX_CTX_ATTR),
downloadStartTime_(0),
downloadStopTime_(0),
acceptMetalink_(true)
{
Expand All @@ -76,23 +75,20 @@ DownloadContext::~DownloadContext() {}

void DownloadContext::resetDownloadStartTime()
{
downloadStartTime_ = global::wallclock();
downloadStopTime_.reset(0);
netStat_.downloadStart();
}

void DownloadContext::resetDownloadStopTime()
{
downloadStopTime_ = global::wallclock();
netStat_.downloadStop();
}

int64_t DownloadContext::calculateSessionTime() const
{
if(downloadStopTime_ > downloadStartTime_) {
return
downloadStartTime_.differenceInMillis(downloadStopTime_);
} else {
return 0;
}
const Timer& startTime = netStat_.getDownloadStartTime();
return startTime.differenceInMillis(downloadStopTime_);
}

SharedHandle<FileEntry>
Expand Down Expand Up @@ -283,4 +279,22 @@ void DownloadContext::setSignature(const SharedHandle<Signature>& signature)
signature_ = signature;
}

void DownloadContext::updateDownloadLength(size_t bytes)
{
netStat_.updateDownloadLength(bytes);
RequestGroupMan* rgman = ownerRequestGroup_->getRequestGroupMan();
if(rgman) {
rgman->getNetStat().updateDownloadLength(bytes);
}
}

void DownloadContext::updateUploadLength(size_t bytes)
{
netStat_.updateUploadLength(bytes);
RequestGroupMan* rgman = ownerRequestGroup_->getRequestGroupMan();
if(rgman) {
rgman->getNetStat().updateUploadLength(bytes);
}
}

} // namespace aria2
16 changes: 15 additions & 1 deletion src/DownloadContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "ValueBase.h"
#include "SegList.h"
#include "ContextAttribute.h"
#include "NetStat.h"

namespace aria2 {

Expand Down Expand Up @@ -79,7 +80,7 @@ class DownloadContext

std::vector<SharedHandle<ContextAttribute> > attrs_;

Timer downloadStartTime_;
NetStat netStat_;

Timer downloadStopTime_;

Expand Down Expand Up @@ -234,6 +235,19 @@ class DownloadContext
{
return acceptMetalink_;
}

NetStat& getNetStat()
{
return netStat_;
}

// This method also updates global download length held by
// RequestGroupMan via getOwnerRequestGroup().
void updateDownloadLength(size_t bytes);

// This method also updates global upload length held by
// RequestGroupMan via getOwnerRequestGroup().
void updateUploadLength(size_t bytes);
};

} // namespace aria2
Expand Down
1 change: 0 additions & 1 deletion src/DownloadEngine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@ void DownloadEngine::onEndOfRun()

void DownloadEngine::afterEachIteration()
{
requestGroupMan_->calculateStat();
if(global::globalHaltRequested == 1) {
A2_LOG_NOTICE(_("Shutdown sequence commencing..."
" Press Ctrl-C again for emergency shutdown."));
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ SRCS = Socket.h\
DownloadEngineFactory.cc DownloadEngineFactory.h\
SpeedCalc.cc SpeedCalc.h\
PeerStat.cc PeerStat.h\
NetStat.cc NetStat.h\
BitfieldMan.cc BitfieldMan.h\
Randomizer.h\
SimpleRandomizer.cc SimpleRandomizer.h\
Expand Down
1 change: 1 addition & 0 deletions src/MultiUrlRequestInfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ error_code::Value MultiUrlRequestInfo::execute()
util::setGlobalSignalHandler(SIGINT, handler, 0);
util::setGlobalSignalHandler(SIGTERM, handler, 0);

e->getRequestGroupMan()->getNetStat().downloadStart();
e->run();

if(!option_->blank(PREF_SAVE_COOKIES)) {
Expand Down
Loading

0 comments on commit 0ecfa19

Please sign in to comment.