storage optimization to peer classes

This commit is contained in:
arvidn 2017-01-20 23:30:05 -05:00 committed by Arvid Norberg
parent c57d062e0d
commit 6d17f0fb66
4 changed files with 33 additions and 23 deletions

View File

@ -1,3 +1,4 @@
* storage optimization to peer classes
* fix torrent name in alerts of builds with deprecated functions * fix torrent name in alerts of builds with deprecated functions
* make torrent_info::is_valid() return false if torrent failed to load * make torrent_info::is_valid() return false if torrent failed to load
* fix per-torrent rate limits for >256 peer classes * fix per-torrent rate limits for >256 peer classes

View File

@ -39,8 +39,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/disable_warnings_push.hpp" #include "libtorrent/aux_/disable_warnings_push.hpp"
#include <vector> #include <vector>
#include <deque>
#include <string> #include <string>
#include <boost/smart_ptr.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp" #include "libtorrent/aux_/disable_warnings_pop.hpp"
@ -86,12 +86,13 @@ namespace libtorrent
int download_priority; int download_priority;
}; };
struct TORRENT_EXTRA_EXPORT peer_class : boost::enable_shared_from_this<peer_class> struct TORRENT_EXTRA_EXPORT peer_class
{ {
friend struct peer_class_pool; friend struct peer_class_pool;
peer_class(std::string const& l) peer_class(std::string const& l)
: ignore_unchoke_slots(false) : in_use(true)
, ignore_unchoke_slots(false)
, connection_limit_factor(100) , connection_limit_factor(100)
, label(l) , label(l)
, references(1) , references(1)
@ -100,6 +101,12 @@ namespace libtorrent
priority[1] = 1; priority[1] = 1;
} }
void clear()
{
in_use = false;
label.clear();
}
void set_info(peer_class_info const* pci); void set_info(peer_class_info const* pci);
void get_info(peer_class_info* pci) const; void get_info(peer_class_info* pci) const;
@ -110,6 +117,9 @@ namespace libtorrent
// keeps track of the current quotas // keeps track of the current quotas
bandwidth_channel channel[2]; bandwidth_channel channel[2];
// this is set to false when this slot is not in use for a peer_class
bool in_use;
bool ignore_unchoke_slots; bool ignore_unchoke_slots;
int connection_limit_factor; int connection_limit_factor;
@ -123,7 +133,6 @@ namespace libtorrent
private: private:
int references; int references;
}; };
struct TORRENT_EXTRA_EXPORT peer_class_pool struct TORRENT_EXTRA_EXPORT peer_class_pool
@ -138,7 +147,7 @@ namespace libtorrent
// state for peer classes (a peer can belong to multiple classes) // state for peer classes (a peer can belong to multiple classes)
// this can control // this can control
std::vector<boost::shared_ptr<peer_class> > m_peer_classes; std::deque<peer_class> m_peer_classes;
// indices in m_peer_classes that are no longer used // indices in m_peer_classes that are no longer used
std::vector<peer_class_t> m_free_list; std::vector<peer_class_t> m_free_list;

View File

@ -84,16 +84,15 @@ namespace libtorrent
{ {
ret = m_free_list.back(); ret = m_free_list.back();
m_free_list.pop_back(); m_free_list.pop_back();
m_peer_classes[ret] = peer_class(label);
} }
else else
{ {
TORRENT_ASSERT(m_peer_classes.size() < 0x100000000); TORRENT_ASSERT(m_peer_classes.size() < 0x100000000);
ret = m_peer_classes.size(); ret = m_peer_classes.size();
m_peer_classes.push_back(boost::shared_ptr<peer_class>()); m_peer_classes.push_back(peer_class(label));
} }
TORRENT_ASSERT(m_peer_classes[ret].get() == 0);
m_peer_classes[ret] = boost::make_shared<peer_class>(label);
return ret; return ret;
} }
@ -103,11 +102,12 @@ namespace libtorrent
VALGRIND_CHECK_VALUE_IS_DEFINED(c); VALGRIND_CHECK_VALUE_IS_DEFINED(c);
#endif #endif
TORRENT_ASSERT(c < m_peer_classes.size()); TORRENT_ASSERT(c < m_peer_classes.size());
TORRENT_ASSERT(m_peer_classes[c].get()); TORRENT_ASSERT(m_peer_classes[c].in_use);
TORRENT_ASSERT(m_peer_classes[c].references > 0);
--m_peer_classes[c]->references; --m_peer_classes[c].references;
if (m_peer_classes[c]->references) return; if (m_peer_classes[c].references) return;
m_peer_classes[c].reset(); m_peer_classes[c].clear();
m_free_list.push_back(c); m_free_list.push_back(c);
} }
@ -117,9 +117,9 @@ namespace libtorrent
VALGRIND_CHECK_VALUE_IS_DEFINED(c); VALGRIND_CHECK_VALUE_IS_DEFINED(c);
#endif #endif
TORRENT_ASSERT(c < m_peer_classes.size()); TORRENT_ASSERT(c < m_peer_classes.size());
TORRENT_ASSERT(m_peer_classes[c].get()); TORRENT_ASSERT(m_peer_classes[c].in_use);
++m_peer_classes[c]->references; ++m_peer_classes[c].references;
} }
peer_class* peer_class_pool::at(peer_class_t c) peer_class* peer_class_pool::at(peer_class_t c)
@ -127,14 +127,14 @@ namespace libtorrent
#ifdef TORRENT_USE_VALGRIND #ifdef TORRENT_USE_VALGRIND
VALGRIND_CHECK_VALUE_IS_DEFINED(c); VALGRIND_CHECK_VALUE_IS_DEFINED(c);
#endif #endif
if (c >= m_peer_classes.size()) return 0; if (c >= m_peer_classes.size() || !m_peer_classes[c].in_use) return NULL;
return m_peer_classes[c].get(); return &m_peer_classes[c];
} }
peer_class const* peer_class_pool::at(peer_class_t c) const peer_class const* peer_class_pool::at(peer_class_t c) const
{ {
if (c >= m_peer_classes.size()) return 0; if (c >= m_peer_classes.size() || !m_peer_classes[c].in_use) return NULL;
return m_peer_classes[c].get(); return &m_peer_classes[c];
} }
} }

View File

@ -66,11 +66,11 @@ TORRENT_TEST(peer_class)
TEST_CHECK(id3 == id2 + 1); TEST_CHECK(id3 == id2 + 1);
// make sure refcounting works // make sure refcounting works
TEST_CHECK(class_name(id3, pool) == "test3"); TEST_EQUAL(class_name(id3, pool), "test3");
pool.incref(id3); pool.incref(id3);
TEST_CHECK(class_name(id3, pool) == "test3"); TEST_EQUAL(class_name(id3, pool), "test3");
pool.decref(id3); pool.decref(id3);
TEST_CHECK(class_name(id3, pool) == "test3"); TEST_EQUAL(class_name(id3, pool), "test3");
pool.decref(id3); pool.decref(id3);
// it should have been deleted now // it should have been deleted now
TEST_CHECK(pool.at(id3) == NULL); TEST_CHECK(pool.at(id3) == NULL);
@ -81,8 +81,8 @@ TORRENT_TEST(peer_class)
peer_class_info i; peer_class_info i;
pool.at(id2)->get_info(&i); pool.at(id2)->get_info(&i);
TEST_CHECK(i.upload_limit == 1000); TEST_EQUAL(i.upload_limit, 1000);
TEST_CHECK(i.download_limit == 2000); TEST_EQUAL(i.download_limit, 2000);
// test peer_class_type_filter // test peer_class_type_filter
peer_class_type_filter filter; peer_class_type_filter filter;