forked from premiere/premiere-libtorrent
piece picker optimization. O(log n), lookup of downloading pieces instead of O(n)
This commit is contained in:
parent
b9be2fe94b
commit
25ad24ec68
|
@ -353,6 +353,14 @@ namespace libtorrent
|
|||
int index;
|
||||
};
|
||||
|
||||
struct compare_index
|
||||
{
|
||||
bool operator()(const downloading_piece& p, int piece) const
|
||||
{ return p.index < piece; }
|
||||
bool operator()(int piece, const downloading_piece& p) const
|
||||
{ return piece < p.index; }
|
||||
};
|
||||
|
||||
int blocks_in_last_piece() const
|
||||
{ return m_blocks_in_last_piece; }
|
||||
|
||||
|
@ -483,11 +491,14 @@ namespace libtorrent
|
|||
// 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);
|
||||
// void sort_piece(std::vector<downloading_piece>::iterator dp);
|
||||
|
||||
downloading_piece& add_download_piece();
|
||||
downloading_piece& add_download_piece(int index);
|
||||
void erase_download_piece(std::vector<downloading_piece>::iterator i);
|
||||
|
||||
std::vector<downloading_piece>::const_iterator find_dl_piece(int index) const;
|
||||
std::vector<downloading_piece>::iterator find_dl_piece(int index);
|
||||
|
||||
// some compilers (e.g. gcc 2.95, does not inherit access
|
||||
// privileges to nested classes)
|
||||
public:
|
||||
|
@ -520,7 +531,8 @@ namespace libtorrent
|
|||
// each piece that's currently being downloaded
|
||||
// has an entry in this list with block allocations.
|
||||
// i.e. it says wich parts of the piece that
|
||||
// is being downloaded
|
||||
// is being downloaded. This list is ordered
|
||||
// by piece index to make lookups efficient
|
||||
std::vector<downloading_piece> m_downloads;
|
||||
|
||||
// this holds the information of the
|
||||
|
|
|
@ -137,9 +137,7 @@ namespace libtorrent
|
|||
|
||||
if (m_piece_map[index].downloading)
|
||||
{
|
||||
std::vector<downloading_piece>::const_iterator piece = std::find_if(
|
||||
m_downloads.begin(), m_downloads.end()
|
||||
, boost::bind(&downloading_piece::index, _1) == index);
|
||||
std::vector<downloading_piece>::const_iterator piece = find_dl_piece(index);
|
||||
TORRENT_ASSERT(piece != m_downloads.end());
|
||||
st = *piece;
|
||||
st.info = 0;
|
||||
|
@ -157,7 +155,7 @@ namespace libtorrent
|
|||
st.finished = 0;
|
||||
}
|
||||
|
||||
piece_picker::downloading_piece& piece_picker::add_download_piece()
|
||||
piece_picker::downloading_piece& piece_picker::add_download_piece(int piece)
|
||||
{
|
||||
int num_downloads = m_downloads.size();
|
||||
int block_index = num_downloads * m_blocks_per_piece;
|
||||
|
@ -173,8 +171,12 @@ namespace libtorrent
|
|||
m_downloads[i].info = &m_block_info[m_downloads[i].info - base];
|
||||
}
|
||||
}
|
||||
m_downloads.push_back(downloading_piece());
|
||||
downloading_piece& ret = m_downloads.back();
|
||||
std::vector<downloading_piece>::iterator i = std::lower_bound(m_downloads.begin()
|
||||
, m_downloads.end(), piece, compare_index());
|
||||
TORRENT_ASSERT(i == m_downloads.end() || i->index != piece);
|
||||
i = m_downloads.insert(i, downloading_piece());
|
||||
downloading_piece& ret = *i;
|
||||
ret.index = piece;
|
||||
ret.info = &m_block_info[block_index];
|
||||
for (int i = 0; i < m_blocks_per_piece; ++i)
|
||||
{
|
||||
|
@ -764,7 +766,7 @@ namespace libtorrent
|
|||
p2.index = temp;
|
||||
std::swap(m_pieces[other_index], m_pieces[elem_index]);
|
||||
}
|
||||
|
||||
/*
|
||||
void piece_picker::sort_piece(std::vector<downloading_piece>::iterator dp)
|
||||
{
|
||||
TORRENT_ASSERT(m_piece_map[dp->index].downloading);
|
||||
|
@ -793,7 +795,7 @@ namespace libtorrent
|
|||
if (j == m_downloads.end() - 1) return;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
void piece_picker::restore_piece(int index)
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
@ -803,9 +805,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_piece_map[index].downloading == 1);
|
||||
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end()
|
||||
, has_index(index));
|
||||
std::vector<downloading_piece>::iterator i = find_dl_piece(index);
|
||||
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
#ifdef TORRENT_DEBUG
|
||||
|
@ -1090,15 +1090,12 @@ namespace libtorrent
|
|||
if (p.downloading)
|
||||
{
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin()
|
||||
, m_downloads.end()
|
||||
, has_index(index));
|
||||
= find_dl_piece(index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
erase_download_piece(i);
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end()
|
||||
, has_index(index)) == m_downloads.end());
|
||||
TORRENT_ASSERT(find_dl_piece(index) == m_downloads.end());
|
||||
|
||||
if (p.have()) return;
|
||||
|
||||
|
@ -1576,8 +1573,7 @@ namespace libtorrent
|
|||
, num_blocks);
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
num_blocks = append_blocks(interesting_blocks, backup_blocks2
|
||||
, num_blocks);
|
||||
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
|
||||
|
@ -1659,8 +1655,7 @@ namespace libtorrent
|
|||
if (piece_priority(i) == 0) continue;
|
||||
if (have_piece(i)) continue;
|
||||
|
||||
std::vector<downloading_piece>::const_iterator k
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(i));
|
||||
std::vector<downloading_piece>::const_iterator k = find_dl_piece(i);
|
||||
|
||||
TORRENT_ASSERT(k != m_downloads.end());
|
||||
if (k == m_downloads.end()) continue;
|
||||
|
@ -1771,8 +1766,7 @@ namespace libtorrent
|
|||
// looked through the downloading pieces
|
||||
if (options & prioritize_partials) return num_blocks;
|
||||
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(piece));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(piece);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
|
||||
// std::cout << "add_blocks_downloading(" << piece << ")" << std::endl;
|
||||
|
@ -1829,7 +1823,7 @@ 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()) >= num_blocks
|
||||
if (int(backup_blocks2.size()) >= 1
|
||||
&& int(backup_blocks.size()) >= num_blocks
|
||||
&& dp.requested + dp.writing + dp.finished == num_blocks_in_piece)
|
||||
return num_blocks;
|
||||
|
@ -1850,7 +1844,7 @@ namespace libtorrent
|
|||
// downloading from this piece, add it as backups
|
||||
if (prefer_whole_pieces > 0 && !exclusive_active)
|
||||
{
|
||||
if (int(backup_blocks2.size()) >= num_blocks)
|
||||
if (int(backup_blocks2.size()) >= 1)
|
||||
return num_blocks;
|
||||
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
|
@ -1887,7 +1881,7 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
// don't pick too many back-up blocks
|
||||
if (int(backup_blocks2.size()) >= num_blocks) return num_blocks;
|
||||
if (int(backup_blocks2.size()) >= 1) return num_blocks;
|
||||
backup_blocks2.push_back(piece_block(dp.index, j));
|
||||
}
|
||||
continue;
|
||||
|
@ -1947,12 +1941,10 @@ namespace libtorrent
|
|||
|
||||
if (m_piece_map[index].downloading == 0)
|
||||
{
|
||||
TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end()
|
||||
, has_index(index)) == m_downloads.end());
|
||||
TORRENT_ASSERT(find_dl_piece(index) == m_downloads.end());
|
||||
return false;
|
||||
}
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
TORRENT_ASSERT((int)i->finished <= m_blocks_per_piece);
|
||||
int max_blocks = blocks_in_piece(index);
|
||||
|
@ -1970,6 +1962,24 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<piece_picker::downloading_piece>::iterator piece_picker::find_dl_piece(int index)
|
||||
{
|
||||
// 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->index == index) return i;
|
||||
return m_downloads.end();
|
||||
}
|
||||
|
||||
std::vector<piece_picker::downloading_piece>::const_iterator piece_picker::find_dl_piece(int index) const
|
||||
{
|
||||
// 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->index == index) return i;
|
||||
return m_downloads.end();
|
||||
}
|
||||
|
||||
bool piece_picker::is_requested(piece_block block) const
|
||||
{
|
||||
TORRENT_ASSERT(block.piece_index >= 0);
|
||||
|
@ -1977,11 +1987,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(block.piece_index < m_piece_map.size());
|
||||
|
||||
if (m_piece_map[block.piece_index].downloading == 0) return false;
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(
|
||||
m_downloads.begin()
|
||||
, m_downloads.end()
|
||||
, has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(block.piece_index);
|
||||
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
return i->info[block.block_index].state == block_info::state_requested;
|
||||
|
@ -1995,8 +2001,7 @@ namespace libtorrent
|
|||
|
||||
if (m_piece_map[block.piece_index].index == piece_pos::we_have_index) return true;
|
||||
if (m_piece_map[block.piece_index].downloading == 0) return false;
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
return i->info[block.block_index].state == block_info::state_finished
|
||||
|| i->info[block.block_index].state == block_info::state_writing;
|
||||
|
@ -2010,8 +2015,7 @@ namespace libtorrent
|
|||
|
||||
if (m_piece_map[block.piece_index].index == piece_pos::we_have_index) return true;
|
||||
if (m_piece_map[block.piece_index].downloading == 0) return false;
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
return i->info[block.block_index].state == block_info::state_finished;
|
||||
}
|
||||
|
@ -2038,8 +2042,7 @@ namespace libtorrent
|
|||
p.downloading = 1;
|
||||
if (prio >= 0 && !m_dirty) update(prio, p.index);
|
||||
|
||||
downloading_piece& dp = add_download_piece();
|
||||
dp.index = block.piece_index;
|
||||
downloading_piece& dp = add_download_piece(block.piece_index);
|
||||
dp.state = state;
|
||||
block_info& info = dp.info[block.block_index];
|
||||
info.state = block_info::state_requested;
|
||||
|
@ -2052,8 +2055,7 @@ namespace libtorrent
|
|||
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
#endif
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
block_info& info = i->info[block.block_index];
|
||||
if (info.state == block_info::state_writing
|
||||
|
@ -2084,8 +2086,7 @@ namespace libtorrent
|
|||
piece_pos const& p = m_piece_map[block.piece_index];
|
||||
if (!p.downloading) return 0;
|
||||
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
|
||||
block_info const& info = i->info[block.block_index];
|
||||
|
@ -2132,20 +2133,18 @@ namespace libtorrent
|
|||
// the piece priority was set to 0
|
||||
if (prio >= 0 && !m_dirty) update(prio, p.index);
|
||||
|
||||
downloading_piece& dp = add_download_piece();
|
||||
dp.index = block.piece_index;
|
||||
downloading_piece& dp = add_download_piece(block.piece_index);
|
||||
dp.state = none;
|
||||
block_info& info = dp.info[block.block_index];
|
||||
info.state = block_info::state_writing;
|
||||
info.peer = peer;
|
||||
info.num_peers = 0;
|
||||
dp.writing = 1;
|
||||
sort_piece(m_downloads.end()-1);
|
||||
// sort_piece(m_downloads.end()-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
block_info& info = i->info[block.block_index];
|
||||
|
||||
|
@ -2169,7 +2168,7 @@ namespace libtorrent
|
|||
// remove the fast/slow state from it
|
||||
i->state = none;
|
||||
}
|
||||
sort_piece(i);
|
||||
// sort_piece(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2178,8 +2177,7 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
if (i == m_downloads.end()) return;
|
||||
|
||||
|
@ -2211,7 +2209,7 @@ namespace libtorrent
|
|||
}
|
||||
else
|
||||
{
|
||||
sort_piece(i);
|
||||
// sort_piece(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2240,8 +2238,7 @@ namespace libtorrent
|
|||
p.downloading = 1;
|
||||
if (prio >= 0 && !m_dirty) update(prio, p.index);
|
||||
|
||||
downloading_piece& dp = add_download_piece();
|
||||
dp.index = block.piece_index;
|
||||
downloading_piece& dp = add_download_piece(block.piece_index);
|
||||
dp.state = none;
|
||||
block_info& info = dp.info[block.block_index];
|
||||
info.peer = peer;
|
||||
|
@ -2250,7 +2247,7 @@ namespace libtorrent
|
|||
if (info.state != block_info::state_finished)
|
||||
{
|
||||
++dp.finished;
|
||||
sort_piece(m_downloads.end() - 1);
|
||||
// sort_piece(m_downloads.end() - 1);
|
||||
}
|
||||
info.state = block_info::state_finished;
|
||||
}
|
||||
|
@ -2260,8 +2257,7 @@ namespace libtorrent
|
|||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
#endif
|
||||
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
block_info& info = i->info[block.block_index];
|
||||
|
||||
|
@ -2282,7 +2278,7 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(info.state == block_info::state_none);
|
||||
info.state = block_info::state_finished;
|
||||
sort_piece(i);
|
||||
// sort_piece(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2290,8 +2286,7 @@ namespace libtorrent
|
|||
void piece_picker::get_downloaders(std::vector<void*>& d, int index) const
|
||||
{
|
||||
TORRENT_ASSERT(index >= 0 && index <= (int)m_piece_map.size());
|
||||
std::vector<downloading_piece>::const_iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
|
||||
d.clear();
|
||||
|
@ -2303,10 +2298,7 @@ namespace libtorrent
|
|||
|
||||
void* piece_picker::get_downloader(piece_block block) const
|
||||
{
|
||||
std::vector<downloading_piece>::const_iterator i = std::find_if(
|
||||
m_downloads.begin()
|
||||
, m_downloads.end()
|
||||
, has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::const_iterator i = find_dl_piece(block.piece_index);
|
||||
|
||||
if (i == m_downloads.end()) return 0;
|
||||
|
||||
|
@ -2333,13 +2325,11 @@ namespace libtorrent
|
|||
|
||||
if (m_piece_map[block.piece_index].downloading == 0)
|
||||
{
|
||||
TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end()
|
||||
, has_index(block.piece_index)) == m_downloads.end());
|
||||
TORRENT_ASSERT(find_dl_piece(block.piece_index) == m_downloads.end());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<downloading_piece>::iterator i = std::find_if(m_downloads.begin()
|
||||
, m_downloads.end(), has_index(block.piece_index));
|
||||
std::vector<downloading_piece>::iterator i = find_dl_piece(block.piece_index);
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
|
||||
block_info& info = i->info[block.block_index];
|
||||
|
@ -2386,8 +2376,7 @@ namespace libtorrent
|
|||
else if (prev_prio >= 0) update(prev_prio, p.index);
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(std::find_if(m_downloads.begin(), m_downloads.end()
|
||||
, has_index(block.piece_index)) == m_downloads.end());
|
||||
TORRENT_ASSERT(find_dl_piece(block.piece_index) == m_downloads.end());
|
||||
}
|
||||
else if (i->requested == 0)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue