forked from premiere/premiere-libtorrent
piece picker optimization
This commit is contained in:
parent
25ad24ec68
commit
1c5399b736
|
@ -383,6 +383,7 @@ namespace libtorrent
|
|||
piece_pos(int peer_count_, int index_)
|
||||
: peer_count(peer_count_)
|
||||
, downloading(0)
|
||||
, full(0)
|
||||
, piece_priority(1)
|
||||
, index(index_)
|
||||
{
|
||||
|
@ -392,9 +393,11 @@ namespace libtorrent
|
|||
|
||||
// the number of peers that has this piece
|
||||
// (availability)
|
||||
unsigned peer_count : 10;
|
||||
unsigned peer_count : 9;
|
||||
// is 1 if the piece is marked as being downloaded
|
||||
unsigned downloading : 1;
|
||||
// set when downloading, but no free blocks to request left
|
||||
unsigned full : 1;
|
||||
// is 0 if the piece is filtered (not to be downloaded)
|
||||
// 1 is normal priority (default)
|
||||
// 2 is higher priority than pieces at the same availability level
|
||||
|
@ -415,7 +418,7 @@ namespace libtorrent
|
|||
// the priority value that means the piece is filtered
|
||||
filter_priority = 0,
|
||||
// the max number the peer count can hold
|
||||
max_peer_count = 0x3ff
|
||||
max_peer_count = 0x1ff
|
||||
};
|
||||
|
||||
bool have() const { return index == we_have_index; }
|
||||
|
@ -499,6 +502,8 @@ namespace libtorrent
|
|||
std::vector<downloading_piece>::const_iterator find_dl_piece(int index) const;
|
||||
std::vector<downloading_piece>::iterator find_dl_piece(int index);
|
||||
|
||||
void update_full(downloading_piece& dp);
|
||||
|
||||
// some compilers (e.g. gcc 2.95, does not inherit access
|
||||
// privileges to nested classes)
|
||||
public:
|
||||
|
|
|
@ -276,7 +276,8 @@ namespace libtorrent
|
|||
{
|
||||
downloading_piece const& dp = *i;
|
||||
downloading_piece const& next = *(i + 1);
|
||||
TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing);
|
||||
// TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing);
|
||||
TORRENT_ASSERT(dp.index < next.index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,6 +315,8 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(num_requested == i->requested);
|
||||
TORRENT_ASSERT(num_writing == i->writing);
|
||||
TORRENT_ASSERT(num_finished == i->finished);
|
||||
if (m_piece_map[i->index].full)
|
||||
TORRENT_ASSERT(num_finished + num_writing + num_requested == num_blocks);
|
||||
}
|
||||
int num_pieces = int(m_piece_map.size());
|
||||
TORRENT_ASSERT(m_cursor >= 0);
|
||||
|
@ -1399,6 +1402,11 @@ namespace libtorrent
|
|||
, end(m_downloads.end()); i != end; ++i)
|
||||
{
|
||||
if (!pieces[i->index]) continue;
|
||||
if (m_piece_map[i->index].full
|
||||
&& backup_blocks.size() >= num_blocks
|
||||
&& backup_blocks2.size() >= num_blocks)
|
||||
continue;
|
||||
|
||||
num_blocks = add_blocks_downloading(*i, pieces
|
||||
, interesting_blocks, backup_blocks, backup_blocks2
|
||||
, num_blocks, prefer_whole_pieces, peer, speed, options);
|
||||
|
@ -1563,22 +1571,27 @@ namespace libtorrent
|
|||
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
// we might have to re-pick some backup blocks
|
||||
// from full pieces, since we skipped those the
|
||||
// first pass over
|
||||
for (std::vector<downloading_piece>::const_iterator i = m_downloads.begin()
|
||||
, end(m_downloads.end()); i != end; ++i)
|
||||
{
|
||||
if (!pieces[i->index]) continue;
|
||||
// we've already considered the non-full pieces
|
||||
if (!m_piece_map[i->index].full) continue;
|
||||
std::vector<piece_block> temp;
|
||||
add_blocks_downloading(*i, pieces
|
||||
, temp, backup_blocks, backup_blocks2
|
||||
, num_blocks, prefer_whole_pieces, peer, speed, options);
|
||||
}
|
||||
|
||||
#ifdef TORRENT_DEBUG
|
||||
verify_pick(interesting_blocks, pieces);
|
||||
verify_pick(backup_blocks, pieces);
|
||||
verify_pick(backup_blocks2, pieces);
|
||||
#endif
|
||||
|
||||
num_blocks = append_blocks(interesting_blocks, backup_blocks
|
||||
, num_blocks);
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
num_blocks = append_blocks(interesting_blocks, backup_blocks2, num_blocks);
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
// don't double-pick anything if the peer is on parole
|
||||
if (options & on_parole) return;
|
||||
|
||||
std::vector<piece_block> temp;
|
||||
for (std::vector<downloading_piece>::const_iterator i = m_downloads.begin()
|
||||
, end(m_downloads.end()); i != end; ++i)
|
||||
|
@ -1603,6 +1616,16 @@ namespace libtorrent
|
|||
if (done) break;
|
||||
}
|
||||
|
||||
num_blocks = append_blocks(interesting_blocks, backup_blocks
|
||||
, num_blocks);
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
num_blocks = append_blocks(interesting_blocks, backup_blocks2, num_blocks);
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
// don't double-pick anything if the peer is on parole
|
||||
if (options & on_parole) return;
|
||||
|
||||
// pick one random block from the first busy piece we encountered
|
||||
// none of these blocks have more than one request to them
|
||||
if (!temp.empty()) interesting_blocks.push_back(temp[random() % temp.size()]);
|
||||
|
@ -1762,6 +1785,8 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_piece_map[piece].priority(this) >= 0);
|
||||
if (m_piece_map[piece].downloading)
|
||||
{
|
||||
if (m_piece_map[piece].full) return num_blocks;
|
||||
|
||||
// if we're prioritizing partials, we've already
|
||||
// looked through the downloading pieces
|
||||
if (options & prioritize_partials) return num_blocks;
|
||||
|
@ -1823,11 +1848,11 @@ namespace libtorrent
|
|||
|
||||
// if all blocks have been requested (and we don't need any backup
|
||||
// blocks), we might as well return immediately
|
||||
if (int(backup_blocks2.size()) >= 1
|
||||
/* if (int(backup_blocks2.size()) >= num_blocks
|
||||
&& int(backup_blocks.size()) >= num_blocks
|
||||
&& dp.requested + dp.writing + dp.finished == num_blocks_in_piece)
|
||||
return num_blocks;
|
||||
|
||||
*/
|
||||
// is true if all the other pieces that are currently
|
||||
// requested from this piece are from the same
|
||||
// peer as 'peer'.
|
||||
|
@ -1844,7 +1869,7 @@ namespace libtorrent
|
|||
// downloading from this piece, add it as backups
|
||||
if (prefer_whole_pieces > 0 && !exclusive_active)
|
||||
{
|
||||
if (int(backup_blocks2.size()) >= 1)
|
||||
if (int(backup_blocks2.size()) >= num_blocks)
|
||||
return num_blocks;
|
||||
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
|
@ -1881,7 +1906,7 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
// don't pick too many back-up blocks
|
||||
if (int(backup_blocks2.size()) >= 1) return num_blocks;
|
||||
if (int(backup_blocks2.size()) >= num_blocks) return num_blocks;
|
||||
backup_blocks2.push_back(piece_block(dp.index, j));
|
||||
}
|
||||
continue;
|
||||
|
@ -1967,6 +1992,7 @@ namespace libtorrent
|
|||
// return std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
|
||||
std::vector<piece_picker::downloading_piece>::iterator i = std::lower_bound(
|
||||
m_downloads.begin(), m_downloads.end(), index, compare_index());
|
||||
if (i == m_downloads.end()) return i;
|
||||
if (i->index == index) return i;
|
||||
return m_downloads.end();
|
||||
}
|
||||
|
@ -1976,10 +2002,17 @@ namespace libtorrent
|
|||
// return std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
|
||||
std::vector<piece_picker::downloading_piece>::const_iterator i = std::lower_bound(
|
||||
m_downloads.begin(), m_downloads.end(), index, compare_index());
|
||||
if (i == m_downloads.end()) return i;
|
||||
if (i->index == index) return i;
|
||||
return m_downloads.end();
|
||||
}
|
||||
|
||||
void piece_picker::update_full(downloading_piece& dp)
|
||||
{
|
||||
int num_blocks = blocks_in_piece(dp.index);
|
||||
m_piece_map[dp.index].full = dp.requested + dp.finished + dp.writing == num_blocks;
|
||||
}
|
||||
|
||||
bool piece_picker::is_requested(piece_block block) const
|
||||
{
|
||||
TORRENT_ASSERT(block.piece_index >= 0);
|
||||
|
@ -2049,6 +2082,7 @@ namespace libtorrent
|
|||
info.peer = peer;
|
||||
info.num_peers = 1;
|
||||
++dp.requested;
|
||||
update_full(dp);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2069,6 +2103,7 @@ namespace libtorrent
|
|||
{
|
||||
info.state = block_info::state_requested;
|
||||
++i->requested;
|
||||
update_full(*i);
|
||||
}
|
||||
++info.num_peers;
|
||||
if (i->state == none) i->state = state;
|
||||
|
@ -2140,6 +2175,7 @@ namespace libtorrent
|
|||
info.peer = peer;
|
||||
info.num_peers = 0;
|
||||
dp.writing = 1;
|
||||
update_full(dp);
|
||||
// sort_piece(m_downloads.end()-1);
|
||||
}
|
||||
else
|
||||
|
@ -2195,6 +2231,8 @@ namespace libtorrent
|
|||
|
||||
info.state = block_info::state_none;
|
||||
|
||||
update_full(*i);
|
||||
|
||||
if (i->finished + i->writing + i->requested == 0)
|
||||
{
|
||||
piece_pos& p = m_piece_map[block.piece_index];
|
||||
|
@ -2358,6 +2396,7 @@ namespace libtorrent
|
|||
// clear this block as being downloaded
|
||||
info.state = block_info::state_none;
|
||||
--i->requested;
|
||||
update_full(*i);
|
||||
}
|
||||
|
||||
// if there are no other blocks in this piece
|
||||
|
|
|
@ -467,7 +467,7 @@ int test_main()
|
|||
TEST_CHECK(picked.front().piece_index == first.piece_index);
|
||||
|
||||
// ========================================================
|
||||
|
||||
/*
|
||||
// make sure downloading pieces closer to completion have higher priority
|
||||
// piece 3 has only 1 block from being completed, and should be picked
|
||||
print_title("test downloading piece order");
|
||||
|
@ -476,7 +476,7 @@ int test_main()
|
|||
, options | piece_picker::prioritize_partials, empty_vector);
|
||||
TEST_CHECK(int(picked.size()) > 0);
|
||||
TEST_CHECK(picked.front() == piece_block(3, 3));
|
||||
|
||||
*/
|
||||
// ========================================================
|
||||
|
||||
// test sequential download
|
||||
|
|
Loading…
Reference in New Issue