scheduler: Fix and simplify thread migration logic in low latency mode

This patch remove the old thread migration logic which used few special
cases and (broken) general check that attempted to balance threads.

The new logic is pretty straightforward and seems perform well without
any additional special cases. Current core is compared with the least loaded
one and the thread is migrated if that would result in estimated loads of
both cores (i.e. the current one and the least loaded one) to become closer
to the average load (i.e. average of that two cores).
This commit is contained in:
Pawel Dziepak 2014-04-08 22:26:44 +02:00
parent 1bba129c56
commit 91810926dc
1 changed files with 12 additions and 16 deletions

View File

@ -78,13 +78,7 @@ rebalance(const ThreadData* threadData)
SCHEDULER_ENTER_FUNCTION();
CoreEntry* core = threadData->Core();
int32 coreLoad = core->GetLoad();
int32 threadLoad = threadData->GetLoad() / core->CPUCount();
// If the thread produces more than 50% of the load, leave it here. In
// such situation it is better to move other threads away.
if (threadLoad >= coreLoad / 2)
return core;
ASSERT(core != NULL);
// Get the least loaded core.
ReadSpinLocker coreLocker(gCoreHeapsLock);
@ -94,18 +88,20 @@ rebalance(const ThreadData* threadData)
coreLocker.Unlock();
ASSERT(other != NULL);
if (other == core)
// Check if the least loaded core is significantly less loaded than
// the current one.
int32 coreLoad = core->GetLoad();
int32 otherLoad = other->GetLoad();
if (other == core || otherLoad + kLoadDifference >= coreLoad)
return core;
// If there are idle cores give them some work unless that will cause
// the current core to become idle.
int32 coreNewLoad = coreLoad - threadLoad;
if (other->GetLoad() == 0 && coreNewLoad != 0)
return other;
// Check whether migrating the current thread would result in both core
// loads become closer to the average.
int32 difference = coreLoad - otherLoad - kLoadDifference;
ASSERT(difference > 0);
// Attempt to keep load balanced.
int32 otherNewLoad = other->GetLoad() + threadLoad;
return coreNewLoad - otherNewLoad >= kLoadDifference ? other : core;
int32 threadLoad = threadData->GetLoad() / core->CPUCount();
return difference >= threadLoad ? other : core;
}