Commit b94e0ea2 authored by lu43jih's avatar lu43jih
Browse files

fixing correction of values

parent 3be2934d
......@@ -54,11 +54,10 @@ public:
const std::string& getName() const { return _name; }
const std::string& getMqtt() const { return _mqtt; }
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 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(); }
std::size_t popReadingQueue(reading_t *reads, std::size_t max) const { return _readingQueue->pop(reads, max); }
......
......@@ -13,16 +13,13 @@
class PerfSensorBase : virtual public SensorBase {
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) :
SensorBase(name),
_type(0),
_config(0) {}
_config(0),
_lastValid(true){}
virtual ~PerfSensorBase() {}
......@@ -31,26 +28,24 @@ public:
void setType(unsigned type) { _type = type; }
void setConfig(unsigned config) { _config = config; }
void setLastInvalid() { _lastValid = false; }
bool isLastValid() { return _lastValid; }
void storeReading(reading_t reading, unsigned cacheIndex) override {
if(reading.value != INVALIDMEASUREMENT){ //store reading normally...
void storeReading(reading_t reading, unsigned cacheIndex, uint64_t valueNoCorrection) {
if(_lastValid){ //store reading normally...
_readingQueue->push(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:
unsigned int _type;
unsigned int _config;
bool _lastValid;
};
......
......@@ -31,7 +31,9 @@ PerfSensorGroup::PerfSensorGroup(const std::string& name) :
_sensorGroupLeader(false),
_cpuId(0),
_group_fd(-1),
_bufSize(0) {
_bufSize(0),
_latest_time_enabled (0),
_latest_time_running(0){
_buf = nullptr;
}
......@@ -162,54 +164,53 @@ void PerfSensorGroup::read() {
return;
}
double multiplyingFactor = 1;
double correction = 1;
bool validMeasurement=true;
if(rf->time_running){
multiplyingFactor = static_cast<double>(rf->time_enabled)/rf->time_running;
uint64_t time_enabled=calculateIntervalValue(_latest_time_enabled, rf->time_enabled, ULLONG_MAX );
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 {
LOG(info) << "PerfSensorGroup: Could not be measured. Time running==0";
LOG(info) << "PerfSensorGroup: Group: " << _groupName << " could not be measured. Time running==0";
validMeasurement = false;
}
if(multiplyingFactor > _maxMultiplyingThreshold ){
LOG(info) << "PerfCounterGroup: Could not be measured. Multiplying factor ==" << multiplyingFactor;
if(correction > _maxCorrection || correction < 1 ){
LOG(info) << "PerfCounterGroup: Group: " << _groupName << " could not be measured. Correction factor ==" << correction;
validMeasurement = false;
}
if(!validMeasurement){
reading.value = PerfSensorBase::INVALIDMEASUREMENT;
for (auto s : _sensors) {
s->storeReading(reading, _cacheIndex);
s->setLastInvalid();
}
return;
}
//iterate over all values returned by ::read()
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
for (unsigned j = 0; j < _sensors.size(); j++) {
if (rf->values[i].id == _ids[j]) {
reading_t lV = _sensors[j]->getLatestValue();
if(lV.value == PerfSensorBase::INVALIDMEASUREMENT){ //if lV has invalid flag...
//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);
if(!_sensors[j]->isLastValid()) {
validMeasurement = false;
}
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
LOG(debug) << _groupName << "::" << _sensors[j]->getName() << ": \"" << reading.value << "\"";
#endif
_sensors[j]->storeReading(reading, _cacheIndex);
//store original count (without correction) so we can compute the overflow.
_sensors[j]->storeReading(reading, _cacheIndex, val);
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() {
......@@ -228,4 +229,9 @@ void PerfSensorGroup::readAsync() {
_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:
//the sensorGroupLeader stores attached groups in here
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_ */
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