Currently, iterateAlloc tries one guess on the remaining capacity and falls back to small steps if that guess turns out to be too optimistic. In the typical case, that the allocation is bound by memory that initial guess works quite well; however, in some cases other requirements limit the amount of instances allocatable on a cluster. Instead of immediately giving up in this case, try smaller guess-and-verify steps to avoid having to check for global N+1 redundancy too often.
Signed-off-by: Klaus Aehlig <[email protected]> --- src/Ganeti/HTools/Cluster.hs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Ganeti/HTools/Cluster.hs b/src/Ganeti/HTools/Cluster.hs index adfe87d..98b4731 100644 --- a/src/Ganeti/HTools/Cluster.hs +++ b/src/Ganeti/HTools/Cluster.hs @@ -785,7 +785,7 @@ guessBigstepSize nl inst = -- however, at every node we might lose almost an instance if it just -- doesn't fit by a tiny margin guess = capacity - Container.size nl - in if guess < 10 then 10 else guess + in if guess < 20 then 20 else guess -- | A speed-up version of `iterateAllocSmallStep`. -- @@ -795,11 +795,17 @@ guessBigstepSize nl inst = -- if the result of this is globally N+1 redundant, then everything was OK -- inbetween and we can continue from there. Only if that fails, do a -- step-by-step iterative allocation. -iterateAlloc :: AlgorithmOptions -> AllocMethod -iterateAlloc opts nl il limit newinst allocnodes ixes cstats = +-- In order to further speed up the computation while keeping it robust, we +-- first try (if the first argument is True) a number of steps guessed from +-- the node capacity, then, if that failed, a fixed step size and only as last +-- restort step-by-step iterative allocation. +iterateAlloc' :: Bool -> AlgorithmOptions -> AllocMethod +iterateAlloc' tryHugestep opts nl il limit newinst allocnodes ixes cstats = if not $ algCapacity opts then iterateAllocSmallStep opts nl il limit newinst allocnodes ixes cstats - else let bigstepsize = guessBigstepSize nl newinst + else let bigstepsize = if tryHugestep + then guessBigstepSize nl newinst + else 10 (limit', newlimit) = maybe (Just bigstepsize, Nothing) (Just . min bigstepsize &&& Just . max 0 . flip (-) bigstepsize) @@ -811,10 +817,17 @@ iterateAlloc opts nl il limit newinst allocnodes ixes cstats = Ok res@(_, nl', il', ixes', cstats') | redundant nl' il' -> if newlimit == Just 0 || length ixes' == length ixes then return res - else iterateAlloc opts nl' il' newlimit newinst allocnodes - ixes' cstats' - _ -> iterateAllocSmallStep opts nl il limit newinst allocnodes - ixes cstats + else iterateAlloc' tryHugestep opts nl' il' newlimit newinst + allocnodes ixes' cstats' + _ -> if tryHugestep + then iterateAlloc' False opts nl il limit newinst allocnodes + ixes cstats + else iterateAllocSmallStep opts nl il limit newinst + allocnodes ixes cstats + +-- | A speed-up version of `iterateAllocSmallStep`. +iterateAlloc :: AlgorithmOptions -> AllocMethod +iterateAlloc = iterateAlloc' True -- | Predicate whether shrinking a single resource can lead to a valid -- allocation. -- 2.4.3.573.g4eafbef
