1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-25 09:13:06 +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:
Charles Kerr 2009-09-10 02:20:35 +00:00
parent 2a69dab92f
commit fb83a0464e
4 changed files with 76 additions and 32 deletions

View file

@ -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 );

View file

@ -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 );

View file

@ -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 );

View file

@ -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;
}