diff --git a/src/agent/Core/ApplicationPool/Group.h b/src/agent/Core/ApplicationPool/Group.h index fba45f8091..9f7362a1d4 100644 --- a/src/agent/Core/ApplicationPool/Group.h +++ b/src/agent/Core/ApplicationPool/Group.h @@ -223,9 +223,9 @@ class Group: public boost::enable_shared_from_this { /****** Process list management ******/ Process *findProcessWithStickySessionId(unsigned int id) const; - Process *findProcessWithStickySessionIdOrLowestBusyness(unsigned int id) const; - Process *findProcessWithLowestBusyness(const ProcessList &processes) const; - Process *findEnabledProcessWithLowestBusyness() const; + Process *findBestProcessPreferringStickySessionId(unsigned int id) const; + Process *findBestProcess(const ProcessList &processes) const; + Process *findBestEnabledProcess() const; void addProcessToList(const ProcessPtr &process, ProcessList &destination); void removeProcessFromList(const ProcessPtr &process, ProcessList &source); diff --git a/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp b/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp index 72124c7530..0c0544d52f 100644 --- a/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +++ b/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp @@ -58,81 +58,81 @@ Group::findProcessWithStickySessionId(unsigned int id) const { } Process * -Group::findProcessWithStickySessionIdOrLowestBusyness(unsigned int id) const { - int leastBusyProcessIndex = -1; - int lowestBusyness = 0; - unsigned int i, size = enabledProcessBusynessLevels.size(), highestGeneration = 0; - const int *enabledProcessBusynessLevels = &this->enabledProcessBusynessLevels[0]; - - for (i = 0; i < size; i++) { - Process *process = enabledProcesses[i].get(); +Group::findBestProcessPreferringStickySessionId(unsigned int id) const { + Process *bestProcess = nullptr; + ProcessList::const_iterator it; + ProcessList::const_iterator end = enabledProcesses.end(); + for (it = enabledProcesses.begin(); it != end; it++) { + Process *process = (*it).get(); if (process->getStickySessionId() == id) { return process; - } else if (leastBusyProcessIndex == -1 || - enabledProcessBusynessLevels[i] < lowestBusyness || - (enabledProcessBusynessLevels[i] == lowestBusyness && process->generation > highestGeneration)) { - highestGeneration = std::max(highestGeneration, process->generation); - leastBusyProcessIndex = i; - lowestBusyness = enabledProcessBusynessLevels[i]; + } else if (bestProcess == nullptr || + process->generation > bestProcess->generation || + (process->generation == bestProcess->generation && process->spawnerCreationTime < bestProcess->spawnerCreationTime) || + (process->generation == bestProcess->generation && process->spawnerCreationTime == bestProcess->spawnerCreationTime && process->busyness() < bestProcess->busyness()) + ) { + bestProcess = process; } } - - if (leastBusyProcessIndex == -1) { - return NULL; - } else { - return enabledProcesses[leastBusyProcessIndex].get(); - } + return bestProcess; } Process * -Group::findProcessWithLowestBusyness(const ProcessList &processes) const { +Group::findBestProcess(const ProcessList &processes) const { if (processes.empty()) { - return NULL; + return nullptr; } - int lowestBusyness = -1; - unsigned int highestGeneration = 0; - Process *leastBusyProcess = NULL; + Process *bestProcess = nullptr; ProcessList::const_iterator it; ProcessList::const_iterator end = processes.end(); for (it = processes.begin(); it != end; it++) { Process *process = (*it).get(); - int busyness = process->busyness(); - if (lowestBusyness == -1 || - lowestBusyness > busyness || - (busyness == lowestBusyness && process->generation > highestGeneration)) { - highestGeneration = std::max(highestGeneration, process->generation); - lowestBusyness = busyness; - leastBusyProcess = process; + + if (bestProcess == nullptr || + process->generation > bestProcess->generation || + (process->generation == bestProcess->generation && process->spawnerCreationTime < bestProcess->spawnerCreationTime) || + (process->generation == bestProcess->generation && process->spawnerCreationTime == bestProcess->spawnerCreationTime && process->busyness() < bestProcess->busyness()) + ) { + bestProcess = process; } } - return leastBusyProcess; + return bestProcess; } /** - * Cache-optimized version of findProcessWithLowestBusyness() for the common case. + * Cache-optimized version of findBestProcess() for the common case. */ Process * -Group::findEnabledProcessWithLowestBusyness() const { +Group::findBestEnabledProcess() const { if (enabledProcesses.empty()) { - return NULL; + return nullptr; } - int leastBusyProcessIndex = -1; - int lowestBusyness = 0; - unsigned int i, size = enabledProcessBusynessLevels.size(), highestGeneration = 0; + Process* bestProcess = nullptr; + unsigned long long bestProcessStartTime = 0; + unsigned int bestProcessGen = 0; + int bestProcessBusyness = 0; + unsigned int size = enabledProcessBusynessLevels.size(); const int *enabledProcessBusynessLevels = &this->enabledProcessBusynessLevels[0]; - for (i = 0; i < size; i++) { - if (leastBusyProcessIndex == -1 || - enabledProcessBusynessLevels[i] < lowestBusyness || - (enabledProcessBusynessLevels[i] == lowestBusyness && enabledProcesses[i]->generation > highestGeneration)) { - highestGeneration = std::max(highestGeneration, enabledProcesses[i]->generation); - leastBusyProcessIndex = i; - lowestBusyness = enabledProcessBusynessLevels[i]; + for (unsigned int i = 0; i < size; i++) { + Process *process = enabledProcesses.at(i).get(); + unsigned int gen = process->generation; + unsigned long long startTime = process->spawnerCreationTime; + int busyness = enabledProcessBusynessLevels[i]; + if (bestProcess == nullptr || + gen > bestProcess->generation || + (gen == bestProcessGen && startTime < bestProcessStartTime) || + (gen == bestProcessGen && startTime == bestProcessStartTime && busyness < bestProcessBusyness) + ) { + bestProcess = process; + bestProcessGen = gen; + bestProcessBusyness = busyness; + bestProcessStartTime = startTime; } } - return enabledProcesses[leastBusyProcessIndex].get(); + return bestProcess; } /** diff --git a/src/agent/Core/ApplicationPool/Group/SessionManagement.cpp b/src/agent/Core/ApplicationPool/Group/SessionManagement.cpp index a9e9510077..be17dca6c3 100644 --- a/src/agent/Core/ApplicationPool/Group/SessionManagement.cpp +++ b/src/agent/Core/ApplicationPool/Group/SessionManagement.cpp @@ -58,14 +58,14 @@ Group::RouteResult Group::route(const Options &options) const { if (OXT_LIKELY(enabledCount > 0)) { if (options.stickySessionId == 0) { - Process *process = findEnabledProcessWithLowestBusyness(); + Process *process = findBestEnabledProcess(); if (process->canBeRoutedTo()) { return RouteResult(process); } else { return RouteResult(NULL, true); } } else { - Process *process = findProcessWithStickySessionIdOrLowestBusyness( + Process *process = findBestProcessPreferringStickySessionId( options.stickySessionId); if (process != NULL) { if (process->canBeRoutedTo()) { @@ -78,7 +78,7 @@ Group::route(const Options &options) const { } } } else { - Process *process = findProcessWithLowestBusyness(disablingProcesses); + Process *process = findBestProcess(disablingProcesses); if (process->canBeRoutedTo()) { return RouteResult(process); } else { @@ -304,7 +304,7 @@ Group::get(const Options &newOptions, const GetCallback &callback, assert(m_spawning || restarting() || poolAtFullCapacity()); if (disablingCount > 0 && !restarting()) { - Process *process = findProcessWithLowestBusyness(disablingProcesses); + Process *process = findBestProcess(disablingProcesses); assert(process != NULL); if (!process->isTotallyBusy()) { return newSession(process, newOptions.currentTime); diff --git a/src/agent/Core/ApplicationPool/Process.h b/src/agent/Core/ApplicationPool/Process.h index c5ad2700ae..611a384fd5 100644 --- a/src/agent/Core/ApplicationPool/Process.h +++ b/src/agent/Core/ApplicationPool/Process.h @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -102,6 +101,12 @@ class Process { public: static const unsigned int MAX_SOCKETS_ACCEPTING_HTTP_REQUESTS = 3; + /** + * Time at which the Spawner that created this process was created. + * Microseconds resolution. + */ + unsigned long long spawnerCreationTime; + private: /************************************************************* * Read-only fields, set once during initialization and never @@ -141,12 +146,6 @@ class Process { */ StaticString codeRevision; - /** - * Time at which the Spawner that created this process was created. - * Microseconds resolution. - */ - unsigned long long spawnerCreationTime; - /** Time at which we started spawning this process. Microseconds resolution. */ unsigned long long spawnStartTime; @@ -451,9 +450,9 @@ class Process { ProcessMetrics metrics; Process(const BasicGroupInfo *groupInfo, const unsigned int gen, const Json::Value &args) - : info(this, groupInfo, args), + : spawnerCreationTime(getJsonUint64Field(args, "spawner_creation_time")), + info(this, groupInfo, args), socketsAcceptingHttpRequestsCount(0), - spawnerCreationTime(getJsonUint64Field(args, "spawner_creation_time")), spawnStartTime(getJsonUint64Field(args, "spawn_start_time")), spawnEndTime(SystemTime::getUsec()), type(args["type"] == "dummy" ? SpawningKit::Result::DUMMY : SpawningKit::Result::UNKNOWN), @@ -477,9 +476,9 @@ class Process { Process(const BasicGroupInfo *groupInfo, const unsigned int gen, const SpawningKit::Result &skResult, const Json::Value &args) - : info(this, groupInfo, skResult), + : spawnerCreationTime(getJsonUint64Field(args, "spawner_creation_time")), + info(this, groupInfo, skResult), socketsAcceptingHttpRequestsCount(0), - spawnerCreationTime(getJsonUint64Field(args, "spawner_creation_time")), spawnStartTime(skResult.spawnStartTime), spawnEndTime(skResult.spawnEndTime), type(skResult.type),