Commit b94e0ea2 authored by lu43jih's avatar lu43jih
Browse files

fixing correction of values

parent 3be2934d
...@@ -54,11 +54,10 @@ public: ...@@ -54,11 +54,10 @@ public:
const std::string& getName() const { return _name; } const std::string& getName() const { return _name; }
const std::string& getMqtt() const { return _mqtt; } const std::string& getMqtt() const { return _mqtt; }
const reading_t * const getCache() const { return _cache.get(); } const reading_t * const getCache() const { return _cache.get(); }
const reading_t getLatestValue() const { return _latestValue; } const reading_t getLatestValue() const { return _latestValue; } /*TODO return reference*/
void setName(const std::string& name) { _name = name; } void setName(const std::string& name) { _name = name; }
void setMqtt(const std::string& mqtt) { _mqtt = mqtt; } void setMqtt(const std::string& mqtt) { _mqtt = mqtt; }
void setLatestValue(const reading_t& latestValue) { _latestValue = latestValue; }
const std::size_t getSizeOfReadingQueue() const { return _readingQueue->read_available(); } const std::size_t getSizeOfReadingQueue() const { return _readingQueue->read_available(); }
std::size_t popReadingQueue(reading_t *reads, std::size_t max) const { return _readingQueue->pop(reads, max); } std::size_t popReadingQueue(reading_t *reads, std::size_t max) const { return _readingQueue->pop(reads, max); }
......
...@@ -13,16 +13,13 @@ ...@@ -13,16 +13,13 @@
class PerfSensorBase : virtual public SensorBase { class PerfSensorBase : virtual public SensorBase {
public: public:
static constexpr uint64_t MAXCOUNTERVALUE = 2ULL << 48; //ToDo check if it is not ULLONG_MAX, or make it configurable! static constexpr uint64_t MAXCOUNTERVALUE = ULLONG_MAX; //ToDo check if it is not ULLONG_MAX, or make it configurable!
//ULLONG_MAX will work as flag to an invalid measurement. Since counters are 48 bits, it shouldn't be reachable.
//If perf_event extends the counters to ULLONG_MAX, then we may be ditching a good measurement when exactly this value
//is read... This has a very low probability of happening.
static constexpr uint64_t INVALIDMEASUREMENT = ULLONG_MAX;
PerfSensorBase(const std::string& name) : PerfSensorBase(const std::string& name) :
SensorBase(name), SensorBase(name),
_type(0), _type(0),
_config(0) {} _config(0),
_lastValid(true){}
virtual ~PerfSensorBase() {} virtual ~PerfSensorBase() {}
...@@ -31,26 +28,24 @@ public: ...@@ -31,26 +28,24 @@ public:
void setType(unsigned type) { _type = type; } void setType(unsigned type) { _type = type; }
void setConfig(unsigned config) { _config = config; } void setConfig(unsigned config) { _config = config; }
void setLastInvalid() { _lastValid = false; }
bool isLastValid() { return _lastValid; }
void storeReading(reading_t reading, unsigned cacheIndex) override { void storeReading(reading_t reading, unsigned cacheIndex, uint64_t valueNoCorrection) {
if(reading.value != INVALIDMEASUREMENT){ //store reading normally... if(_lastValid){ //store reading normally...
_readingQueue->push(reading); _readingQueue->push(reading);
_cache[cacheIndex] = reading; _cache[cacheIndex] = reading;
//want to store absolute values here
if (MAXCOUNTERVALUE - _latestValue.value < reading.value) {
_latestValue.value = reading.value - (MAXCOUNTERVALUE - _latestValue.value);
} else {
_latestValue.value += reading.value;
}
_latestValue.timestamp = reading.timestamp;
} else {
_latestValue.value = INVALIDMEASUREMENT; //only store last value as invalid. Next measurement will also not count...
} }
_lastValid = true;
_latestValue.value = valueNoCorrection;
_latestValue.timestamp = reading.timestamp;
} }
protected: protected:
unsigned int _type; unsigned int _type;
unsigned int _config; unsigned int _config;
bool _lastValid;
}; };
......
...@@ -31,7 +31,9 @@ PerfSensorGroup::PerfSensorGroup(const std::string& name) : ...@@ -31,7 +31,9 @@ PerfSensorGroup::PerfSensorGroup(const std::string& name) :
_sensorGroupLeader(false), _sensorGroupLeader(false),
_cpuId(0), _cpuId(0),
_group_fd(-1), _group_fd(-1),
_bufSize(0) { _bufSize(0),
_latest_time_enabled (0),
_latest_time_running(0){
_buf = nullptr; _buf = nullptr;
} }
...@@ -162,54 +164,53 @@ void PerfSensorGroup::read() { ...@@ -162,54 +164,53 @@ void PerfSensorGroup::read() {
return; return;
} }
double multiplyingFactor = 1; double correction = 1;
bool validMeasurement=true; bool validMeasurement=true;
if(rf->time_running){ uint64_t time_enabled=calculateIntervalValue(_latest_time_enabled, rf->time_enabled, ULLONG_MAX );
multiplyingFactor = static_cast<double>(rf->time_enabled)/rf->time_running; uint64_t time_running=calculateIntervalValue(_latest_time_running, rf->time_running, ULLONG_MAX );
if(time_running){
correction = static_cast<double>(time_enabled)/time_running;
} else { } else {
LOG(info) << "PerfSensorGroup: Could not be measured. Time running==0"; LOG(info) << "PerfSensorGroup: Group: " << _groupName << " could not be measured. Time running==0";
validMeasurement = false; validMeasurement = false;
} }
if(multiplyingFactor > _maxMultiplyingThreshold ){ if(correction > _maxCorrection || correction < 1 ){
LOG(info) << "PerfCounterGroup: Could not be measured. Multiplying factor ==" << multiplyingFactor; LOG(info) << "PerfCounterGroup: Group: " << _groupName << " could not be measured. Correction factor ==" << correction;
validMeasurement = false; validMeasurement = false;
} }
if(!validMeasurement){ if(!validMeasurement){
reading.value = PerfSensorBase::INVALIDMEASUREMENT;
for (auto s : _sensors) { for (auto s : _sensors) {
s->storeReading(reading, _cacheIndex); s->setLastInvalid();
} }
return; return;
} }
//iterate over all values returned by ::read() //iterate over all values returned by ::read()
for (unsigned i = 0; i < rf->nr; i++) { for (unsigned i = 0; i < rf->nr; i++) {
uint64_t val = static_cast<uint64_t>(rf->values[i].value * multiplyingFactor); uint64_t val = rf->values[i].value;
//iterate over all counters and find the one with matching id //iterate over all counters and find the one with matching id
for (unsigned j = 0; j < _sensors.size(); j++) { for (unsigned j = 0; j < _sensors.size(); j++) {
if (rf->values[i].id == _ids[j]) { if (rf->values[i].id == _ids[j]) {
reading_t lV = _sensors[j]->getLatestValue(); if(!_sensors[j]->isLastValid()) {
if(lV.value == PerfSensorBase::INVALIDMEASUREMENT){ //if lV has invalid flag... validMeasurement = false;
//only store new lV on all sensors, next measurement can be pushed (hopefully)
reading.value = val;
_sensors[j]->setLatestValue(reading);
continue;
}
if (val >= lV.value) {
reading.value = val - lV.value;
} else {
//the counter overflow since last read
reading.value = val + (PerfSensorBase::MAXCOUNTERVALUE - lV.value);
} }
reading_t lV = _sensors[j]->getLatestValue(); //has no correction (might overflow on no corrected value)
//calculate interval and then apply correction
reading.value = static_cast<uint64_t>(calculateIntervalValue(lV.value, val, PerfSensorBase::MAXCOUNTERVALUE)*correction);
#ifdef DEBUG #ifdef DEBUG
LOG(debug) << _groupName << "::" << _sensors[j]->getName() << ": \"" << reading.value << "\""; LOG(debug) << _groupName << "::" << _sensors[j]->getName() << ": \"" << reading.value << "\"";
#endif #endif
_sensors[j]->storeReading(reading, _cacheIndex); //store original count (without correction) so we can compute the overflow.
_sensors[j]->storeReading(reading, _cacheIndex, val);
break; break;
} }
} }
} }
_cacheIndex = (_cacheIndex + 1) % _cacheSize; //ToDo check with Micha if we need to do anything special with an invalid measurement if(validMeasurement){
_cacheIndex = (_cacheIndex + 1) % _cacheSize; //ToDo check
}
} }
void PerfSensorGroup::readAsync() { void PerfSensorGroup::readAsync() {
...@@ -228,4 +229,9 @@ void PerfSensorGroup::readAsync() { ...@@ -228,4 +229,9 @@ void PerfSensorGroup::readAsync() {
_pendingTasks--; _pendingTasks--;
} }
uint64_t calculateIntervalValue(uint64_t previous, uint64_t current, uint64_t maxValue){
if(previous > current) { //overflow
return current + (maxValue - previous);
}
return current - previous;
}
...@@ -45,7 +45,12 @@ private: ...@@ -45,7 +45,12 @@ private:
//the sensorGroupLeader stores attached groups in here //the sensorGroupLeader stores attached groups in here
std::vector<PerfSensorGroup*> _fellowSensorGroups; std::vector<PerfSensorGroup*> _fellowSensorGroups;
static constexpr double _maxMultiplyingThreshold = 40; static constexpr double _maxCorrection = 20; //ToDo make this configurable
uint64_t _latest_time_enabled;
uint64_t _latest_time_running;
}; };
uint64_t calculateIntervalValue(uint64_t previous, uint64_t current, uint64_t maxValue);
#endif /* PERFSENSORGROUP_H_ */ #endif /* PERFSENSORGROUP_H_ */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment