perf: faster tr_sessionCountQueueFreeSlots() (#1785)

The previous code had some redundant calculations, e.g. calling 
tr_torrentGetActivity() a couple of times per torrent, once in 
tr_sessionCountQueueFreeSlots() and once in tr_torrentIsStalled(). 
Only one call is necessary.

tr_sessionCountQueueFreeSlots() used to keep iterating through all 
torrents even if the number of free slots had already been decremented 
to zero, even though further iteration does not change the zero return 
value :) This PR checks the return value while looping to prevent this.
This commit is contained in:
Charles Kerr 2021-09-10 15:15:35 -05:00 committed by GitHub
parent a673c49bd6
commit 40868d1621
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 41 deletions

View File

@ -176,14 +176,11 @@ static void allocateBandwidth(
}
/* traverse & repeat for the subtree */
if (true)
struct tr_bandwidth** children = (struct tr_bandwidth**)tr_ptrArrayBase(&b->children);
struct tr_bandwidth** const end = children + tr_ptrArraySize(&b->children);
for (; children != end; ++children)
{
struct tr_bandwidth** children = (struct tr_bandwidth**)tr_ptrArrayBase(&b->children);
for (int i = 0, n = tr_ptrArraySize(&b->children); i < n; ++i)
{
allocateBandwidth(children[i], priority, dir, period_msec, peer_pool);
}
allocateBandwidth(*children, priority, dir, period_msec, peer_pool);
}
}

View File

@ -3096,8 +3096,6 @@ void tr_sessionGetNextQueuedTorrents(tr_session* session, tr_direction direction
int tr_sessionCountQueueFreeSlots(tr_session* session, tr_direction dir)
{
tr_torrent* tor;
int active_count;
int const max = tr_sessionGetQueueSize(session, dir);
tr_torrent_activity const activity = dir == TR_UP ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
@ -3106,20 +3104,31 @@ int tr_sessionCountQueueFreeSlots(tr_session* session, tr_direction dir)
return INT_MAX;
}
tor = NULL;
active_count = 0;
/* count how many torrents are active */
int active_count = 0;
bool const stalled_enabled = tr_sessionGetQueueStalledEnabled(session);
int const stalled_if_idle_for_n_seconds = tr_sessionGetQueueStalledMinutes(session) * 60;
time_t const now = tr_time();
tr_torrent* tor = NULL;
while ((tor = tr_torrentNext(session, tor)) != NULL)
{
if (!tr_torrentIsStalled(tor) && (tr_torrentGetActivity(tor) == activity))
{
++active_count;
}
}
/* is it the right activity? */
if (activity != tr_torrentGetActivity(tor))
continue;
if (active_count >= max)
{
return 0;
/* is it stalled? */
if (stalled_enabled)
{
int const idle_secs = (int)difftime(now, MAX(tor->startDate, tor->activityDate));
if (idle_secs >= stalled_if_idle_for_n_seconds)
continue;
}
++active_count;
/* if we've reached the limit, no need to keep counting */
if (active_count >= max)
return 0;
}
return max - active_count;

View File

@ -1240,27 +1240,16 @@ tr_torrent_activity tr_torrentGetActivity(tr_torrent const* tor)
return ret;
}
static int torrentGetIdleSecs(tr_torrent const* tor)
static int torrentGetIdleSecs(tr_torrent const* tor, tr_torrent_activity activity)
{
int idle_secs;
tr_torrent_activity const activity = tr_torrentGetActivity(tor);
if ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0)
{
idle_secs = (int)difftime(tr_time(), MAX(tor->startDate, tor->activityDate));
}
else
{
idle_secs = -1;
}
return idle_secs;
return ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0) ?
(int)difftime(tr_time(), MAX(tor->startDate, tor->activityDate)) :
-1;
}
bool tr_torrentIsStalled(tr_torrent const* tor)
static inline bool tr_torrentIsStalled(tr_torrent const* tor, int idle_secs)
{
return tr_sessionGetQueueStalledEnabled(tor->session) &&
torrentGetIdleSecs(tor) > tr_sessionGetQueueStalledMinutes(tor->session) * 60;
return tr_sessionGetQueueStalledEnabled(tor->session) && idle_secs > tr_sessionGetQueueStalledMinutes(tor->session) * 60;
}
static double getVerifyProgress(tr_torrent const* tor)
@ -1316,7 +1305,8 @@ tr_stat const* tr_torrentStat(tr_torrent* tor)
s->activity = tr_torrentGetActivity(tor);
s->error = tor->error;
s->queuePosition = tor->queuePosition;
s->isStalled = tr_torrentIsStalled(tor);
s->idleSecs = torrentGetIdleSecs(tor, s->activity);
s->isStalled = tr_torrentIsStalled(tor, s->idleSecs);
tr_strlcpy(s->errorString, tor->errorString, sizeof(s->errorString));
s->manualAnnounceTime = tr_announcerNextManualAnnounce(tor);
@ -1351,7 +1341,6 @@ tr_stat const* tr_torrentStat(tr_torrent* tor)
s->startDate = tor->startDate;
s->secondsSeeding = tor->secondsSeeding;
s->secondsDownloading = tor->secondsDownloading;
s->idleSecs = torrentGetIdleSecs(tor);
s->corruptEver = tor->corruptCur + tor->corruptPrev;
s->downloadedEver = tor->downloadedCur + tor->downloadedPrev;

View File

@ -425,8 +425,6 @@ time_t tr_torrentGetFileMTime(tr_torrent const* tor, tr_file_index_t i);
uint64_t tr_torrentGetCurrentSizeOnDisk(tr_torrent const* tor);
bool tr_torrentIsStalled(tr_torrent const* tor);
unsigned char const* tr_torrentGetPeerId(tr_torrent* tor);
static inline uint64_t tr_torrentGetLeftUntilDone(tr_torrent const* tor)