From 40b0eea1cda924d3dd95bd512e4b123d80547211 Mon Sep 17 00:00:00 2001 From: Jyothish Thomas Date: Wed, 10 Apr 2024 10:19:51 +0000 Subject: [PATCH] weighed random load balancing --- src/XrdCms/XrdCmsCluster.cc | 48 +++++++++++++++++++++++++++++++------ src/XrdCms/XrdCmsConfig.cc | 4 +++- src/XrdCms/XrdCmsConfig.hh | 1 + 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/XrdCms/XrdCmsCluster.cc b/src/XrdCms/XrdCmsCluster.cc index 011bcde2813..3315db891b8 100644 --- a/src/XrdCms/XrdCmsCluster.cc +++ b/src/XrdCms/XrdCmsCluster.cc @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "XProtocol/YProtocol.hh" @@ -1784,12 +1786,17 @@ XrdCmsNode *XrdCmsCluster::SelbyCost(SMask_t mask, XrdCmsSelector &selR) XrdCmsNode *XrdCmsCluster::SelbyLoad(SMask_t mask, XrdCmsSelector &selR) { XrdCmsNode *np, *sp = 0; - bool Multi = false, reqSS = (selR.needSpace & XrdCmsNode::allowsSS) != 0; + bool Multi=false,reqSS = (selR.needSpace & XrdCmsNode::allowsSS) != 0; -// Scan for a node (preset possible, suspended, overloaded, full, and dead) -// - selR.Reset(); SelTcnt++; - for (int i = 0; i <= STHi; i++) + // Scan for a node (preset possible, suspended, overloaded, full, and dead) + // + selR.Reset(); SelTcnt++; + int selCap = 1; + int randomSel=1; + //default 0 to skip the node in random selection if the below checks fail + int *weighed = new int[STHi] {0}; + + for (int i = 0; i <= STHi; i++) if ((np = NodeTab[i]) && (np->NodeMask & mask)) {if (!(selR.needNet & np->hasNet)) {selR.xNoNet= true; continue;} selR.nPick++; @@ -1800,7 +1807,17 @@ XrdCmsNode *XrdCmsCluster::SelbyLoad(SMask_t mask, XrdCmsSelector &selR) || (reqSS && np->isNoStage))) {selR.xFull = true; continue;} if (!sp) sp = np; - else{if (selR.needSpace) + else{ + if (Config.P_randlb==1){ + //add 1 to the inverse load, this is to allow some selection in case reported loads hit 100 + weighed[i] = selCap + static_cast(101 - np->myLoad + + std::pow(101 - np->myLoad, + std::log(100)-std::log(std::min(std::max(Config.P_fuzz,1),100)))/2); + selCap += static_cast(101 - np->myLoad + + std::pow(101 - np->myLoad, + std::log(100)-std::log(std::min(std::max(Config.P_fuzz,1),100)))/2); + } + else{if (selR.needSpace) {if (abs(sp->myMass - np->myMass) <= Config.P_fuzz) {if (sp->RefW > (np->RefW+Config.DiskLinger)) sp=np;} else if (sp->myMass > np->myMass) sp=np; @@ -1816,12 +1833,29 @@ XrdCmsNode *XrdCmsCluster::SelbyLoad(SMask_t mask, XrdCmsSelector &selR) } Multi = true; } + } } - + if (Config.P_randlb==1){ + // pick a random weighed node + // + std::random_device rand_dev; + std::mt19937 generator(rand_dev()); + std::uniform_int_distribution distr(randomSel,selCap); + randomSel = distr(generator); + for(int i=0;i<=STHi;i++){ + if(randomSel<=weighed[i]){ + sp=NodeTab[i]; + break; + } + } + } + delete [] weighed; // Check for overloaded node and return result // if (!sp) return calcDelay(selR); + if (Config.P_randlb!=1){ RefCount(sp, Multi, selR.needSpace); + } return sp; } diff --git a/src/XrdCms/XrdCmsConfig.cc b/src/XrdCms/XrdCmsConfig.cc index bcf3e465d30..ca47b3ab6a5 100644 --- a/src/XrdCms/XrdCmsConfig.cc +++ b/src/XrdCms/XrdCmsConfig.cc @@ -735,6 +735,7 @@ void XrdCmsConfig::ConfigDefaults(void) P_load = 0; P_mem = 0; P_pag = 0; + P_randlb = 0; // SelbyLoad algoruthm choice AskPerf = 10; // Every 10 pings AskPing = 60; // Every 1 minute PingTick = 0; @@ -2651,7 +2652,8 @@ int XrdCmsConfig::xsched(XrdSysError *eDest, XrdOucStream &CFile) {"refreset", -1, &RefReset}, {"affinity", -2, 0}, {"affpath", -3, 0}, - {"tryhname", 1, &V_hntry} + {"tryhname", 1, &V_hntry}, + {"randlb", 1, &P_randlb} }; int numopts = sizeof(scopts)/sizeof(struct schedopts); diff --git a/src/XrdCms/XrdCmsConfig.hh b/src/XrdCms/XrdCmsConfig.hh index 8f2977029e7..8857aeff0b8 100644 --- a/src/XrdCms/XrdCmsConfig.hh +++ b/src/XrdCms/XrdCmsConfig.hh @@ -107,6 +107,7 @@ int P_io; // % I/O Capacity in load factor int P_load; // % MSC Capacity in load factor int P_mem; // % MEM Capacity in load factor int P_pag; // % PAG Capacity in load factor +int P_randlb; // enable weighed random load balancing char DoMWChk; // When true (default) perform multiple write check char DoHnTry; // When true (default) use hostnames for try redirs