From c471bcb49f3a5ed46edfc22b68a51f704425c45f Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 17 Sep 2014 07:23:41 +0000 Subject: [PATCH] optimize peer classes a bit --- include/libtorrent/peer_class.hpp | 44 ++++++++++++++------------- include/libtorrent/peer_class_set.hpp | 21 +++++++------ src/peer_class_set.cpp | 29 +++++++++++++----- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/include/libtorrent/peer_class.hpp b/include/libtorrent/peer_class.hpp index 4b313bdea..9da4952cc 100644 --- a/include/libtorrent/peer_class.hpp +++ b/include/libtorrent/peer_class.hpp @@ -44,38 +44,40 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - typedef boost::uint32_t peer_class_t; + typedef boost::uint8_t peer_class_t; struct peer_class_info { - // ``ignore_unchoke_slots`` determines whether peers should always unchoke a peer, - // regardless of the choking algorithm, or if it should honor the unchoke slot limits. - // It's used for local peers by default. If *any* of the peer classes a peer belongs to - // has this set to true, that peer will be unchoked at all times. + // ``ignore_unchoke_slots`` determines whether peers should always + // unchoke a peer, regardless of the choking algorithm, or if it should + // honor the unchoke slot limits. It's used for local peers by default. + // If *any* of the peer classes a peer belongs to has this set to true, + // that peer will be unchoked at all times. bool ignore_unchoke_slots; - // adjusts the connection limit (global and per torrent) that - // applies to this peer class. By default, local peers are allowed to exceed the normal - // connection limit for instance. This is specified as a percent factor. 100 makes - // the peer class apply normally to the limit. 200 means as long as there are fewer - // connections than twice the limit, we accept this peer. This factor applies both to - // the global connection limit and the per-torrent limit. Note that if not used carefully - // one peer class can potentially completely starve out all other over time. + // adjusts the connection limit (global and per torrent) that applies to + // this peer class. By default, local peers are allowed to exceed the + // normal connection limit for instance. This is specified as a percent + // factor. 100 makes the peer class apply normally to the limit. 200 + // means as long as there are fewer connections than twice the limit, we + // accept this peer. This factor applies both to the global connection + // limit and the per-torrent limit. Note that if not used carefully one + // peer class can potentially completely starve out all other over time. int connection_limit_factor; - // not used by libtorrent. It's intended as a potentially user-facing identifier - // of this peer class. + // not used by libtorrent. It's intended as a potentially user-facing + // identifier of this peer class. std::string label; - // transfer rates limits for the whole peer class. - // They are specified in bytes per second and apply to the sum of all peers that are - // members of this class. + // transfer rates limits for the whole peer class. They are specified in + // bytes per second and apply to the sum of all peers that are members of + // this class. int upload_limit; int download_limit; - // relative priorities used by the - // bandwidth allocator in the rate limiter. If no rate limits are in use, the priority - // is not used either. Priorities start at 1 (0 is not a valid priority) and may not + // relative priorities used by the bandwidth allocator in the rate + // limiter. If no rate limits are in use, the priority is not used + // either. Priorities start at 1 (0 is not a valid priority) and may not // exceed 255. int upload_priority; int download_priority; @@ -137,7 +139,7 @@ namespace libtorrent std::vector > m_peer_classes; // indices in m_peer_classes that are no longer used - std::vector m_free_list; + std::vector m_free_list; }; } diff --git a/include/libtorrent/peer_class_set.hpp b/include/libtorrent/peer_class_set.hpp index b45c3c59b..092833256 100644 --- a/include/libtorrent/peer_class_set.hpp +++ b/include/libtorrent/peer_class_set.hpp @@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_PEER_CLASS_SET_HPP_INCLUDED #include "libtorrent/peer_class.hpp" -#include +#include namespace libtorrent { @@ -42,24 +42,27 @@ namespace libtorrent { // to it. Most notably, peer connections and torrents derive from this. struct peer_class_set { + peer_class_set() : m_size(0) {} void add_class(peer_class_pool& pool, peer_class_t c); bool has_class(peer_class_t c) const; void remove_class(peer_class_pool& pool, peer_class_t c); - int num_classes() const { return m_class.size(); } + int num_classes() const { return m_size; } peer_class_t class_at(int i) const { - TORRENT_ASSERT(i >= 0 && i < int(m_class.size())); + TORRENT_ASSERT(i >= 0 && i < int(m_size)); return m_class[i]; } private: - // if this object belongs to any peer-class, this - // vector contains all class IDs. Each ID refers - // to a an entry in m_ses.m_peer_classes which - // holds the metadata about the class. Classes - // affect bandwidth limits among other things - std::vector m_class; + // the number of elements used in the m_class array + boost::uint8_t m_size; + + // if this object belongs to any peer-class, this vector contains all + // class IDs. Each ID refers to a an entry in m_ses.m_peer_classes which + // holds the metadata about the class. Classes affect bandwidth limits + // among other things + boost::array m_class; }; } diff --git a/src/peer_class_set.cpp b/src/peer_class_set.cpp index 03fa4ce6d..84e366610 100644 --- a/src/peer_class_set.cpp +++ b/src/peer_class_set.cpp @@ -33,27 +33,42 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/peer_class_set.hpp" #include "libtorrent/peer_class.hpp" #include -#include // for_find +#include // for find namespace libtorrent { void peer_class_set::add_class(peer_class_pool& pool, peer_class_t c) { - if (std::find(m_class.begin(), m_class.end(), c) != m_class.end()) return; - m_class.push_back(c); + if (std::find(m_class.begin(), m_class.begin() + m_size, c) + != m_class.begin() + m_size) return; + if (m_size >= m_class.size() - 1) + { + assert(false); + return; + } + m_class[m_size] = c; pool.incref(c); + ++m_size; } bool peer_class_set::has_class(peer_class_t c) const { - return std::find(m_class.begin(), m_class.end(), c) != m_class.end(); + return std::find(m_class.begin(), m_class.begin() + m_size, c) + != m_class.begin() + m_size; } void peer_class_set::remove_class(peer_class_pool& pool, peer_class_t c) { - std::vector::iterator i = std::find(m_class.begin(), m_class.end(), c); - if (i == m_class.end()) return; - m_class.erase(i); + boost::array::iterator i = std::find(m_class.begin() + , m_class.begin() + m_size, c); + int idx = i - m_class.begin(); + if (idx == m_size) return; // not found + if (idx < m_size - 1) + { + // place the last element in the slot of the erased one + m_class[idx] = m_class[m_size - 1]; + } + --m_size; pool.decref(c); } }