Commit 605cdbd0 authored by lu43jih's avatar lu43jih
Browse files

Adding invalid measurement to perf plugin

parent bcddcc15
......@@ -58,6 +58,7 @@ public:
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); }
......@@ -82,6 +83,8 @@ public:
_latestValue.timestamp = reading.timestamp;
}
protected:
std::string _name;
......
......@@ -13,6 +13,12 @@
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!
//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),
......@@ -27,20 +33,25 @@ public:
void setConfig(unsigned config) { _config = config; }
void storeReading(reading_t reading, unsigned cacheIndex) override {
_readingQueue->push(reading);
_cache[cacheIndex] = reading;
//want to store absolute values here
if (ULLONG_MAX - _latestValue.value < reading.value) {
_latestValue.value = reading.value - (ULLONG_MAX - _latestValue.value);
if(reading.value != INVALIDMEASUREMENT){ //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 += reading.value;
_latestValue.value = INVALIDMEASUREMENT; //only store last value as invalid. Next measurement will also not count...
}
_latestValue.timestamp = reading.timestamp;
}
protected:
unsigned int _type;
unsigned int _config;
};
#endif /* PERFEVENT_PERFSENSORBASE_H_ */
......@@ -18,6 +18,8 @@
//the read group data will have this format
struct read_format {
uint64_t nr;
uint64_t time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
uint64_t time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
struct {
uint64_t value;
uint64_t id;
......@@ -80,7 +82,7 @@ void PerfSensorGroup::start() {
pe.disabled = 1;
pe.exclude_kernel = 0;
pe.exclude_hv = 1;
pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID | PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
//perf_event_open() group leader
_group_fd = syscall(__NR_perf_event_open, &pe, -1, _cpuId, -1, 0);
......@@ -147,20 +149,44 @@ void PerfSensorGroup::read() {
return;
}
double multiplyingFactor = 1;
bool validMeasurement=true;
if(rf->time_running){
multiplyingFactor = static_cast<double>(rf->time_enabled)/rf->time_running;
} else {
LOG(info) << "PerfSensorGroup: Could not be measured. Time running==0";
validMeasurement = false;
}
if(multiplyingFactor > _maxMultiplyingThreshold ){
LOG(info) << "PerfCounterGroup: Could not be measured. Multiplying factor ==" << multiplyingFactor;
validMeasurement = false;
}
if(!validMeasurement){
reading.value = PerfSensorBase::INVALIDMEASUREMENT;
for (auto s : _sensors) {
s->storeReading(reading, _cacheIndex);
}
return;
}
//iterate over all values returned by ::read()
for (unsigned i = 0; i < rf->nr; i++) {
uint64_t val = rf->values[i].value;
uint64_t val = static_cast<uint64_t>(rf->values[i].value * multiplyingFactor);
//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
//according to perf_event_open() man-page u64 (=64bit) is used for event values
//--> unsigned long long is usually also 64bit
reading.value = val + (ULLONG_MAX - lV.value);
reading.value = val + (PerfSensorBase::MAXCOUNTERVALUE - lV.value);
}
#ifdef DEBUG
LOG(debug) << _groupName << "::" << _sensors[j]->getName() << ": \"" << reading.value << "\"";
......@@ -170,7 +196,7 @@ void PerfSensorGroup::read() {
}
}
}
_cacheIndex = (_cacheIndex + 1) % _cacheSize;
_cacheIndex = (_cacheIndex + 1) % _cacheSize; //ToDo check with Micha if we need to do anything special with an invalid measurement
}
void PerfSensorGroup::readAsync() {
......@@ -188,3 +214,5 @@ void PerfSensorGroup::readAsync() {
}
_pendingTasks--;
}
......@@ -44,6 +44,8 @@ private:
//the sensorGroupLeader stores attached groups in here
std::vector<PerfSensorGroup*> _fellowSensorGroups;
static constexpr double _maxMultiplyingThreshold = 40;
};
#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