2008-05-31 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Reduced the usage of gettimeofday().
	* src/DefaultBtMessageDispatcher.cc
	
(DefaultBtMessageDispatcher::checkRequestSlotAndDoNecessaryThing)
	(class FindStaleRequestSlot, class ProcessStaleRequestSlot)
	* src/RequestSlot.cc
	* src/RequestSlot.h
	(RequestSlot::isTimeout)
	
	Made RequestSlot have a reference to Piece object to avoid find
	Piece repeatedly.
	* src/DefaultBtMessageDispatcher.cc
	(class FindStaleRequestSlot, class ProcessStaleRequestSlot)
	* src/RequestSlot.cc
	* src/RequestSlot.h
	(RequestSlot::getPiece)
	* test/DefaultBtMessageDispatcherTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2008-05-31 05:46:16 +00:00
parent f771b42e53
commit 1d7b5e6f4a
5 changed files with 73 additions and 21 deletions

View File

@ -1,3 +1,22 @@
2008-05-31 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Reduced the usage of gettimeofday().
* src/DefaultBtMessageDispatcher.cc
(DefaultBtMessageDispatcher::checkRequestSlotAndDoNecessaryThing)
(class FindStaleRequestSlot, class ProcessStaleRequestSlot)
* src/RequestSlot.cc
* src/RequestSlot.h
(RequestSlot::isTimeout)
Made RequestSlot have a reference to Piece object to avoid find
Piece repeatedly.
* src/DefaultBtMessageDispatcher.cc
(class FindStaleRequestSlot, class ProcessStaleRequestSlot)
* src/RequestSlot.cc
* src/RequestSlot.h
(RequestSlot::getPiece)
* test/DefaultBtMessageDispatcherTest.cc
2008-05-31 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2008-05-31 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/TimeA2.cc * src/TimeA2.cc

View File

@ -246,6 +246,7 @@ private:
SharedHandle<PieceStorage> _pieceStorage; SharedHandle<PieceStorage> _pieceStorage;
BtMessageDispatcher* _messageDispatcher; BtMessageDispatcher* _messageDispatcher;
WeakHandle<BtMessageFactory> _messageFactory; WeakHandle<BtMessageFactory> _messageFactory;
const struct timeval& _now;
time_t _requestTimeout; time_t _requestTimeout;
Logger* _logger; Logger* _logger;
public: public:
@ -253,26 +254,27 @@ public:
const SharedHandle<PieceStorage>& pieceStorage, const SharedHandle<PieceStorage>& pieceStorage,
BtMessageDispatcher* dispatcher, BtMessageDispatcher* dispatcher,
const WeakHandle<BtMessageFactory>& factory, const WeakHandle<BtMessageFactory>& factory,
const struct timeval& now,
time_t requestTimeout): time_t requestTimeout):
_cuid(cuid), _cuid(cuid),
_peer(peer), _peer(peer),
_pieceStorage(pieceStorage), _pieceStorage(pieceStorage),
_messageDispatcher(dispatcher), _messageDispatcher(dispatcher),
_messageFactory(factory), _messageFactory(factory),
_now(now),
_requestTimeout(requestTimeout), _requestTimeout(requestTimeout),
_logger(LogFactory::getInstance()) {} _logger(LogFactory::getInstance()) {}
void operator()(const RequestSlot& slot) void operator()(const RequestSlot& slot)
{ {
SharedHandle<Piece> piece = _pieceStorage->getPiece(slot.getIndex()); if(slot.isTimeout(_now, _requestTimeout)) {
if(slot.isTimeout(_requestTimeout)) {
_logger->debug(MSG_DELETING_REQUEST_SLOT_TIMEOUT, _logger->debug(MSG_DELETING_REQUEST_SLOT_TIMEOUT,
_cuid, _cuid,
slot.getBlockIndex()); slot.getBlockIndex());
_logger->debug("index=%d, begin=%d", slot.getIndex(), slot.getBegin()); _logger->debug("index=%d, begin=%d", slot.getIndex(), slot.getBegin());
piece->cancelBlock(slot.getBlockIndex()); slot.getPiece()->cancelBlock(slot.getBlockIndex());
_peer->snubbing(true); _peer->snubbing(true);
} else if(piece->hasBlock(slot.getBlockIndex())) { } else if(slot.getPiece()->hasBlock(slot.getBlockIndex())) {
_logger->debug(MSG_DELETING_REQUEST_SLOT_ACQUIRED, _logger->debug(MSG_DELETING_REQUEST_SLOT_ACQUIRED,
_cuid, _cuid,
slot.getBlockIndex()); slot.getBlockIndex());
@ -288,20 +290,22 @@ public:
class FindStaleRequestSlot { class FindStaleRequestSlot {
private: private:
SharedHandle<PieceStorage> _pieceStorage; SharedHandle<PieceStorage> _pieceStorage;
const struct timeval& _now;
time_t _requestTimeout; time_t _requestTimeout;
public: public:
FindStaleRequestSlot(const SharedHandle<PieceStorage>& pieceStorage, FindStaleRequestSlot(const SharedHandle<PieceStorage>& pieceStorage,
const struct timeval& now,
time_t requestTimeout): time_t requestTimeout):
_pieceStorage(pieceStorage), _pieceStorage(pieceStorage),
_now(now),
_requestTimeout(requestTimeout) {} _requestTimeout(requestTimeout) {}
bool operator()(const RequestSlot& slot) bool operator()(const RequestSlot& slot)
{ {
if(slot.isTimeout(_requestTimeout)) { if(slot.isTimeout(_now, _requestTimeout)) {
return true; return true;
} else { } else {
SharedHandle<Piece> piece = _pieceStorage->getPiece(slot.getIndex()); if(slot.getPiece()->hasBlock(slot.getBlockIndex())) {
if(piece->hasBlock(slot.getBlockIndex())) {
return true; return true;
} else { } else {
return false; return false;
@ -312,15 +316,20 @@ public:
void DefaultBtMessageDispatcher::checkRequestSlotAndDoNecessaryThing() void DefaultBtMessageDispatcher::checkRequestSlotAndDoNecessaryThing()
{ {
struct timeval now;
gettimeofday(&now, 0);
std::for_each(requestSlots.begin(), requestSlots.end(), std::for_each(requestSlots.begin(), requestSlots.end(),
ProcessStaleRequestSlot(cuid, ProcessStaleRequestSlot(cuid,
peer, peer,
pieceStorage, pieceStorage,
this, this,
messageFactory, messageFactory,
now,
requestTimeout)); requestTimeout));
requestSlots.erase(std::remove_if(requestSlots.begin(), requestSlots.end(), requestSlots.erase(std::remove_if(requestSlots.begin(), requestSlots.end(),
FindStaleRequestSlot(pieceStorage, FindStaleRequestSlot(pieceStorage,
now,
requestTimeout)), requestTimeout)),
requestSlots.end()); requestSlots.end());
} }
@ -363,7 +372,7 @@ bool DefaultBtMessageDispatcher::isOutstandingRequest(size_t index, size_t block
RequestSlot RequestSlot
DefaultBtMessageDispatcher::getOutstandingRequest(size_t index, uint32_t begin, size_t length) DefaultBtMessageDispatcher::getOutstandingRequest(size_t index, uint32_t begin, size_t length)
{ {
RequestSlot ret(0, 0, 0, 0); RequestSlot ret;
RequestSlot rs(index, begin, length, 0); RequestSlot rs(index, begin, length, 0);
std::deque<RequestSlot>::iterator i = std::deque<RequestSlot>::iterator i =
std::lower_bound(requestSlots.begin(), requestSlots.end(), rs); std::lower_bound(requestSlots.begin(), requestSlots.end(), rs);

View File

@ -37,21 +37,25 @@
namespace aria2 { namespace aria2 {
RequestSlot RequestSlot::nullSlot(0, 0, 0, 0); RequestSlot RequestSlot::nullSlot = RequestSlot();
RequestSlot::RequestSlot(size_t index, uint32_t begin, size_t length, size_t blockIndex) RequestSlot::RequestSlot(size_t index, uint32_t begin, size_t length, size_t blockIndex, const SharedHandle<Piece>& piece)
:index(index), begin(begin), length(length), blockIndex(blockIndex) {} :index(index), begin(begin), length(length), blockIndex(blockIndex),
_piece(piece) {}
RequestSlot::RequestSlot(const RequestSlot& requestSlot) { RequestSlot::RequestSlot(const RequestSlot& requestSlot) {
copy(requestSlot); copy(requestSlot);
} }
RequestSlot::RequestSlot():index(0), begin(0), length(0), blockIndex(0) {}
void RequestSlot::copy(const RequestSlot& requestSlot) { void RequestSlot::copy(const RequestSlot& requestSlot) {
index = requestSlot.index; index = requestSlot.index;
begin = requestSlot.begin; begin = requestSlot.begin;
length = requestSlot.length; length = requestSlot.length;
blockIndex = requestSlot.blockIndex; blockIndex = requestSlot.blockIndex;
dispatchedTime = requestSlot.dispatchedTime; dispatchedTime = requestSlot.dispatchedTime;
_piece = requestSlot._piece;
} }
RequestSlot& RequestSlot::operator=(const RequestSlot& requestSlot) RequestSlot& RequestSlot::operator=(const RequestSlot& requestSlot)
@ -89,8 +93,8 @@ void RequestSlot::setDispatchedTime(time_t secFromEpoch) {
dispatchedTime.setTimeInSec(secFromEpoch); dispatchedTime.setTimeInSec(secFromEpoch);
} }
bool RequestSlot::isTimeout(time_t timeoutSec) const { bool RequestSlot::isTimeout(const struct timeval& now, time_t timeoutSec) const {
return dispatchedTime.elapsed(timeoutSec); return dispatchedTime.difference(now) >= timeoutSec;
} }
unsigned int RequestSlot::getLatencyInMillis() const { unsigned int RequestSlot::getLatencyInMillis() const {
@ -102,4 +106,9 @@ bool RequestSlot::isNull(const RequestSlot& requestSlot) {
requestSlot.length == 0; requestSlot.length == 0;
} }
SharedHandle<Piece> RequestSlot::getPiece() const
{
return _piece;
}
} // namespace aria2 } // namespace aria2

View File

@ -37,6 +37,7 @@
#include "common.h" #include "common.h"
#include "TimeA2.h" #include "TimeA2.h"
#include "Piece.h"
#include <deque> #include <deque>
namespace aria2 { namespace aria2 {
@ -48,11 +49,23 @@ private:
uint32_t begin; uint32_t begin;
size_t length; size_t length;
size_t blockIndex; size_t blockIndex;
// This is the piece whose index is index of this RequestSlot has.
// To detect duplicate RequestSlot, we have to find the piece using
// PieceStorage::getPiece() repeatedly. It turns out that this process
// takes time(about 1.7% of processing time). To reduce it, we put piece here
// at the construction of RequestSlot as a cache.
SharedHandle<Piece> _piece;
void copy(const RequestSlot& requestSlot); void copy(const RequestSlot& requestSlot);
public: public:
RequestSlot(size_t index, uint32_t begin, size_t length, size_t blockIndex); RequestSlot(size_t index, uint32_t begin, size_t length, size_t blockIndex,
const SharedHandle<Piece>& piece = SharedHandle<Piece>());
RequestSlot(const RequestSlot& requestSlot); RequestSlot(const RequestSlot& requestSlot);
RequestSlot();
~RequestSlot() {} ~RequestSlot() {}
RequestSlot& operator=(const RequestSlot& requestSlot); RequestSlot& operator=(const RequestSlot& requestSlot);
@ -66,7 +79,7 @@ public:
void setDispatchedTime(); void setDispatchedTime();
void setDispatchedTime(time_t secFromEpoch); void setDispatchedTime(time_t secFromEpoch);
bool isTimeout(time_t timeoutSec) const; bool isTimeout(const struct timeval& now, time_t timeoutSec) const;
unsigned int getLatencyInMillis() const; unsigned int getLatencyInMillis() const;
size_t getIndex() const { return index; } size_t getIndex() const { return index; }
@ -81,6 +94,8 @@ public:
size_t getBlockIndex() const { return blockIndex; } size_t getBlockIndex() const { return blockIndex; }
void setBlockIndex(size_t blockIndex) { this->blockIndex = blockIndex; } void setBlockIndex(size_t blockIndex) { this->blockIndex = blockIndex; }
SharedHandle<Piece> getPiece() const;
static RequestSlot nullSlot; static RequestSlot nullSlot;
static bool isNull(const RequestSlot& requestSlot); static bool isNull(const RequestSlot& requestSlot);

View File

@ -278,9 +278,9 @@ void DefaultBtMessageDispatcherTest::testDoCancelSendingPieceAction() {
int MY_PIECE_LENGTH = 16*1024; int MY_PIECE_LENGTH = 16*1024;
void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing() { void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing() {
RequestSlot slot(0, 0, MY_PIECE_LENGTH, 0);
SharedHandle<Piece> piece(new Piece(0, MY_PIECE_LENGTH)); SharedHandle<Piece> piece(new Piece(0, MY_PIECE_LENGTH));
RequestSlot slot(0, 0, MY_PIECE_LENGTH, 0, piece);
size_t index; size_t index;
CPPUNIT_ASSERT(piece->getMissingUnusedBlockIndex(index)); CPPUNIT_ASSERT(piece->getMissingUnusedBlockIndex(index));
CPPUNIT_ASSERT_EQUAL((size_t)0, index); CPPUNIT_ASSERT_EQUAL((size_t)0, index);
@ -305,11 +305,11 @@ void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing() {
} }
void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing_timeout() { void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing_timeout() {
RequestSlot slot(0, 0, MY_PIECE_LENGTH, 0); SharedHandle<Piece> piece(new Piece(0, MY_PIECE_LENGTH));
RequestSlot slot(0, 0, MY_PIECE_LENGTH, 0, piece);
// make this slot timeout // make this slot timeout
slot.setDispatchedTime(0); slot.setDispatchedTime(0);
SharedHandle<Piece> piece(new Piece(0, MY_PIECE_LENGTH));
size_t index; size_t index;
CPPUNIT_ASSERT(piece->getMissingUnusedBlockIndex(index)); CPPUNIT_ASSERT(piece->getMissingUnusedBlockIndex(index));
CPPUNIT_ASSERT_EQUAL((size_t)0, index); CPPUNIT_ASSERT_EQUAL((size_t)0, index);
@ -338,11 +338,11 @@ void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing_tim
} }
void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing_completeBlock() { void DefaultBtMessageDispatcherTest::testCheckRequestSlotAndDoNecessaryThing_completeBlock() {
RequestSlot slot(0, 0, MY_PIECE_LENGTH, 0);
SharedHandle<Piece> piece(new Piece(0, MY_PIECE_LENGTH)); SharedHandle<Piece> piece(new Piece(0, MY_PIECE_LENGTH));
piece->completeBlock(0); piece->completeBlock(0);
RequestSlot slot(0, 0, MY_PIECE_LENGTH, 0, piece);
SharedHandle<MockPieceStorage2> pieceStorage(new MockPieceStorage2()); SharedHandle<MockPieceStorage2> pieceStorage(new MockPieceStorage2());
pieceStorage->setPiece(piece); pieceStorage->setPiece(piece);
BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(), BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(),