mirror of
https://github.com/transmission/transmission
synced 2024-12-24 16:52:39 +00:00
(trunk libT) #2395: caching too many peers between sessions makes startup slow and uses too much memory (KyleK, stdisease, et al)
This commit is contained in:
parent
2a69dab92f
commit
fb83a0464e
4 changed files with 76 additions and 32 deletions
|
@ -1520,8 +1520,28 @@ peerPrefersCrypto( const tr_peer * peer )
|
|||
}
|
||||
#endif
|
||||
|
||||
/* better goes first */
|
||||
static int
|
||||
compareAtomsByUsefulness( const void * va, const void *vb )
|
||||
{
|
||||
const struct peer_atom * a = * (const struct peer_atom**) va;
|
||||
const struct peer_atom * b = * (const struct peer_atom**) vb;
|
||||
|
||||
assert( ( 0 < a->from ) && ( a->from < TR_PEER_FROM__MAX ) );
|
||||
assert( ( 0 < b->from ) && ( b->from < TR_PEER_FROM__MAX ) );
|
||||
|
||||
if( a->piece_data_time != b->piece_data_time )
|
||||
return a->piece_data_time > b->piece_data_time ? -1 : 1;
|
||||
if( a->from != b->from )
|
||||
return a->from < b->from ? -1 : 1;
|
||||
if( a->numFails != b->numFails )
|
||||
return a->numFails < b->numFails ? -1 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tr_peerMgrGetPeers( tr_torrent * tor, tr_pex ** setme_pex, uint8_t af )
|
||||
tr_peerMgrGetPeers( tr_torrent * tor, tr_pex ** setme_pex, uint8_t af, int maxPeerCount )
|
||||
{
|
||||
int count = 0;
|
||||
const Torrent * t = tor->torrentPeers;
|
||||
|
@ -1530,14 +1550,18 @@ tr_peerMgrGetPeers( tr_torrent * tor, tr_pex ** setme_pex, uint8_t af )
|
|||
|
||||
{
|
||||
int i;
|
||||
const struct peer_atom ** atoms = (const struct peer_atom**) tr_ptrArrayBase( &t->pool );
|
||||
const int atomCount = tr_ptrArraySize( &t->pool );
|
||||
const int pexCount = MIN( atomCount, maxPeerCount );
|
||||
const struct peer_atom ** atomsBase = (const struct peer_atom**) tr_ptrArrayBase( &t->pool );
|
||||
struct peer_atom ** atoms = tr_memdup( atomsBase, atomCount * sizeof( struct peer_atom * ) );
|
||||
/* for now, this will waste memory on torrents that have both
|
||||
* ipv6 and ipv4 peers */
|
||||
tr_pex * pex = tr_new0( tr_pex, atomCount );
|
||||
tr_pex * walk = pex;
|
||||
|
||||
for( i=0; i<atomCount; ++i )
|
||||
qsort( atoms, atomCount, sizeof( struct peer_atom * ), compareAtomsByUsefulness );
|
||||
|
||||
for( i=0; i<atomCount && count<pexCount; ++i )
|
||||
{
|
||||
const struct peer_atom * atom = atoms[i];
|
||||
if( atom->addr.type == af )
|
||||
|
@ -1552,8 +1576,9 @@ tr_peerMgrGetPeers( tr_torrent * tor, tr_pex ** setme_pex, uint8_t af )
|
|||
}
|
||||
|
||||
assert( ( walk - pex ) == count );
|
||||
qsort( pex, count, sizeof( tr_pex ), tr_pexCompare );
|
||||
*setme_pex = pex;
|
||||
|
||||
tr_free( atoms );
|
||||
}
|
||||
|
||||
managerUnlock( t->manager );
|
||||
|
|
|
@ -150,7 +150,8 @@ void tr_peerMgrSetBlame( tr_torrent * tor,
|
|||
|
||||
int tr_peerMgrGetPeers( tr_torrent * tor,
|
||||
tr_pex ** setme_pex,
|
||||
uint8_t af);
|
||||
uint8_t af,
|
||||
int maxPeerCount );
|
||||
|
||||
void tr_peerMgrStartTorrent( tr_torrent * tor );
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ enum
|
|||
|
||||
TR_LTEP_PEX = 1,
|
||||
|
||||
|
||||
MAX_PEX_PEER_COUNT = 100,
|
||||
|
||||
MIN_CHOKE_PERIOD_SEC = ( 10 ),
|
||||
|
||||
|
@ -1975,8 +1975,8 @@ sendPex( tr_peermsgs * msgs )
|
|||
PexDiffs diffs6;
|
||||
tr_pex * newPex = NULL;
|
||||
tr_pex * newPex6 = NULL;
|
||||
const int newCount = tr_peerMgrGetPeers( msgs->torrent, &newPex, TR_AF_INET );
|
||||
const int newCount6 = tr_peerMgrGetPeers( msgs->torrent, &newPex6, TR_AF_INET6 );
|
||||
const int newCount = tr_peerMgrGetPeers( msgs->torrent, &newPex, TR_AF_INET, MAX_PEX_PEER_COUNT );
|
||||
const int newCount6 = tr_peerMgrGetPeers( msgs->torrent, &newPex6, TR_AF_INET6, MAX_PEX_PEER_COUNT );
|
||||
|
||||
/* build the diffs */
|
||||
diffs.added = tr_new( tr_pex, newCount );
|
||||
|
|
|
@ -58,6 +58,11 @@
|
|||
#define KEY_PROGRESS_MTIMES "mtimes"
|
||||
#define KEY_PROGRESS_BITFIELD "bitfield"
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_REMEMBERED_PEERS = 200
|
||||
};
|
||||
|
||||
static char*
|
||||
getResumeFilename( const tr_torrent * tor )
|
||||
{
|
||||
|
@ -73,27 +78,54 @@ getResumeFilename( const tr_torrent * tor )
|
|||
***/
|
||||
|
||||
static void
|
||||
savePeers( tr_benc * dict,
|
||||
const tr_torrent * tor )
|
||||
savePeers( tr_benc * dict, const tr_torrent * tor )
|
||||
{
|
||||
int count;
|
||||
tr_pex * pex;
|
||||
|
||||
count = tr_peerMgrGetPeers( (tr_torrent*) tor, &pex, TR_AF_INET );
|
||||
count = tr_peerMgrGetPeers( (tr_torrent*) tor, &pex, TR_AF_INET, MAX_REMEMBERED_PEERS );
|
||||
if( count > 0 )
|
||||
tr_bencDictAddRaw( dict, KEY_PEERS, pex, sizeof( tr_pex ) * count );
|
||||
tr_free( pex );
|
||||
|
||||
count = tr_peerMgrGetPeers( (tr_torrent*) tor, &pex, TR_AF_INET6 );
|
||||
count = tr_peerMgrGetPeers( (tr_torrent*) tor, &pex, TR_AF_INET6, MAX_REMEMBERED_PEERS );
|
||||
if( count > 0 )
|
||||
tr_bencDictAddRaw( dict, KEY_PEERS6, pex, sizeof( tr_pex ) * count );
|
||||
|
||||
tr_free( pex );
|
||||
}
|
||||
|
||||
static tr_bool
|
||||
tr_isPex( const tr_pex * pex )
|
||||
{
|
||||
return tr_isAddress( &pex->addr )
|
||||
&& ( pex->flags & 3 ) == pex->flags;
|
||||
}
|
||||
|
||||
static int
|
||||
addPeers( tr_torrent * tor, const uint8_t * buf, int buflen )
|
||||
{
|
||||
int i;
|
||||
int numAdded = 0;
|
||||
const int count = buflen / sizeof( tr_pex );
|
||||
|
||||
for( i=0; i<count && numAdded<MAX_REMEMBERED_PEERS; ++i )
|
||||
{
|
||||
tr_pex pex;
|
||||
memcpy( &pex, buf + ( i * sizeof( tr_pex ) ), sizeof( tr_pex ) );
|
||||
if( tr_isPex( &pex ) )
|
||||
{
|
||||
tr_peerMgrAddPex( tor, TR_PEER_FROM_CACHE, &pex );
|
||||
++numAdded;
|
||||
}
|
||||
}
|
||||
|
||||
return numAdded;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t
|
||||
loadPeers( tr_benc * dict,
|
||||
tr_torrent * tor )
|
||||
loadPeers( tr_benc * dict, tr_torrent * tor )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
const uint8_t * str;
|
||||
|
@ -101,29 +133,15 @@ loadPeers( tr_benc * dict,
|
|||
|
||||
if( tr_bencDictFindRaw( dict, KEY_PEERS, &str, &len ) )
|
||||
{
|
||||
int i;
|
||||
const int count = len / sizeof( tr_pex );
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
tr_pex pex;
|
||||
memcpy( &pex, str + ( i * sizeof( tr_pex ) ), sizeof( tr_pex ) );
|
||||
tr_peerMgrAddPex( tor, TR_PEER_FROM_CACHE, &pex );
|
||||
}
|
||||
tr_tordbg( tor, "Loaded %d IPv4 peers from resume file", count );
|
||||
const int numAdded = addPeers( tor, str, len );
|
||||
tr_tordbg( tor, "Loaded %d IPv4 peers from resume file", numAdded );
|
||||
ret = TR_FR_PEERS;
|
||||
}
|
||||
|
||||
if( tr_bencDictFindRaw( dict, KEY_PEERS6, &str, &len ) )
|
||||
{
|
||||
int i;
|
||||
const int count = len / sizeof( tr_pex );
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
tr_pex pex;
|
||||
memcpy( &pex, str + ( i * sizeof( tr_pex ) ), sizeof( tr_pex ) );
|
||||
tr_peerMgrAddPex( tor, TR_PEER_FROM_CACHE, &pex );
|
||||
}
|
||||
tr_tordbg( tor, "Loaded %d IPv6 peers from resume file", count );
|
||||
const int numAdded = addPeers( tor, str, len );
|
||||
tr_tordbg( tor, "Loaded %d IPv6 peers from resume file", numAdded );
|
||||
ret = TR_FR_PEERS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue