forked from premiere/premiere-libtorrent
deprecated auto_expand_choker. started factoring out choker logic into its own translation unit (preparing for making it unit testable)
This commit is contained in:
parent
907dc9dddd
commit
02a9ea18b7
|
@ -16,6 +16,7 @@ set(sources
|
|||
block_cache
|
||||
bloom_filter
|
||||
chained_buffer
|
||||
choker
|
||||
crc32c
|
||||
create_torrent
|
||||
disk_buffer_holder
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
* removed auto_expand_choker. use rate_based_choker instead
|
||||
* optimize UDP tracker packet handling
|
||||
* support SSL over uTP connections
|
||||
* support web seeds that resolve to multiple IPs
|
||||
|
|
1
Jamfile
1
Jamfile
|
@ -512,6 +512,7 @@ SOURCES =
|
|||
block_cache
|
||||
bloom_filter
|
||||
chained_buffer
|
||||
choker
|
||||
crc32c
|
||||
create_torrent
|
||||
disk_buffer_holder
|
||||
|
|
|
@ -25,6 +25,7 @@ nobase_include_HEADERS = \
|
|||
build_config.hpp \
|
||||
byteswap.hpp \
|
||||
chained_buffer.hpp \
|
||||
choker.hpp \
|
||||
config.hpp \
|
||||
ConvertUTF.h \
|
||||
copy_ptr.hpp \
|
||||
|
|
|
@ -627,7 +627,7 @@ namespace libtorrent
|
|||
void update_i2p_bridge();
|
||||
void update_peer_tos();
|
||||
void update_user_agent();
|
||||
void update_choking_algorithm();
|
||||
void update_unchoke_limit();
|
||||
void update_connection_speed();
|
||||
void update_queued_disk_bytes();
|
||||
void update_alert_queue_size();
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/time.hpp" // for time_duration
|
||||
#include <vector>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
namespace aux { struct session_settings; }
|
||||
class peer_connection;
|
||||
|
||||
// sorts the vector of peers in-place. When returning, the top unchoke slots
|
||||
// elements are the peers we should unchoke. This is similar to a partial
|
||||
// sort. Only the unchoke slots first elements are sorted.
|
||||
// the return value are the number of peers that should be unchoked. This
|
||||
// is also the number of elements that are valid at the beginning of the
|
||||
// peer list. Peers bayond this initial range are not sorted.
|
||||
TORRENT_EXTRA_EXPORT int unchoke_sort(std::vector<peer_connection*>& peers
|
||||
, int max_upload_rate, time_duration unchoke_interval
|
||||
, aux::session_settings const& sett);
|
||||
|
||||
}
|
|
@ -443,18 +443,21 @@ namespace libtorrent
|
|||
{
|
||||
// the traditional choker with a fixed number of unchoke slots, as
|
||||
// specified by session::set_max_uploads()..
|
||||
fixed_slots_choker,
|
||||
fixed_slots_choker = 0,
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
// opens at least the number of slots as specified by
|
||||
// session::set_max_uploads() but opens up more slots if the upload
|
||||
// capacity is not saturated. This unchoker will work just like the
|
||||
// ``fixed_slot_choker`` if there's no global upload rate limit set.
|
||||
auto_expand_choker,
|
||||
auto_expand_choker = 1,
|
||||
#endif
|
||||
|
||||
// opens up unchoke slots based on the upload rate achieved to peers.
|
||||
// The more slots that are opened, the marginal upload rate required
|
||||
// to open up another slot increases.
|
||||
rate_based_choker,
|
||||
rate_based_choker = 1,
|
||||
|
||||
// attempts to optimize download rate by finding the reciprocation
|
||||
// rate of each peer individually and prefers peers that gives the
|
||||
// highest *return on investment*. It still allocates all upload
|
||||
|
@ -464,7 +467,7 @@ namespace libtorrent
|
|||
// this choker, see the paper_.
|
||||
//
|
||||
// .. _paper: http://bittyrant.cs.washington.edu/#papers
|
||||
bittyrant_choker
|
||||
bittyrant_choker = 2
|
||||
};
|
||||
|
||||
// specifies which algorithm to use to determine which peers to unchoke.
|
||||
|
|
|
@ -842,11 +842,6 @@ namespace libtorrent
|
|||
// * ``fixed_slots_choker`` is the traditional choker with a fixed number of unchoke
|
||||
// slots (as specified by ``session::set_max_uploads()``).
|
||||
//
|
||||
// * ``auto_expand_choker`` opens at least the number of slots as specified by
|
||||
// ``session::set_max_uploads()`` but opens up more slots if the upload capacity
|
||||
// is not saturated. This unchoker will work just like the ``fixed_slots_choker``
|
||||
// if there's no global upload rate limit set.
|
||||
//
|
||||
// * ``rate_based_choker`` opens up unchoke slots based on the upload rate
|
||||
// achieved to peers. The more slots that are opened, the marginal upload
|
||||
// rate required to open up another slot increases.
|
||||
|
@ -1474,10 +1469,9 @@ namespace libtorrent
|
|||
|
||||
enum choking_algorithm_t
|
||||
{
|
||||
fixed_slots_choker,
|
||||
auto_expand_choker,
|
||||
rate_based_choker,
|
||||
bittyrant_choker
|
||||
fixed_slots_choker = 0,
|
||||
rate_based_choker = 2,
|
||||
bittyrant_choker = 3
|
||||
};
|
||||
|
||||
enum seed_choking_algorithm_t
|
||||
|
|
|
@ -48,6 +48,7 @@ libtorrent_rasterbar_la_SOURCES = \
|
|||
block_cache.cpp \
|
||||
bt_peer_connection.cpp \
|
||||
chained_buffer.cpp \
|
||||
choker.cpp \
|
||||
ConvertUTF.cpp \
|
||||
crc32c.cpp \
|
||||
create_torrent.cpp \
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/choker.hpp"
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
#include "libtorrent/aux_/session_settings.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
int unchoke_sort(std::vector<peer_connection*>& peers
|
||||
, int max_upload_rate
|
||||
, time_duration unchoke_interval
|
||||
, aux::session_settings const& sett)
|
||||
{
|
||||
int upload_slots = sett.get_int(settings_pack::unchoke_slots_limit);
|
||||
|
||||
// ==== BitTyrant ====
|
||||
//
|
||||
// if we're using the bittyrant unchoker, go through all peers that
|
||||
// we have unchoked already, and adjust our estimated reciprocation
|
||||
// rate. If the peer has reciprocated, lower the estimate, if it hasn't,
|
||||
// increase the estimate (this attempts to optimize "ROI" of upload
|
||||
// capacity, by sending just enough to be reciprocated).
|
||||
// For more information, see: http://bittyrant.cs.washington.edu/
|
||||
if (sett.get_int(settings_pack::choking_algorithm)
|
||||
== settings_pack::bittyrant_choker)
|
||||
{
|
||||
for (std::vector<peer_connection*>::const_iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
if (p->is_choked() || !p->is_interesting()) continue;
|
||||
|
||||
if (!p->has_peer_choked())
|
||||
{
|
||||
// we're unchoked, we may want to lower our estimated
|
||||
// reciprocation rate
|
||||
p->decrease_est_reciprocation_rate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've unchoked this peer, and it hasn't reciprocated
|
||||
// we may want to increase our estimated reciprocation rate
|
||||
p->increase_est_reciprocation_rate();
|
||||
}
|
||||
}
|
||||
|
||||
// if we're using the bittyrant choker, sort peers by their return
|
||||
// on investment. i.e. download rate / upload rate
|
||||
|
||||
// TODO: make the comparison function a free function and move it
|
||||
// into this source file
|
||||
std::sort(peers.begin(), peers.end()
|
||||
, boost::bind(&peer_connection::bittyrant_unchoke_compare, _1, _2));
|
||||
|
||||
int upload_capacity_left = max_upload_rate;
|
||||
|
||||
// now, figure out how many peers should be unchoked. We deduct the
|
||||
// estimated reciprocation rate from our upload_capacity estimate
|
||||
// until there none left
|
||||
upload_slots = 0;
|
||||
|
||||
for (std::vector<peer_connection*>::iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
TORRENT_ASSERT(p);
|
||||
|
||||
if (p->est_reciprocation_rate() > upload_capacity_left) break;
|
||||
|
||||
++upload_slots;
|
||||
upload_capacity_left -= p->est_reciprocation_rate();
|
||||
}
|
||||
|
||||
return upload_slots;
|
||||
}
|
||||
|
||||
// ==== rate-based ====
|
||||
//
|
||||
// The rate based unchoker looks at our upload rate to peers, and find
|
||||
// a balance between number of upload slots and the rate we achieve. The
|
||||
// intention is to not spread upload bandwidth too thin, but also to not
|
||||
// unchoke few enough peers to not be able to saturate the up-link.
|
||||
// this is done by traversing the peers sorted by our upload rate to
|
||||
// them in decreasing rates. For each peer we increase our threshold
|
||||
// by 1 kB/s. The first peer we get to to whom we upload slower than
|
||||
// the threshold, we stop and that's the number of unchoke slots we have.
|
||||
if (sett.get_int(settings_pack::choking_algorithm)
|
||||
== settings_pack::rate_based_choker)
|
||||
{
|
||||
// first reset the number of unchoke slots, because we'll calculate
|
||||
// it purely based on the current state of our peers.
|
||||
upload_slots = 0;
|
||||
|
||||
// TODO: optimize this using partial_sort or something. We don't need
|
||||
// to sort the entire list
|
||||
|
||||
// TODO: make the comparison function a free function and move it
|
||||
// into this cpp file
|
||||
std::sort(peers.begin(), peers.end()
|
||||
, boost::bind(&peer_connection::upload_rate_compare, _1, _2));
|
||||
|
||||
// TODO: make configurable
|
||||
int rate_threshold = 1024;
|
||||
|
||||
for (std::vector<peer_connection*>::const_iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection const& p = **i;
|
||||
int rate = int(p.uploaded_in_last_round()
|
||||
* 1000 / total_milliseconds(unchoke_interval));
|
||||
|
||||
if (rate < rate_threshold) break;
|
||||
|
||||
++upload_slots;
|
||||
|
||||
// TODO: make configurable
|
||||
rate_threshold += 1024;
|
||||
}
|
||||
++upload_slots;
|
||||
}
|
||||
|
||||
// sorts the peers that are eligible for unchoke by download rate and secondary
|
||||
// by total upload. The reason for this is, if all torrents are being seeded,
|
||||
// the download rate will be 0, and the peers we have sent the least to should
|
||||
// be unchoked
|
||||
|
||||
// TODO: use partial_sort
|
||||
|
||||
// TODO: make the comparison function a free function and move it into
|
||||
// this cpp file
|
||||
std::sort(peers.begin(), peers.end()
|
||||
, boost::bind(&peer_connection::unchoke_compare, _1, _2));
|
||||
|
||||
return upload_slots;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -93,6 +93,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/magnet_uri.hpp"
|
||||
#include "libtorrent/aux_/session_settings.hpp"
|
||||
#include "libtorrent/torrent_peer.hpp"
|
||||
#include "libtorrent/choker.hpp"
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING
|
||||
#include "libtorrent/socket_io.hpp"
|
||||
|
@ -599,7 +600,7 @@ namespace aux {
|
|||
update_download_rate();
|
||||
update_upload_rate();
|
||||
update_connections_limit();
|
||||
update_choking_algorithm();
|
||||
update_unchoke_limit();
|
||||
update_disk_threads();
|
||||
update_network_threads();
|
||||
update_upnp();
|
||||
|
@ -3869,28 +3870,10 @@ retry:
|
|||
torrent* t = p->associated_torrent().lock().get();
|
||||
torrent_peer* pi = p->peer_info_struct();
|
||||
|
||||
if (p->ignore_unchoke_slots() || t == 0 || pi == 0 || pi->web_seed || t->is_paused())
|
||||
if (p->ignore_unchoke_slots() || t == 0 || pi == 0
|
||||
|| pi->web_seed || t->is_paused())
|
||||
continue;
|
||||
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::bittyrant_choker)
|
||||
{
|
||||
if (!p->is_choked() && p->is_interesting())
|
||||
{
|
||||
if (!p->has_peer_choked())
|
||||
{
|
||||
// we're unchoked, we may want to lower our estimated
|
||||
// reciprocation rate
|
||||
p->decrease_est_reciprocation_rate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've unchoked this peer, and it hasn't reciprocated
|
||||
// we may want to increase our estimated reciprocation rate
|
||||
p->increase_est_reciprocation_rate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!p->is_peer_interested()
|
||||
|| p->is_disconnecting()
|
||||
|| p->is_connecting())
|
||||
|
@ -3910,116 +3893,34 @@ retry:
|
|||
t->choke_peer(*p);
|
||||
continue;
|
||||
}
|
||||
|
||||
peers.push_back(p.get());
|
||||
}
|
||||
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::rate_based_choker)
|
||||
// the unchoker wants an estimate of our upload rate capacity
|
||||
// (used by bittyrant)
|
||||
int max_upload_rate = upload_rate_limit(m_global_class);
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm)
|
||||
== settings_pack::bittyrant_choker
|
||||
&& max_upload_rate == 0)
|
||||
{
|
||||
m_allowed_upload_slots = 0;
|
||||
std::sort(peers.begin(), peers.end()
|
||||
, boost::bind(&peer_connection::upload_rate_compare, _1, _2));
|
||||
|
||||
#ifdef TORRENT_DEBUG
|
||||
for (std::vector<peer_connection*>::const_iterator i = peers.begin()
|
||||
, end(peers.end()), prev(peers.end()); i != end; ++i)
|
||||
{
|
||||
if (prev != end)
|
||||
{
|
||||
boost::shared_ptr<torrent> t1 = (*prev)->associated_torrent().lock();
|
||||
TORRENT_ASSERT(t1);
|
||||
boost::shared_ptr<torrent> t2 = (*i)->associated_torrent().lock();
|
||||
TORRENT_ASSERT(t2);
|
||||
TORRENT_ASSERT((*prev)->uploaded_in_last_round() * 1000
|
||||
* (1 + t1->priority()) / total_milliseconds(unchoke_interval)
|
||||
>= (*i)->uploaded_in_last_round() * 1000
|
||||
* (1 + t2->priority()) / total_milliseconds(unchoke_interval));
|
||||
}
|
||||
prev = i;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: make configurable
|
||||
int rate_threshold = 1024;
|
||||
|
||||
for (std::vector<peer_connection*>::const_iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection const& p = **i;
|
||||
int rate = int(p.uploaded_in_last_round()
|
||||
* 1000 / total_milliseconds(unchoke_interval));
|
||||
|
||||
if (rate < rate_threshold) break;
|
||||
|
||||
++m_allowed_upload_slots;
|
||||
|
||||
// TODO: make configurable
|
||||
rate_threshold += 1024;
|
||||
}
|
||||
// allow one optimistic unchoke
|
||||
++m_allowed_upload_slots;
|
||||
// we don't know at what rate we can upload. If we have a
|
||||
// measurement of the peak, use that + 10kB/s, otherwise
|
||||
// assume 20 kB/s
|
||||
max_upload_rate = (std::max)(20000, m_peak_up_rate + 10000);
|
||||
if (m_alerts.should_post<performance_alert>())
|
||||
m_alerts.post_alert(performance_alert(torrent_handle()
|
||||
, performance_alert::bittyrant_with_no_uplimit));
|
||||
}
|
||||
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::bittyrant_choker)
|
||||
{
|
||||
// if we're using the bittyrant choker, sort peers by their return
|
||||
// on investment. i.e. download rate / upload rate
|
||||
std::sort(peers.begin(), peers.end()
|
||||
, boost::bind(&peer_connection::bittyrant_unchoke_compare, _1, _2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// sorts the peers that are eligible for unchoke by download rate and secondary
|
||||
// by total upload. The reason for this is, if all torrents are being seeded,
|
||||
// the download rate will be 0, and the peers we have sent the least to should
|
||||
// be unchoked
|
||||
std::sort(peers.begin(), peers.end()
|
||||
, boost::bind(&peer_connection::unchoke_compare, _1, _2));
|
||||
}
|
||||
|
||||
// auto unchoke
|
||||
peer_class* gpc = m_classes.at(m_global_class);
|
||||
int upload_limit = gpc->channel[peer_connection::upload_channel].throttle();
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::auto_expand_choker
|
||||
&& upload_limit > 0)
|
||||
{
|
||||
// if our current upload rate is less than 90% of our
|
||||
// limit
|
||||
if (m_stat.upload_rate() < upload_limit * 0.9f
|
||||
&& m_allowed_upload_slots
|
||||
<= m_stats_counters[counters::num_peers_up_unchoked] + 1
|
||||
&& m_upload_rate.queue_size() < 2)
|
||||
{
|
||||
++m_allowed_upload_slots;
|
||||
}
|
||||
else if (m_upload_rate.queue_size() > 1
|
||||
&& m_allowed_upload_slots > m_settings.get_int(settings_pack::unchoke_slots_limit)
|
||||
&& m_settings.get_int(settings_pack::unchoke_slots_limit) >= 0)
|
||||
{
|
||||
--m_allowed_upload_slots;
|
||||
}
|
||||
}
|
||||
m_allowed_upload_slots = unchoke_sort(peers, max_upload_rate
|
||||
, unchoke_interval, m_settings);
|
||||
|
||||
int num_opt_unchoke = m_settings.get_int(settings_pack::num_optimistic_unchoke_slots);
|
||||
if (num_opt_unchoke == 0) num_opt_unchoke = (std::max)(1, m_allowed_upload_slots / 5);
|
||||
|
||||
// reserve some upload slots for optimistic unchokes
|
||||
int unchoke_set_size = m_allowed_upload_slots - num_opt_unchoke;
|
||||
|
||||
int upload_capacity_left = 0;
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::bittyrant_choker)
|
||||
{
|
||||
upload_capacity_left = upload_rate_limit(m_global_class);
|
||||
if (upload_capacity_left == 0)
|
||||
{
|
||||
// we don't know at what rate we can upload. If we have a
|
||||
// measurement of the peak, use that + 10kB/s, otherwise
|
||||
// assume 20 kB/s
|
||||
upload_capacity_left = (std::max)(20000, m_peak_up_rate + 10000);
|
||||
if (m_alerts.should_post<performance_alert>())
|
||||
m_alerts.post_alert(performance_alert(torrent_handle()
|
||||
, performance_alert::bittyrant_with_no_uplimit));
|
||||
}
|
||||
}
|
||||
int unchoke_set_size = m_allowed_upload_slots;
|
||||
|
||||
// go through all the peers and unchoke the first ones and choke
|
||||
// all the other ones.
|
||||
|
@ -4037,22 +3938,8 @@ retry:
|
|||
torrent* t = p->associated_torrent().lock().get();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
// if this peer should be unchoked depends on different things
|
||||
// in different unchoked schemes
|
||||
bool unchoke = false;
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::bittyrant_choker)
|
||||
if (unchoke_set_size > 0)
|
||||
{
|
||||
unchoke = p->est_reciprocation_rate() <= upload_capacity_left;
|
||||
}
|
||||
else
|
||||
{
|
||||
unchoke = unchoke_set_size > 0;
|
||||
}
|
||||
|
||||
if (unchoke)
|
||||
{
|
||||
upload_capacity_left -= p->est_reciprocation_rate();
|
||||
|
||||
// yes, this peer should be unchoked
|
||||
if (p->is_choked())
|
||||
{
|
||||
|
@ -5835,23 +5722,20 @@ retry:
|
|||
m_settings.set_str(settings_pack::user_agent, agent);
|
||||
}
|
||||
|
||||
void session_impl::update_choking_algorithm()
|
||||
void session_impl::update_unchoke_limit()
|
||||
{
|
||||
int algo = m_settings.get_int(settings_pack::choking_algorithm);
|
||||
int unchoke_limit = m_settings.get_int(settings_pack::unchoke_slots_limit);
|
||||
|
||||
if (algo == settings_pack::fixed_slots_choker)
|
||||
m_allowed_upload_slots = unchoke_limit;
|
||||
else if (algo == settings_pack::auto_expand_choker)
|
||||
m_allowed_upload_slots = unchoke_limit;
|
||||
|
||||
m_allowed_upload_slots = unchoke_limit;
|
||||
|
||||
if (m_allowed_upload_slots < 0)
|
||||
m_allowed_upload_slots = (std::numeric_limits<int>::max)();
|
||||
|
||||
m_stats_counters.set_value(counters::num_unchoke_slots
|
||||
, m_allowed_upload_slots);
|
||||
|
||||
if (m_settings.get_int(settings_pack::num_optimistic_unchoke_slots) >= m_allowed_upload_slots / 2)
|
||||
if (m_settings.get_int(settings_pack::num_optimistic_unchoke_slots)
|
||||
>= m_allowed_upload_slots / 2)
|
||||
{
|
||||
if (m_alerts.should_post<performance_alert>())
|
||||
m_alerts.post_alert(performance_alert(torrent_handle()
|
||||
|
@ -6642,8 +6526,7 @@ retry:
|
|||
std::set<peer_connection*> unique_peers;
|
||||
#endif
|
||||
TORRENT_ASSERT(m_settings.get_int(settings_pack::connections_limit) > 0);
|
||||
if (m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::auto_expand_choker)
|
||||
TORRENT_ASSERT(m_allowed_upload_slots >= m_settings.get_int(settings_pack::unchoke_slots_limit));
|
||||
|
||||
int unchokes = 0;
|
||||
int unchokes_all = 0;
|
||||
int num_optimistic = 0;
|
||||
|
|
|
@ -236,7 +236,7 @@ namespace libtorrent
|
|||
SET(send_buffer_low_watermark, 512, 0),
|
||||
SET(send_buffer_watermark, 500 * 1024, 0),
|
||||
SET(send_buffer_watermark_factor, 50, 0),
|
||||
SET(choking_algorithm, settings_pack::fixed_slots_choker, &session_impl::update_choking_algorithm),
|
||||
SET(choking_algorithm, settings_pack::fixed_slots_choker, 0),
|
||||
SET(seed_choking_algorithm, settings_pack::round_robin, 0),
|
||||
SET(cache_size, 1024, 0),
|
||||
SET(cache_buffer_chunk_size, 0, &session_impl::update_cache_buffer_chunk_size),
|
||||
|
@ -292,7 +292,7 @@ namespace libtorrent
|
|||
DEPRECATED_SET(local_upload_rate_limit, 0, &session_impl::update_local_upload_rate),
|
||||
DEPRECATED_SET(local_download_rate_limit, 0, &session_impl::update_local_download_rate),
|
||||
SET(dht_upload_rate_limit, 4000, &session_impl::update_dht_upload_rate_limit),
|
||||
SET(unchoke_slots_limit, 8, &session_impl::update_choking_algorithm),
|
||||
SET(unchoke_slots_limit, 8, &session_impl::update_unchoke_limit),
|
||||
DEPRECATED_SET(half_open_limit, 0, 0),
|
||||
SET(connections_limit, 200, &session_impl::update_connections_limit),
|
||||
SET(connections_slack, 10, 0),
|
||||
|
|
|
@ -57,16 +57,19 @@ void test_swarm()
|
|||
// this is to avoid everything finish from a single peer
|
||||
// immediately. To make the swarm actually connect all
|
||||
// three peers before finishing.
|
||||
float rate_limit = 100000;
|
||||
float rate_limit = 50000;
|
||||
|
||||
settings_pack pack;
|
||||
pack.set_int(settings_pack::alert_mask, alert::all_categories);
|
||||
pack.set_bool(settings_pack::allow_multiple_connections_per_ip, true);
|
||||
pack.set_int(settings_pack::choking_algorithm, settings_pack::auto_expand_choker);
|
||||
pack.set_int(settings_pack::choking_algorithm, settings_pack::rate_based_choker);
|
||||
pack.set_int(settings_pack::upload_rate_limit, rate_limit);
|
||||
pack.set_int(settings_pack::unchoke_slots_limit, 1);
|
||||
pack.set_int(settings_pack::max_retry_port_bind, 900);
|
||||
pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:48010");
|
||||
pack.set_bool(settings_pack::enable_natpmp, false);
|
||||
pack.set_bool(settings_pack::enable_upnp, false);
|
||||
pack.set_bool(settings_pack::enable_dht, false);
|
||||
|
||||
pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_forced);
|
||||
pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_forced);
|
||||
|
@ -76,6 +79,7 @@ void test_swarm()
|
|||
pack.set_int(settings_pack::upload_rate_limit, rate_limit / 10);
|
||||
pack.set_int(settings_pack::download_rate_limit, rate_limit / 5);
|
||||
pack.set_int(settings_pack::unchoke_slots_limit, 0);
|
||||
pack.set_int(settings_pack::choking_algorithm, settings_pack::fixed_slots_choker);
|
||||
pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:49010");
|
||||
|
||||
lt::session ses2(pack, fingerprint("LT", 0, 1, 0, 0));
|
||||
|
@ -93,7 +97,7 @@ void test_swarm()
|
|||
session_status st = ses1.status();
|
||||
fprintf(stderr, "st.allowed_upload_slots: %d\n", st.allowed_upload_slots);
|
||||
TEST_EQUAL(st.allowed_upload_slots, 1);
|
||||
for (int i = 0; i < 100; ++i)
|
||||
for (int i = 0; i < 200; ++i)
|
||||
{
|
||||
print_alerts(ses1, "ses1");
|
||||
print_alerts(ses2, "ses2");
|
||||
|
@ -107,7 +111,7 @@ void test_swarm()
|
|||
torrent_status st2 = tor2.status();
|
||||
torrent_status st3 = tor3.status();
|
||||
|
||||
print_ses_rate(i, &st1, &st2, &st3);
|
||||
print_ses_rate(i / 10.f, &st1, &st2, &st3);
|
||||
|
||||
test_sleep(100);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue