173 lines
4.1 KiB
C++
173 lines
4.1 KiB
C++
/*
|
|
* StatisticsCollector.cc
|
|
*
|
|
* Created on: 21.08.2013
|
|
* Author: lrade
|
|
*/
|
|
|
|
#include "ResultCollector.hpp"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <cmath>
|
|
#include <numeric>
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
|
|
|
#include "comm/InjectionPointHopsMessage.pb.h"
|
|
|
|
#include <proc/readproc.h>
|
|
|
|
using std::hex;
|
|
using std::dec;
|
|
|
|
char separator = ' ';
|
|
|
|
extern std::ofstream g_cp_ofstream;
|
|
|
|
extern fail::Logger LOG;
|
|
|
|
void
|
|
ResultCollector::setProtoOStream(ProtoOStream* protoOStream)
|
|
{
|
|
ps = protoOStream;
|
|
}
|
|
|
|
unsigned int calculate_costs(std::vector<result_tuple >& res)
|
|
{
|
|
std::vector<result_tuple>::iterator it = res.begin();
|
|
std::vector<result_tuple>::iterator it_ahead = res.begin();
|
|
it_ahead++;
|
|
|
|
// Cost COST_CHANGE for first hop
|
|
// Costs of all following hops are calculated only on basis of
|
|
// difference between two consecutive hop_positions
|
|
unsigned int costs = COST_CHANGE;
|
|
|
|
while (it != res.end() && it_ahead != res.end()) {
|
|
if (it->first == it_ahead->first) {
|
|
costs += COST_NO_CHANGE;
|
|
} else {
|
|
costs += COST_CHANGE;
|
|
}
|
|
it_ahead++;
|
|
it++;
|
|
}
|
|
|
|
return costs;
|
|
}
|
|
|
|
void
|
|
ResultCollector::addResult(std::vector<result_tuple >& res, unsigned int costs)
|
|
{
|
|
m_result_size++;
|
|
|
|
// Costs not calculated in hop calculator (e.g. dijkstra)? => Do it here
|
|
if (costs == 0) {
|
|
costs = calculate_costs(res);
|
|
}
|
|
|
|
if (m_output_mode == OUTPUT_COSTS) {
|
|
m_ostream << m_res_count++ << separator << costs << '\n';
|
|
} else if (m_output_mode == OUTPUT_RESULT) {
|
|
if (ps) {
|
|
InjectionPointMessage hc;
|
|
hc.set_costs(costs);
|
|
hc.set_target_trace_position(res.back().second);
|
|
// If checkpoint at beginning of hop-chain, add its id to InjectionPointMessage
|
|
std::vector<result_tuple >::iterator it_hop = res.begin();
|
|
if (it_hop != res.end() && it_hop->first.second == ACCESS_CHECKPOINT) {
|
|
hc.set_checkpoint_id(it_hop->first.first);
|
|
it_hop++;
|
|
}
|
|
|
|
for (; it_hop != res.end();
|
|
it_hop++) {
|
|
InjectionPointMessage_Hops *hop = hc.add_hops();
|
|
hop->set_address(it_hop->first.first);
|
|
|
|
enum InjectionPointMessage_Hops_AccessType at;
|
|
switch (it_hop->first.second) {
|
|
case ACCESS_NONE:
|
|
at = InjectionPointMessage_Hops_AccessType_EXECUTE;
|
|
break;
|
|
case ACCESS_READ:
|
|
at = InjectionPointMessage_Hops_AccessType_READ;
|
|
break;
|
|
case ACCESS_WRITE:
|
|
at = InjectionPointMessage_Hops_AccessType_WRITE;
|
|
break;
|
|
case ACCESS_READORWRITE:
|
|
LOG << "ReadOrWrite memory access event not yet"
|
|
" covered" << std::endl;
|
|
exit(-1);
|
|
break;
|
|
case ACCESS_CHECKPOINT:
|
|
LOG << "Checkpoint not allowed after beginning of hop chain" << std::endl;
|
|
exit(-1);
|
|
}
|
|
hop->set_accesstype(at);
|
|
}
|
|
ps->writeMessage(&hc);
|
|
} else {
|
|
for (std::vector<result_tuple >::iterator it_hop = res.begin();
|
|
it_hop != res.end();
|
|
it_hop++) {
|
|
address_t add = it_hop->first.first;
|
|
mem_access_type_e mem_acc_type = it_hop->first.second;
|
|
std::string prefix = (mem_acc_type == ACCESS_READ)?"R":((mem_acc_type == ACCESS_WRITE)?"W":((mem_acc_type == ACCESS_NONE)?"X":((mem_acc_type == ACCESS_CHECKPOINT)?"C":"")));
|
|
m_ostream << prefix << hex << add << dec << separator;
|
|
}
|
|
|
|
if (res.size() > 0)
|
|
m_ostream << '\n';
|
|
}
|
|
} else if (m_output_mode == OUTPUT_STATISTICS) {
|
|
// Calculate mean
|
|
// http://www.heikohoffmann.de/htmlthesis/node134.html
|
|
// c(t+1) = c(t) + (1/(t+1))*(x - c(t))
|
|
m_it_mean_costs = m_it_mean_costs + (1/(double)m_result_size)*((double)costs-m_it_mean_costs);
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
ResultCollector::addCheckpoint(unsigned int pos)
|
|
{
|
|
g_cp_ofstream << m_checkpoint_count++ << separator << pos << '\n';
|
|
}
|
|
|
|
void
|
|
ResultCollector::startTimer()
|
|
{
|
|
m_timer.startTimer();
|
|
}
|
|
|
|
void
|
|
ResultCollector::stopTimer()
|
|
{
|
|
m_timer.stopTimer();
|
|
}
|
|
|
|
void
|
|
ResultCollector::setMaxMemUsage()
|
|
{
|
|
struct proc_t usage;
|
|
look_up_our_self(&usage);
|
|
m_mem_usage = usage.vsize;
|
|
}
|
|
|
|
void
|
|
ResultCollector::finish()
|
|
{
|
|
// Print results if buffered
|
|
|
|
// Print statistics
|
|
if (m_output_mode == OUTPUT_STATISTICS) {
|
|
|
|
m_ostream << m_result_size << separator << m_timer.getRuntimeAsDouble() << separator
|
|
<< m_mem_usage << separator << m_it_mean_costs << separator << m_checkpoint_count << '\n';
|
|
}
|
|
}
|