Improve cpusensor performance
The cpusensor service is still making some redundant accesses for
reading hwmon attributes on every scanning. Actually, threshold
update is needed only when CPU package's Tcontrol target is
changed so this commit make it do that only when Tcontrol value
is changed.
Tested:
Compare cpu resource consumption of cpusensor service using top.
It should eat less cpu resources than before.
Change-Id: Ieb582996fc5c9c07abbfc7ac0d1b37f593269d00
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
diff --git a/include/CPUSensor.hpp b/include/CPUSensor.hpp
index a38c84e..f66e655 100644
--- a/include/CPUSensor.hpp
+++ b/include/CPUSensor.hpp
@@ -10,20 +10,30 @@
CPUSensor(const std::string& path, const std::string& objectType,
sdbusplus::asio::object_server& objectServer,
std::shared_ptr<sdbusplus::asio::connection>& conn,
- boost::asio::io_service& io, const std::string& fanName,
+ boost::asio::io_service& io, const std::string& sensorName,
std::vector<thresholds::Threshold>&& thresholds,
- const std::string& configuration);
+ const std::string& configuration, int cpuId, bool show);
~CPUSensor();
static constexpr unsigned int sensorScaleFactor = 1000;
static constexpr unsigned int sensorPollMs = 1000;
+ static constexpr size_t warnAfterErrorCount = 10;
+ static constexpr double maxReading = 127;
+ static constexpr double minReading = -128;
+ static constexpr const char* labelTcontrol = "Tcontrol";
private:
sdbusplus::asio::object_server& objServer;
boost::asio::posix::stream_descriptor inputDev;
boost::asio::deadline_timer waitTimer;
boost::asio::streambuf readBuf;
+ std::string nameTcontrol;
+ double privTcontrol;
+ bool show;
int errCount;
void setupRead(void);
void handleResponse(const boost::system::error_code& err);
void checkThresholds(void) override;
};
+
+extern boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>
+ gCpuSensors;
diff --git a/src/CPUSensor.cpp b/src/CPUSensor.cpp
index d8d0ecb..a6dc275 100644
--- a/src/CPUSensor.cpp
+++ b/src/CPUSensor.cpp
@@ -27,39 +27,42 @@
#include <sdbusplus/asio/object_server.hpp>
#include <string>
-static constexpr size_t warnAfterErrorCount = 10;
-static constexpr double maxReading = 127;
-static constexpr double minReading = -128;
-
CPUSensor::CPUSensor(const std::string& path, const std::string& objectType,
sdbusplus::asio::object_server& objectServer,
std::shared_ptr<sdbusplus::asio::connection>& conn,
boost::asio::io_service& io, const std::string& sensorName,
std::vector<thresholds::Threshold>&& _thresholds,
- const std::string& sensorConfiguration) :
+ const std::string& sensorConfiguration, int cpuId,
+ bool show) :
Sensor(boost::replace_all_copy(sensorName, " ", "_"), path,
std::move(_thresholds), sensorConfiguration, objectType, maxReading,
minReading),
objServer(objectServer), inputDev(io, open(path.c_str(), O_RDONLY)),
- waitTimer(io), errCount(0)
-
+ waitTimer(io), show(show),
+ privTcontrol(std::numeric_limits<double>::quiet_NaN()), errCount(0)
{
- sensorInterface = objectServer.add_interface(
- "/xyz/openbmc_project/sensors/temperature/" + name,
- "xyz.openbmc_project.Sensor.Value");
- if (thresholds::hasWarningInterface(thresholds))
+ nameTcontrol = labelTcontrol;
+ nameTcontrol += " CPU" + std::to_string(cpuId);
+
+ if (show)
{
- thresholdInterfaceWarning = objectServer.add_interface(
+ sensorInterface = objectServer.add_interface(
"/xyz/openbmc_project/sensors/temperature/" + name,
- "xyz.openbmc_project.Sensor.Threshold.Warning");
+ "xyz.openbmc_project.Sensor.Value");
+ if (thresholds::hasWarningInterface(thresholds))
+ {
+ thresholdInterfaceWarning = objectServer.add_interface(
+ "/xyz/openbmc_project/sensors/temperature/" + name,
+ "xyz.openbmc_project.Sensor.Threshold.Warning");
+ }
+ if (thresholds::hasCriticalInterface(thresholds))
+ {
+ thresholdInterfaceCritical = objectServer.add_interface(
+ "/xyz/openbmc_project/sensors/temperature/" + name,
+ "xyz.openbmc_project.Sensor.Threshold.Critical");
+ }
+ setInitialProperties(conn);
}
- if (thresholds::hasCriticalInterface(thresholds))
- {
- thresholdInterfaceCritical = objectServer.add_interface(
- "/xyz/openbmc_project/sensors/temperature/" + name,
- "xyz.openbmc_project.Sensor.Threshold.Critical");
- }
- setInitialProperties(conn);
setupPowerMatch(conn);
setupRead();
}
@@ -69,9 +72,12 @@
// close the input dev to cancel async operations
inputDev.close();
waitTimer.cancel();
- objServer.remove_interface(thresholdInterfaceWarning);
- objServer.remove_interface(thresholdInterfaceCritical);
- objServer.remove_interface(sensorInterface);
+ if (show)
+ {
+ objServer.remove_interface(thresholdInterfaceWarning);
+ objServer.remove_interface(thresholdInterfaceCritical);
+ objServer.remove_interface(sensorInterface);
+ }
}
void CPUSensor::setupRead(void)
@@ -96,7 +102,7 @@
try
{
std::getline(responseStream, response);
- float nvalue = std::stof(response);
+ double nvalue = std::stof(response);
responseStream.clear();
nvalue /= CPUSensor::sensorScaleFactor;
if (overridenState)
@@ -105,25 +111,44 @@
}
if (nvalue != value)
{
- updateValue(nvalue);
- }
- if (!thresholds.empty())
- {
- std::vector<thresholds::Threshold> newThresholds;
- if (parseThresholdsFromAttr(newThresholds, path,
- CPUSensor::sensorScaleFactor))
+ if (show)
{
- if (!std::equal(thresholds.begin(), thresholds.end(),
- newThresholds.begin(), newThresholds.end()))
- {
- thresholds = newThresholds;
- thresholds::updateThresholds(this);
- }
+ updateValue(nvalue);
}
else
{
- std::cerr << "Failure to update thresholds for " << name
- << "\n";
+ value = nvalue;
+ }
+ }
+ double gTcontrol = gCpuSensors[nameTcontrol]
+ ? gCpuSensors[nameTcontrol]->value
+ : std::numeric_limits<double>::quiet_NaN();
+ if (gTcontrol != privTcontrol)
+ {
+ privTcontrol = gTcontrol;
+
+ if (!thresholds.empty())
+ {
+ std::vector<thresholds::Threshold> newThresholds;
+ if (parseThresholdsFromAttr(newThresholds, path,
+ CPUSensor::sensorScaleFactor))
+ {
+ if (!std::equal(thresholds.begin(), thresholds.end(),
+ newThresholds.begin(),
+ newThresholds.end()))
+ {
+ thresholds = newThresholds;
+ if (show)
+ {
+ thresholds::updateThresholds(this);
+ }
+ }
+ }
+ else
+ {
+ std::cerr << "Failure to update thresholds for " << name
+ << "\n";
+ }
}
}
errCount = 0;
@@ -150,13 +175,27 @@
std::cerr << "Failure to read sensor " << name << " at " << path
<< "\n";
}
- updateValue(0);
+ if (show)
+ {
+ updateValue(0);
+ }
+ else
+ {
+ value = 0;
+ }
errCount++;
}
else
{
errCount = 0; // check power again in 10 cycles
- updateValue(std::numeric_limits<double>::quiet_NaN());
+ if (show)
+ {
+ updateValue(std::numeric_limits<double>::quiet_NaN());
+ }
+ else
+ {
+ value = std::numeric_limits<double>::quiet_NaN();
+ }
}
}
@@ -180,5 +219,8 @@
void CPUSensor::checkThresholds(void)
{
- thresholds::checkThresholds(this);
+ if (show)
+ {
+ thresholds::checkThresholds(this);
+ }
}
diff --git a/src/CPUSensorMain.cpp b/src/CPUSensorMain.cpp
index 6c4e2e5..858ab24 100644
--- a/src/CPUSensorMain.cpp
+++ b/src/CPUSensorMain.cpp
@@ -41,6 +41,8 @@
static constexpr bool DEBUG = false;
+boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>> gCpuSensors;
+
enum State
{
OFF, // host powered down
@@ -76,26 +78,22 @@
"xyz.openbmc_project.Configuration.";
static constexpr std::array<const char*, 3> sensorTypes = {
"SkylakeCPU", "BroadwellCPU", "HaswellCPU"};
-static constexpr std::array<const char*, 3> skipProps = {"Tcontrol",
- "Tthrottle", "Tjmax"};
+static constexpr std::array<const char*, 3> hiddenProps = {
+ CPUSensor::labelTcontrol, "Tthrottle", "Tjmax"};
void detectCpuAsync(
boost::asio::deadline_timer& pingTimer,
boost::asio::deadline_timer& creationTimer, boost::asio::io_service& io,
sdbusplus::asio::object_server& objectServer,
std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
- boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
- cpuSensors,
boost::container::flat_set<CPUConfig>& cpuConfigs,
ManagedObjectType& sensorConfigs);
-bool createSensors(
- boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
- std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
- boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
- cpuSensors,
- boost::container::flat_set<CPUConfig>& cpuConfigs,
- ManagedObjectType& sensorConfigs)
+bool createSensors(boost::asio::io_service& io,
+ sdbusplus::asio::object_server& objectServer,
+ std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
+ boost::container::flat_set<CPUConfig>& cpuConfigs,
+ ManagedObjectType& sensorConfigs)
{
bool available = false;
for (const CPUConfig& cpu : cpuConfigs)
@@ -269,25 +267,10 @@
std::getline(labelFile, label);
labelFile.close();
- // skip non-sensor properties
- bool skipIt = false;
- for (const char* prop : skipProps)
- {
- if (label == prop)
- {
- skipIt = true;
- break;
- }
- }
- if (skipIt)
- {
- continue;
- }
-
std::string sensorName = label + " CPU" + std::to_string(cpuId);
- auto findSensor = cpuSensors.find(sensorName);
- if (findSensor != cpuSensors.end())
+ auto findSensor = gCpuSensors.find(sensorName);
+ if (findSensor != gCpuSensors.end())
{
if (DEBUG)
{
@@ -297,6 +280,17 @@
continue;
}
+ // check hidden properties
+ bool show = true;
+ for (const char* prop : hiddenProps)
+ {
+ if (label == prop)
+ {
+ show = false;
+ break;
+ }
+ }
+
std::vector<thresholds::Threshold> sensorThresholds;
std::string labelHead = label.substr(0, label.find(" "));
parseThresholdsFromConfig(*sensorData, sensorThresholds,
@@ -310,9 +304,10 @@
<< sensorName << "\n";
}
}
- cpuSensors[sensorName] = std::make_unique<CPUSensor>(
+ gCpuSensors[sensorName] = std::make_unique<CPUSensor>(
inputPathStr, sensorType, objectServer, dbusConnection, io,
- sensorName, std::move(sensorThresholds), *interfacePath);
+ sensorName, std::move(sensorThresholds), *interfacePath, cpuId,
+ show);
createdSensors.insert(sensorName);
if (DEBUG)
{
@@ -375,15 +370,13 @@
std::cout << parameters << " on bus " << busStr << " is exported\n";
}
-void detectCpu(
- boost::asio::deadline_timer& pingTimer,
- boost::asio::deadline_timer& creationTimer, boost::asio::io_service& io,
- sdbusplus::asio::object_server& objectServer,
- std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
- boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
- cpuSensors,
- boost::container::flat_set<CPUConfig>& cpuConfigs,
- ManagedObjectType& sensorConfigs)
+void detectCpu(boost::asio::deadline_timer& pingTimer,
+ boost::asio::deadline_timer& creationTimer,
+ boost::asio::io_service& io,
+ sdbusplus::asio::object_server& objectServer,
+ std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
+ boost::container::flat_set<CPUConfig>& cpuConfigs,
+ ManagedObjectType& sensorConfigs)
{
size_t rescanDelaySeconds = 0;
bool keepPinging = false;
@@ -490,12 +483,11 @@
return; // we're being canceled
}
- if (!createSensors(io, objectServer, dbusConnection, cpuSensors,
- cpuConfigs, sensorConfigs))
+ if (!createSensors(io, objectServer, dbusConnection, cpuConfigs,
+ sensorConfigs))
{
detectCpuAsync(pingTimer, creationTimer, io, objectServer,
- dbusConnection, cpuSensors, cpuConfigs,
- sensorConfigs);
+ dbusConnection, cpuConfigs, sensorConfigs);
}
});
}
@@ -503,7 +495,7 @@
if (keepPinging)
{
detectCpuAsync(pingTimer, creationTimer, io, objectServer,
- dbusConnection, cpuSensors, cpuConfigs, sensorConfigs);
+ dbusConnection, cpuConfigs, sensorConfigs);
}
}
@@ -512,8 +504,6 @@
boost::asio::deadline_timer& creationTimer, boost::asio::io_service& io,
sdbusplus::asio::object_server& objectServer,
std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
- boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
- cpuSensors,
boost::container::flat_set<CPUConfig>& cpuConfigs,
ManagedObjectType& sensorConfigs)
{
@@ -525,7 +515,7 @@
}
detectCpu(pingTimer, creationTimer, io, objectServer, dbusConnection,
- cpuSensors, cpuConfigs, sensorConfigs);
+ cpuConfigs, sensorConfigs);
});
}
@@ -623,8 +613,6 @@
systemBus->request_name("xyz.openbmc_project.CPUSensor");
sdbusplus::asio::object_server objectServer(systemBus);
- boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>
- cpuSensors;
std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
boost::asio::deadline_timer pingTimer(io);
boost::asio::deadline_timer creationTimer(io);
@@ -641,7 +629,7 @@
if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs))
{
detectCpuAsync(pingTimer, creationTimer, io, objectServer,
- systemBus, cpuSensors, cpuConfigs, sensorConfigs);
+ systemBus, cpuConfigs, sensorConfigs);
}
});
@@ -669,8 +657,7 @@
if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs))
{
detectCpuAsync(pingTimer, creationTimer, io, objectServer,
- systemBus, cpuSensors, cpuConfigs,
- sensorConfigs);
+ systemBus, cpuConfigs, sensorConfigs);
}
});
};