mirror of
https://github.com/transmission/transmission
synced 2024-12-26 09:37:56 +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:
parent
25b8b60245
commit
aa906ced75
3 changed files with 104 additions and 97 deletions
|
@ -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
|
||||
queuePulse (tr_session * session, tr_direction dir)
|
||||
{
|
||||
assert (tr_isSession (session));
|
||||
assert (tr_isDirection (dir));
|
||||
assert (tr_isSession (session));
|
||||
assert (tr_isDirection (dir));
|
||||
|
||||
if (tr_sessionGetQueueEnabled (session, dir))
|
||||
if (tr_sessionGetQueueEnabled (session, dir))
|
||||
{
|
||||
int i;
|
||||
const int n = tr_sessionCountQueueFreeSlots (session, dir);
|
||||
for (i=0; i<n; i++) {
|
||||
tr_torrent * tor = tr_sessionGetNextQueuedTorrent (session, dir);
|
||||
if (tor != NULL) {
|
||||
tr_torrentStartNow (tor);
|
||||
if (tor->queue_started_callback != NULL)
|
||||
(*tor->queue_started_callback)(tor, tor->queue_started_user_data);
|
||||
}
|
||||
}
|
||||
tr_ptrArray torrents = TR_PTR_ARRAY_INIT;
|
||||
|
||||
tr_sessionGetNextQueuedTorrents (session,
|
||||
dir,
|
||||
tr_sessionCountQueueFreeSlots (session, dir),
|
||||
&torrents);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
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);
|
||||
assert (storeIndex <= right);
|
||||
assert (candidates[storeIndex].score == pivotScore);
|
||||
if (a->score < b->score)
|
||||
ret = -1;
|
||||
else if (a->score > b->score)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
for (i=left; i<storeIndex; ++i)
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Partial sorting -- selecting the k best candidates
|
||||
Adapted from http://en.wikipedia.org/wiki/Selection_algorithm */
|
||||
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)
|
||||
{
|
||||
const int pivotIndex = left + (right-left)/2;
|
||||
|
||||
int pivotNewIndex = partitionPeerCandidates (candidates, left, right, pivotIndex);
|
||||
|
||||
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);
|
||||
}
|
||||
tr_quickfindFirstK (candidates,
|
||||
candidate_count,
|
||||
sizeof(struct peer_candidate),
|
||||
comparePeerCandidates,
|
||||
select_count);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -4042,7 +4008,7 @@ getPeerCandidates (tr_session * session, int * candidateCount, int max)
|
|||
|
||||
*candidateCount = walk - candidates;
|
||||
if (walk != candidates)
|
||||
selectPeerCandidates (candidates, 0, (walk-candidates)-1, max);
|
||||
selectPeerCandidates (candidates, walk-candidates, max);
|
||||
|
||||
assert (checkBestScoresComeFirst (candidates, *candidateCount, max));
|
||||
|
||||
|
|
|
@ -2713,33 +2713,74 @@ tr_sessionGetQueueStalledMinutes (const tr_session * session)
|
|||
return session->queueStalledMinutes;
|
||||
}
|
||||
|
||||
tr_torrent *
|
||||
tr_sessionGetNextQueuedTorrent (tr_session * session, tr_direction direction)
|
||||
struct TorrentAndPosition
|
||||
{
|
||||
tr_torrent * tor = NULL;
|
||||
tr_torrent * best_tor = NULL;
|
||||
int best_position = INT_MAX;
|
||||
tr_torrent * tor;
|
||||
int position;
|
||||
};
|
||||
|
||||
assert (tr_isSession (session));
|
||||
assert (tr_isDirection (direction));
|
||||
/* higher positions come first */
|
||||
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))
|
||||
continue;
|
||||
if (direction != tr_torrentGetQueueDirection (tor))
|
||||
continue;
|
||||
if (direction != tr_torrentGetQueueDirection (tor))
|
||||
continue;
|
||||
|
||||
position = tr_torrentGetQueuePosition (tor);
|
||||
if (best_position > position) {
|
||||
best_position = position;
|
||||
best_tor = tor;
|
||||
}
|
||||
candidates[i].tor = tor;
|
||||
candidates[i].position = tr_torrentGetQueuePosition (tor);
|
||||
++i;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -329,7 +329,7 @@ bool tr_sessionGetActiveSpeedLimit_Bps (const tr_session * session,
|
|||
unsigned int * setme);
|
||||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue