1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-27 18:18:10 +00:00

(trunk, libT) #5199 'tr_sessionGetNextQueuedTorrent() can be faster' -- modify session.c's tr_sessionGetNextQueuedTorrents() and peer-mgr.c's getPeerCandidates() functions use the new tr_quickfindFirstK() utility"

This commit is contained in:
Jordan Lee 2012-12-28 20:10:03 +00:00
parent 25b8b60245
commit aa906ced75
3 changed files with 104 additions and 97 deletions

View file

@ -3590,24 +3590,36 @@ pumpAllPeers (tr_peerMgr * mgr)
} }
} }
static void
queuePulseForeach (void * vtor)
{
tr_torrent * tor = vtor;
tr_torrentStartNow (tor);
if (tor->queue_started_callback != NULL)
(*tor->queue_started_callback)(tor, tor->queue_started_user_data);
}
static void static void
queuePulse (tr_session * session, tr_direction dir) queuePulse (tr_session * session, tr_direction dir)
{ {
assert (tr_isSession (session)); assert (tr_isSession (session));
assert (tr_isDirection (dir)); assert (tr_isDirection (dir));
if (tr_sessionGetQueueEnabled (session, dir)) if (tr_sessionGetQueueEnabled (session, dir))
{ {
int i; tr_ptrArray torrents = TR_PTR_ARRAY_INIT;
const int n = tr_sessionCountQueueFreeSlots (session, dir);
for (i=0; i<n; i++) { tr_sessionGetNextQueuedTorrents (session,
tr_torrent * tor = tr_sessionGetNextQueuedTorrent (session, dir); dir,
if (tor != NULL) { tr_sessionCountQueueFreeSlots (session, dir),
tr_torrentStartNow (tor); &torrents);
if (tor->queue_started_callback != NULL)
(*tor->queue_started_callback)(tor, tor->queue_started_user_data); tr_ptrArrayForeach (&torrents, queuePulseForeach);
}
} tr_ptrArrayDestruct (&torrents, NULL);
} }
} }
@ -3877,79 +3889,33 @@ getPeerCandidateScore (const tr_torrent * tor, const struct peer_atom * atom, ui
return score; return score;
} }
#ifndef NDEBUG
static int static int
checkPartition (const struct peer_candidate * candidates, int left, int right, uint64_t pivotScore, int storeIndex) comparePeerCandidates (const void * va, const void * vb)
{ {
int i; int ret;
const struct peer_candidate * a = va;
const struct peer_candidate * b = vb;
assert (storeIndex >= left); if (a->score < b->score)
assert (storeIndex <= right); ret = -1;
assert (candidates[storeIndex].score == pivotScore); else if (a->score > b->score)
ret = 1;
else
ret = 0;
for (i=left; i<storeIndex; ++i) return ret;
assert (candidates[i].score < pivotScore);
for (i=storeIndex+1; i<=right; ++i)
assert (candidates[i].score >= pivotScore);
return true;
}
#endif
/* Helper to selectPeerCandidates().
* Adapted from http://en.wikipedia.org/wiki/Selection_algorithm */
static int
partitionPeerCandidates (struct peer_candidate * candidates, int left, int right, int pivotIndex)
{
int i;
int storeIndex;
struct peer_candidate tmp;
const struct peer_candidate pivotValue = candidates[pivotIndex];
/* move pivot to end */
tmp = candidates[right];
candidates[right] = pivotValue;
candidates[pivotIndex] = tmp;
storeIndex = left;
for (i=left; i<=right; ++i)
{
if (candidates[i].score < pivotValue.score)
{
tmp = candidates[storeIndex];
candidates[storeIndex] = candidates[i];
candidates[i] = tmp;
storeIndex++;
}
}
/* move pivot to its final place */
tmp = candidates[right];
candidates[right] = candidates[storeIndex];
candidates[storeIndex] = tmp;
/* sanity check */
assert (checkPartition (candidates, left, right, pivotValue.score, storeIndex));
return storeIndex;
} }
/* Partial sorting -- selecting the k best candidates /* Partial sorting -- selecting the k best candidates
Adapted from http://en.wikipedia.org/wiki/Selection_algorithm */ Adapted from http://en.wikipedia.org/wiki/Selection_algorithm */
static void static void
selectPeerCandidates (struct peer_candidate * candidates, int left, int right, int k) selectPeerCandidates (struct peer_candidate * candidates, int candidate_count, int select_count)
{ {
if (right > left) tr_quickfindFirstK (candidates,
{ candidate_count,
const int pivotIndex = left + (right-left)/2; sizeof(struct peer_candidate),
comparePeerCandidates,
int pivotNewIndex = partitionPeerCandidates (candidates, left, right, pivotIndex); select_count);
if (pivotNewIndex > left + k) /* new condition */
selectPeerCandidates (candidates, left, pivotNewIndex-1, k);
else if (pivotNewIndex < left + k)
selectPeerCandidates (candidates, pivotNewIndex+1, right, k+left-pivotNewIndex-1);
}
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -4042,7 +4008,7 @@ getPeerCandidates (tr_session * session, int * candidateCount, int max)
*candidateCount = walk - candidates; *candidateCount = walk - candidates;
if (walk != candidates) if (walk != candidates)
selectPeerCandidates (candidates, 0, (walk-candidates)-1, max); selectPeerCandidates (candidates, walk-candidates, max);
assert (checkBestScoresComeFirst (candidates, *candidateCount, max)); assert (checkBestScoresComeFirst (candidates, *candidateCount, max));

View file

@ -2713,33 +2713,74 @@ tr_sessionGetQueueStalledMinutes (const tr_session * session)
return session->queueStalledMinutes; return session->queueStalledMinutes;
} }
tr_torrent * struct TorrentAndPosition
tr_sessionGetNextQueuedTorrent (tr_session * session, tr_direction direction)
{ {
tr_torrent * tor = NULL; tr_torrent * tor;
tr_torrent * best_tor = NULL; int position;
int best_position = INT_MAX; };
assert (tr_isSession (session)); /* higher positions come first */
assert (tr_isDirection (direction)); static int
compareTorrentAndPositions (const void * va, const void * vb)
{
int ret;
const struct TorrentAndPosition * a = va;
const struct TorrentAndPosition * b = vb;
while ((tor = tr_torrentNext (session, tor))) if (a->position > b->position)
ret = -1;
else if (a->position < b->position)
ret = 1;
else
ret = 0;
return ret;
}
void
tr_sessionGetNextQueuedTorrents (tr_session * session,
tr_direction direction,
size_t num_wanted,
tr_ptrArray * setme)
{
size_t i;
tr_torrent * tor;
struct TorrentAndPosition * candidates;
assert (tr_isSession (session));
assert (tr_isDirection (direction));
/* build an array of the candidates */
candidates = tr_new (struct TorrentAndPosition, session->torrentCount);
tor = NULL;
while ((tor = tr_torrentNext (session, tor)))
{ {
int position; if (!tr_torrentIsQueued (tor))
continue;
if (!tr_torrentIsQueued (tor)) if (direction != tr_torrentGetQueueDirection (tor))
continue; continue;
if (direction != tr_torrentGetQueueDirection (tor))
continue;
position = tr_torrentGetQueuePosition (tor); candidates[i].tor = tor;
if (best_position > position) { candidates[i].position = tr_torrentGetQueuePosition (tor);
best_position = position; ++i;
best_tor = tor;
}
} }
return best_tor; /* find the best n candidates */
if (num_wanted > i)
num_wanted = i;
else if (num_wanted < i)
tr_quickfindFirstK (candidates, i,
sizeof(struct TorrentAndPosition),
compareTorrentAndPositions, num_wanted);
/* add them to the return array */
for (i=0; i<num_wanted; ++i)
tr_ptrArrayAppend (setme, candidates[i].tor);
/* cleanup */
tr_free (candidates);
} }
int int

View file

@ -329,7 +329,7 @@ bool tr_sessionGetActiveSpeedLimit_Bps (const tr_session * session,
unsigned int * setme); unsigned int * setme);
tr_torrent * tr_sessionGetNextQueuedSeed (tr_session * session); tr_torrent * tr_sessionGetNextQueuedSeed (tr_session * session);
tr_torrent * tr_sessionGetNextQueuedTorrent (tr_session * session, tr_direction); void tr_sessionGetNextQueuedTorrents (tr_session * session, tr_direction, size_t n, tr_ptrArray * steme);
int tr_sessionCountQueueFreeSlots (tr_session * session, tr_direction); int tr_sessionCountQueueFreeSlots (tr_session * session, tr_direction);