rewrote the piece picker to be more cpu and memory efficient. replaces the concept of sequential-download-threshold with just a sequential download settings

This commit is contained in:
Arvid Norberg
2008-01-31 17:52:29 +00:00
parent 3562c3e646
commit c798ab30e1
11 changed files with 822 additions and 656 deletions

View File

@@ -133,7 +133,8 @@ namespace libtorrent
void get_availability(std::vector<int>& avail) const;
void set_sequenced_download_threshold(int sequenced_download_threshold);
void sequential_download(bool sd);
bool sequential_download() const { return m_sequential_download >= 0; }
// the vector tells which pieces we already have
// and which we don't have.
@@ -143,12 +144,16 @@ namespace libtorrent
, std::vector<int>& verify_pieces);
// increases the peer count for the given piece
// (is used when a HAVE or BITFIELD message is received)
// (is used when a HAVE message is received)
void inc_refcount(int index);
void dec_refcount(int index);
// increases the peer count for the given piece
// (is used when a BITFIELD message is received)
void inc_refcount(std::vector<bool> const& bitmask);
// decreases the peer count for the given piece
// (used when a peer disconnects)
void dec_refcount(int index);
void dec_refcount(std::vector<bool> const& bitmask);
// these will increase and decrease the peer count
// of all pieces. They are used when seeds join
@@ -274,9 +279,11 @@ namespace libtorrent
#ifndef NDEBUG
// used in debug mode
void verify_priority(int start, int end, int prio) const;
void check_invariant(const torrent* t = 0) const;
void verify_pick(std::vector<piece_block> const& picked
, std::vector<bool> const& bitfield) const;
void print_pieces() const;
#endif
// functor that compares indices on downloading_pieces
@@ -295,6 +302,8 @@ namespace libtorrent
private:
friend struct piece_pos;
bool can_pick(int piece, std::vector<bool> const& bitmask) const;
std::pair<int, int> expand_piece(int piece, int whole_pieces
, std::vector<bool> const& have) const;
@@ -346,26 +355,20 @@ namespace libtorrent
bool filtered() const { return piece_priority == filter_priority; }
void filtered(bool f) { piece_priority = f ? filter_priority : 0; }
int priority(int limit) const
int priority(piece_picker const* picker) const
{
if (downloading || filtered() || have()) return 0;
if (downloading || filtered()
|| have() || peer_count + picker->m_seeds == 0)
return -1;
// priority 5, 6 and 7 disregards availability of the piece
if (piece_priority > 4) return 7 - piece_priority;
// pieces we are currently downloading have high priority
int prio = peer_count * 2;
// if the peer_count is 0 or 1, the priority cannot be higher
if (prio <= 1) return prio;
if (prio >= limit * 2) prio = limit * 2;
// the different priority levels
switch (piece_priority)
{
case 1: return prio;
case 2: return prio - 1;
case 3: return (std::max)(prio / 2, 1);
case 4: return (std::max)(prio / 2 - 1, 1);
case 5: return (std::max)(prio / 3, 1);
case 6: return (std::max)(prio / 3 - 1, 1);
case 7: return 1;
}
return prio;
int prio = peer_count * 4;
// if (prio >= picker->m_prio_limit * 6) prio = picker->m_prio_limit * 6;
return prio + (4 - piece_priority);
}
bool operator!=(piece_pos p) const
@@ -378,27 +381,44 @@ namespace libtorrent
BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4);
bool is_ordered(int priority) const
{
return priority >= m_sequenced_download_threshold * 2;
}
void update_pieces() const;
// fills in the range [start, end) of pieces in
// m_pieces that have priority 'prio'
void priority_range(int prio, int* start, int* end);
// adds the piece 'index' to m_pieces
void add(int index);
void move(int vec_index, int elem_index);
// removes the piece with the given priority and the
// elem_index in the m_pieces vector
void remove(int priority, int elem_index);
// updates the position of the piece with the given
// priority and the elem_index in the m_pieces vector
void update(int priority, int elem_index);
// shuffles the given piece inside it's priority range
void shuffle(int priority, int elem_index);
void sort_piece(std::vector<downloading_piece>::iterator dp);
downloading_piece& add_download_piece();
void erase_download_piece(std::vector<downloading_piece>::iterator i);
// this vector contains all pieces we don't have.
// in the first entry (index 0) is a vector of all pieces
// that no peer have, the vector at index 1 contains
// all pieces that exactly one peer have, index 2 contains
// all pieces exactly two peers have and so on.
// this is not entirely true. The availibility of a piece
// is adjusted depending on its priority. But the principle
// is that the higher index, the lower priority a piece has.
std::vector<std::vector<int> > m_piece_info;
// the number of seeds. These are not added to
// the availability counters of the pieces
int m_seeds;
// the following vectors are mutable because they sometimes may
// be updated lazily, triggered by const functions
// this vector contains all piece indices that are pickable
// sorted by priority. Pieces are in random random order
// among pieces with the same priority
mutable std::vector<int> m_pieces;
// these are indices to the priority boundries inside
// the m_pieces vector. priority 0 always start at
// 0, priority 1 starts at m_priority_boundries[0] etc.
mutable std::vector<int> m_priority_boundries;
// this maps indices to number of peers that has this piece and
// index into the m_piece_info vectors.
@@ -406,7 +426,7 @@ namespace libtorrent
// doesn't exist in the piece_info buckets
// pieces with the filtered flag set doesn't have entries in
// the m_piece_info buckets either
std::vector<piece_pos> m_piece_map;
mutable std::vector<piece_pos> m_piece_map;
// each piece that's currently being downloaded
// has an entry in this list with block allocations.
@@ -438,9 +458,16 @@ namespace libtorrent
// the number of pieces we have
int m_num_have;
// the required popularity of a piece in order to download
// it in sequence instead of random order.
int m_sequenced_download_threshold;
// -1 means sequential download is not active.
// >= 0 means that pieces are requested in sequential order
// and this variable is the next piece to request.
// in that case m_pieces is cleared and not used.
int m_sequential_download;
// if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces.
mutable bool m_dirty;
#ifndef NDEBUG
bool m_files_checked_called;
#endif

View File

@@ -157,7 +157,7 @@ namespace libtorrent
aux::session_impl& session() { return m_ses; }
void set_sequenced_download_threshold(int threshold);
void set_sequential_download(bool sd);
bool verify_resume_data(entry& rd, std::string& error)
{ TORRENT_ASSERT(m_storage); return m_storage->verify_resume_data(rd, error); }
@@ -371,8 +371,7 @@ namespace libtorrent
int num_pieces() const { return m_num_pieces; }
// when we get a have- or bitfield- messages, this is called for every
// piece a peer has gained.
// when we get a have message, this is called for that piece
void peer_has(int index)
{
if (m_picker.get())
@@ -389,6 +388,22 @@ namespace libtorrent
#endif
}
// when we get a bitfield message, this is called for that piece
void peer_has(std::vector<bool> const& bitfield)
{
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
m_picker->inc_refcount(bitfield);
}
#ifndef NDEBUG
else
{
TORRENT_ASSERT(is_seed());
}
#endif
}
void peer_has_all()
{
if (m_picker.get())
@@ -404,7 +419,6 @@ namespace libtorrent
#endif
}
// when peer disconnects, this is called for every piece it had
void peer_lost(int index)
{
if (m_picker.get())
@@ -725,7 +739,7 @@ namespace libtorrent
// in case the piece picker hasn't been constructed
// when this settings is set, this variable will keep
// its value until the piece picker is created
int m_sequenced_download_threshold;
bool m_sequential_download;
// is false by default and set to
// true when the first tracker reponse

View File

@@ -378,7 +378,7 @@ namespace libtorrent
void set_download_limit(int limit) const;
int download_limit() const;
void set_sequenced_download_threshold(int threshold) const;
void set_sequential_download(bool sd) const;
void set_peer_upload_limit(tcp::endpoint ip, int limit) const;
void set_peer_download_limit(tcp::endpoint ip, int limit) const;