diff --git a/modula/Components/Include/Logger.h b/modula/Components/Include/Logger.h index 5d4a1d3fc..891fda843 100644 --- a/modula/Components/Include/Logger.h +++ b/modula/Components/Include/Logger.h @@ -84,6 +84,7 @@ enum CommonMessageTypes { YAML_PARSE_ERROR, NOTIFY_RESOURCE_TUNER_INIT_START, NOTIFY_CURRENT_TARGET_NAME, + NOTIFY_RAM_TIER_DETECTED, NOTIFY_PARSING_START, NOTIFY_PARSING_SUCCESS, NOTIFY_PARSING_FAILURE, diff --git a/modula/Components/Logger.cpp b/modula/Components/Logger.cpp index 8be233bcd..5da232b8f 100644 --- a/modula/Components/Logger.cpp +++ b/modula/Components/Logger.cpp @@ -266,6 +266,14 @@ void Logger::typeLog(CommonMessageTypes type, const std::string& funcName, ...) break; + case CommonMessageTypes::NOTIFY_RAM_TIER_DETECTED: + vsnprintf(buffer, sizeof(buffer), + "Detected RAM Tier: [%s]", args); + + Logger::log(LOG_INFO, "URM_SERVER_INIT", funcName, buffer); + + break; + case CommonMessageTypes::PULSE_MONITOR_INIT_FAILED: Logger::log(LOG_ERR, "URM_SERVER_INIT", funcName, "Pulse Monitor Could not be started, " \ diff --git a/modula/CoreModules/AuxRoutines.cpp b/modula/CoreModules/AuxRoutines.cpp index c1a633446..3e868879c 100644 --- a/modula/CoreModules/AuxRoutines.cpp +++ b/modula/CoreModules/AuxRoutines.cpp @@ -271,3 +271,57 @@ std::string AuxRoutines::toLowerCase(const std::string& str) { [](unsigned char c) { return std::tolower(c); }); return result; } + +// Get total system RAM in MB from /proc/meminfo +int64_t AuxRoutines::getTotalSystemRAM() { + std::ifstream meminfo("/proc/meminfo"); + if (!meminfo.is_open()) { + LOGE("URM_AUX_ROUTINE", "Failed to open /proc/meminfo"); + return -1; + } + std::string line; + while (std::getline(meminfo, line)) { + if (line.find("MemTotal:") == 0) { + std::istringstream iss(line); + std::string label; + int64_t value; + std::string unit; + + iss >> label >> value >> unit; + meminfo.close(); + + // Convert KB to MB + return value / 1024; + } + } + + meminfo.close(); + LOGE("URM_AUX_ROUTINE", "MemTotal not found in /proc/meminfo"); + return -1; +} +// Categorize RAM into tiers: low, medium, high, very_high +std::string AuxRoutines::getRAMTier() { + int64_t totalRAM = getTotalSystemRAM(); + + if (totalRAM < 0) { + LOGW("URM_AUX_ROUTINE", "Failed to detect RAM, using default tier"); + return "medium"; + } + + LOGI("URM_AUX_ROUTINE", "Detected Total RAM: " + std::to_string(totalRAM) + " MB"); + + // RAM tier thresholds (in MB) + if (totalRAM < 4096) { + LOGI("URM_AUX_ROUTINE", "RAM Tier: LOW (< 4GB)"); + return "low"; + } else if (totalRAM < 8192) { + LOGI("URM_AUX_ROUTINE", "RAM Tier: MEDIUM (4GB - 8GB)"); + return "medium"; + } else if (totalRAM < 65536) { + LOGI("URM_AUX_ROUTINE", "RAM Tier: HIGH (8GB - 64GB)"); + return "high"; + } else { + LOGI("URM_AUX_ROUTINE", "RAM Tier: VERY_HIGH (> 64GB)"); + return "very_high"; + } +} diff --git a/modula/CoreModules/Include/AuxRoutines.h b/modula/CoreModules/Include/AuxRoutines.h index 066b489d0..4fb054a2f 100644 --- a/modula/CoreModules/Include/AuxRoutines.h +++ b/modula/CoreModules/Include/AuxRoutines.h @@ -43,6 +43,10 @@ class AuxRoutines { static int64_t generateUniqueHandle(); static int64_t getCurrentTimeInMilliseconds(); static std::string toLowerCase(const std::string& str); + + // RAM detection utilities + static int64_t getTotalSystemRAM(); + static std::string getRAMTier(); }; // Following are some client-lib centric utilities diff --git a/modula/CoreModules/Include/RAMConfigGenerator.h b/modula/CoreModules/Include/RAMConfigGenerator.h new file mode 100644 index 000000000..2dea3971c --- /dev/null +++ b/modula/CoreModules/Include/RAMConfigGenerator.h @@ -0,0 +1,58 @@ +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +// SPDX-License-Identifier: BSD-3-Clause-Clear + +#ifndef RAM_CONFIG_GENERATOR_H +#define RAM_CONFIG_GENERATOR_H + +#include +#include +#include + +/** + * @brief RAMConfigGenerator + * @details Generates optimized configuration values based on system RAM tier. + * This class provides RAM-aware configuration values for various + * resource tuner parameters. + */ +class RAMConfigGenerator { +public: + /** + * @brief Get configuration value for a given property based on RAM tier + * @param propertyName The name of the property + * @param ramTier The RAM tier (low, medium, high, very_high) + * @return The optimized value for the property, or empty string if not found + */ + static std::string getConfigValue(const std::string& propertyName, + const std::string& ramTier); + + /** + * @brief Get all RAM-based configurations for a given tier + * @param ramTier The RAM tier (low, medium, high, very_high) + * @return Map of property names to their optimized values + */ + static std::unordered_map + getAllConfigs(const std::string& ramTier); + +private: + // Configuration profiles for different RAM tiers + struct ConfigProfile { + uint32_t maxConcurrentRequests; + uint32_t maxResourcesPerRequest; + uint32_t threadPoolDesiredCapacity; + uint32_t threadPoolMaxScalingCapacity; + uint32_t pulseDuration; + uint32_t garbageCollectionDuration; + uint32_t garbageCollectionBatchSize; + uint32_t rateLimiterDelta; + double penaltyFactor; + double rewardFactor; + }; + + static ConfigProfile getLowRAMProfile(); + static ConfigProfile getMediumRAMProfile(); + static ConfigProfile getHighRAMProfile(); + static ConfigProfile getVeryHighRAMProfile(); + static ConfigProfile getProfileForTier(const std::string& ramTier); +}; + +#endif diff --git a/modula/CoreModules/RAMConfigGenerator.cpp b/modula/CoreModules/RAMConfigGenerator.cpp new file mode 100644 index 000000000..3edb61c01 --- /dev/null +++ b/modula/CoreModules/RAMConfigGenerator.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +// SPDX-License-Identifier: BSD-3-Clause-Clear + +#include "RAMConfigGenerator.h" +#include "Logger.h" + +// Low RAM Profile (< 4GB) +// Conservative settings to minimize memory usage +RAMConfigGenerator::ConfigProfile RAMConfigGenerator::getLowRAMProfile() { + ConfigProfile profile; + profile.maxConcurrentRequests = 30; + profile.maxResourcesPerRequest = 10; + profile.threadPoolDesiredCapacity = 3; + profile.threadPoolMaxScalingCapacity = 6; + profile.pulseDuration = 30000; + profile.garbageCollectionDuration = 1500; + profile.garbageCollectionBatchSize = 10; + profile.rateLimiterDelta = 3; + profile.penaltyFactor = 2.5; + profile.rewardFactor = 0.3; + return profile; +} + +// Medium RAM Profile (4GB - 8GB) +// Balanced settings - similar to current defaults +RAMConfigGenerator::ConfigProfile RAMConfigGenerator::getMediumRAMProfile() { + ConfigProfile profile; + profile.maxConcurrentRequests = 60; + profile.maxResourcesPerRequest = 20; + profile.threadPoolDesiredCapacity = 5; + profile.threadPoolMaxScalingCapacity = 10; + profile.pulseDuration = 23000; + profile.garbageCollectionDuration = 1000; + profile.garbageCollectionBatchSize = 20; + profile.rateLimiterDelta = 5; + profile.penaltyFactor = 2.0; + profile.rewardFactor = 0.4; + return profile; +} + +// High RAM Profile (8GB - 64GB) +// Aggressive settings for better performance +RAMConfigGenerator::ConfigProfile RAMConfigGenerator::getHighRAMProfile() { + ConfigProfile profile; + profile.maxConcurrentRequests = 75; + profile.maxResourcesPerRequest = 30; + profile.threadPoolDesiredCapacity = 8; + profile.threadPoolMaxScalingCapacity = 16; + profile.pulseDuration = 18000; + profile.garbageCollectionDuration = 800; + profile.garbageCollectionBatchSize = 30; + profile.rateLimiterDelta = 7; + profile.penaltyFactor = 1.8; + profile.rewardFactor = 0.5; + return profile; +} + +// Very High RAM Profile (> 64GB) +// Maximum performance settings +RAMConfigGenerator::ConfigProfile RAMConfigGenerator::getVeryHighRAMProfile() { + ConfigProfile profile; + profile.maxConcurrentRequests = 100; + profile.maxResourcesPerRequest = 50; + profile.threadPoolDesiredCapacity = 12; + profile.threadPoolMaxScalingCapacity = 24; + profile.pulseDuration = 15000; + profile.garbageCollectionDuration = 600; + profile.garbageCollectionBatchSize = 40; + profile.rateLimiterDelta = 10; + profile.penaltyFactor = 1.5; + profile.rewardFactor = 0.6; + return profile; +} + +RAMConfigGenerator::ConfigProfile RAMConfigGenerator::getProfileForTier(const std::string& ramTier) { + if (ramTier == "low") { + LOGI("RAM_CONFIG_GEN", "Using LOW RAM configuration profile"); + return getLowRAMProfile(); + } else if (ramTier == "medium") { + LOGI("RAM_CONFIG_GEN", "Using MEDIUM RAM configuration profile"); + return getMediumRAMProfile(); + } else if (ramTier == "high") { + LOGI("RAM_CONFIG_GEN", "Using HIGH RAM configuration profile"); + return getHighRAMProfile(); + } else if (ramTier == "very_high") { + LOGI("RAM_CONFIG_GEN", "Using VERY_HIGH RAM configuration profile"); + return getVeryHighRAMProfile(); + } else { + LOGW("RAM_CONFIG_GEN", "Unknown RAM tier: " + ramTier + ", using MEDIUM profile"); + return getMediumRAMProfile(); + } +} + +std::string RAMConfigGenerator::getConfigValue(const std::string& propertyName, + const std::string& ramTier) { + ConfigProfile profile = getProfileForTier(ramTier); + + if (propertyName == "resource_tuner.maximum.concurrent.requests") { + return std::to_string(profile.maxConcurrentRequests); + } else if (propertyName == "resource_tuner.maximum.resources.per.request") { + return std::to_string(profile.maxResourcesPerRequest); + } else if (propertyName == "resource_tuner.thread_pool.desired_capacity") { + return std::to_string(profile.threadPoolDesiredCapacity); + } else if (propertyName == "resource_tuner.thread_pool.max_scaling_capacity") { + return std::to_string(profile.threadPoolMaxScalingCapacity); + } else if (propertyName == "resource_tuner.pulse.duration") { + return std::to_string(profile.pulseDuration); + } else if (propertyName == "resource_tuner.garbage_collection.duration") { + return std::to_string(profile.garbageCollectionDuration); + } else if (propertyName == "resource_tuner.garbage_collection.batch_size") { + return std::to_string(profile.garbageCollectionBatchSize); + } else if (propertyName == "resource_tuner.rate_limiter.delta") { + return std::to_string(profile.rateLimiterDelta); + } else if (propertyName == "resource_tuner.penalty.factor") { + return std::to_string(profile.penaltyFactor); + } else if (propertyName == "resource_tuner.reward.factor") { + return std::to_string(profile.rewardFactor); + } + + return ""; +} + +std::unordered_map +RAMConfigGenerator::getAllConfigs(const std::string& ramTier) { + std::unordered_map configs; + ConfigProfile profile = getProfileForTier(ramTier); + + configs["resource_tuner.maximum.concurrent.requests"] = + std::to_string(profile.maxConcurrentRequests); + configs["resource_tuner.maximum.resources.per.request"] = + std::to_string(profile.maxResourcesPerRequest); + configs["resource_tuner.thread_pool.desired_capacity"] = + std::to_string(profile.threadPoolDesiredCapacity); + configs["resource_tuner.thread_pool.max_scaling_capacity"] = + std::to_string(profile.threadPoolMaxScalingCapacity); + configs["resource_tuner.pulse.duration"] = + std::to_string(profile.pulseDuration); + configs["resource_tuner.garbage_collection.duration"] = + std::to_string(profile.garbageCollectionDuration); + configs["resource_tuner.garbage_collection.batch_size"] = + std::to_string(profile.garbageCollectionBatchSize); + configs["resource_tuner.rate_limiter.delta"] = + std::to_string(profile.rateLimiterDelta); + configs["resource_tuner.penalty.factor"] = + std::to_string(profile.penaltyFactor); + configs["resource_tuner.reward.factor"] = + std::to_string(profile.rewardFactor); + + return configs; +} diff --git a/resource-tuner/core/Include/PropertiesRegistry.h b/resource-tuner/core/Include/PropertiesRegistry.h index 85b3f5f42..06daa121f 100644 --- a/resource-tuner/core/Include/PropertiesRegistry.h +++ b/resource-tuner/core/Include/PropertiesRegistry.h @@ -64,6 +64,15 @@ class PropertiesRegistry { int32_t getPropertiesCount(); + /** + * @brief Apply RAM-based configuration overrides + * @param ramTier The RAM tier (low, medium, high, very_high) + * @return int8_t: + * - 1: if RAM-based configs were successfully applied + * - 0: otherwise + */ + int8_t applyRAMBasedConfigs(const std::string& ramTier); + static std::shared_ptr getInstance() { if(propRegistryInstance == nullptr) { std::shared_ptr localpropRegistryInstance(new PropertiesRegistry()); diff --git a/resource-tuner/core/PropertiesRegistry.cpp b/resource-tuner/core/PropertiesRegistry.cpp index da1a91051..a121d6cd1 100644 --- a/resource-tuner/core/PropertiesRegistry.cpp +++ b/resource-tuner/core/PropertiesRegistry.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear #include "PropertiesRegistry.h" +#include "RAMConfigGenerator.h" +#include "Logger.h" std::shared_ptr PropertiesRegistry::propRegistryInstance = nullptr; @@ -81,4 +83,41 @@ int32_t PropertiesRegistry::getPropertiesCount() { return this->mProperties.size(); } +int8_t PropertiesRegistry::applyRAMBasedConfigs(const std::string& ramTier) { + LOGI("PROPERTIES_REGISTRY", "Applying RAM-based configurations for tier: " + ramTier); + + // Get all RAM-based configurations + auto ramConfigs = RAMConfigGenerator::getAllConfigs(ramTier); + + int32_t appliedCount = 0; + for (const auto& config : ramConfigs) { + const std::string& propName = config.first; + const std::string& propValue = config.second; + + // Check if property already exists + std::string existingValue; + if (queryProperty(propName, existingValue) > 0) { + // Property exists, modify it + if (modifyProperty(propName, propValue)) { + LOGI("PROPERTIES_REGISTRY", + "Updated property: " + propName + " = " + propValue + + " (was: " + existingValue + ")"); + appliedCount++; + } + } else { + // Property doesn't exist, create it + if (createProperty(propName, propValue)) { + LOGI("PROPERTIES_REGISTRY", + "Created property: " + propName + " = " + propValue); + appliedCount++; + } + } + } + + LOGI("PROPERTIES_REGISTRY", + "Applied " + std::to_string(appliedCount) + " RAM-based configurations"); + + return appliedCount > 0 ? true : false; +} + PropertiesRegistry::~PropertiesRegistry() {} diff --git a/resource-tuner/init/RestuneInit.cpp b/resource-tuner/init/RestuneInit.cpp index 274c0cdc9..967c2ce72 100644 --- a/resource-tuner/init/RestuneInit.cpp +++ b/resource-tuner/init/RestuneInit.cpp @@ -21,6 +21,7 @@ #include "UrmSettings.h" #include "SignalRegistry.h" #include "RestuneParser.h" +#include "RAMConfigGenerator.h" #define MAX_EXTENSION_LIB_HANDLES 6 static void** extensionLibHandles = nullptr; @@ -533,6 +534,14 @@ static ErrCode init(void* arg) { return RC_MODULE_INIT_FAILURE; } + // Detect RAM and apply RAM-based configurations + std::string ramTier = AuxRoutines::getRAMTier(); + TYPELOGV(NOTIFY_RAM_TIER_DETECTED, ramTier.c_str()); + + if(!PropertiesRegistry::getInstance()->applyRAMBasedConfigs(ramTier)) { + LOGW("RESTUNE_SERVER_INIT", "Failed to apply RAM-based configurations, using defaults"); + } + if(RC_IS_NOTOK(fetchMetaConfigs())) { TYPELOGD(META_CONF_FETCH_FAILED); return RC_MODULE_INIT_FAILURE;