/* * StatisticsCollector.cc * * Created on: 21.08.2013 * Author: lrade */ #include "ResultCollector.hpp" #include #include #include #include #include #include #include "comm/InjectionPointHopsMessage.pb.h" #include 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& res) { std::vector::iterator it = res.begin(); std::vector::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& 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::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::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'; } }