/Util/Stats.h
C++ Header | 93 lines | 66 code | 14 blank | 13 comment | 5 complexity | 2cfa3f148290b902666eaf4994d3b4ac MD5 | raw file
1// -*- C++ -*- 2#ifndef UTIL_STATS_H 3#define UTIL_STATS_H 4 5#ifndef __cplusplus 6#error This header expects to be included only in C++ source 7#endif 8 9#include "llvm/Support/MutexGuard.h" 10#include "llvm/Support/raw_ostream.h" 11 12#include <algorithm> 13#include <numeric> 14#include <vector> 15 16// Calculate the median of a given data set. This assumes that the data is 17// sorted. 18template<typename ValueTy> 19ValueTy 20Median(const std::vector<ValueTy> &data) 21{ 22 size_t mid_point = data.size() / 2; 23 if (data.size() % 2 == 0) { 24 ValueTy first = data[mid_point]; 25 ValueTy second = data[mid_point - 1]; 26 return (first + second) / 2; 27 } else { 28 return data[mid_point]; 29 } 30} 31 32 33// Base class useful for collecting stats on vectors of individual data points. 34// This is intended to be used with llvm::ManagedStatic and will print 35// min, median, mean, max and sum statistics about the data vector when the 36// process shuts down. 37template<typename ValueTy> 38class DataVectorStats { 39public: 40 typedef std::vector<ValueTy> DataType; 41 42 // Append a new data point to the vector. This is thread-safe. 43 void RecordDataPoint(ValueTy data_point) { 44 llvm::MutexGuard locked(this->lock_); 45 this->data_.push_back(data_point); 46 } 47 48 DataVectorStats(const char *const name) : name_(name) {} 49 50 ~DataVectorStats() { 51 DataType data = this->data_; 52 if (data.size() == 0) 53 return; 54 ValueTy sum = std::accumulate(data.begin(), data.end(), ValueTy()); 55 std::sort(data.begin(), data.end()); 56 57 llvm::errs() << "\n" << this->name_ << ":\n"; 58 llvm::errs() << "N: " << data.size() << "\n"; 59 llvm::errs() << "Min: " << data[0] << "\n"; 60 llvm::errs() << "Median: " << Median(data) << "\n"; 61 llvm::errs() << "Mean: " << sum / data.size() << "\n"; 62 llvm::errs() << "Max: " << *(data.end() - 1) << "\n"; 63 llvm::errs() << "Sum: " << sum << "\n"; 64 } 65 66private: 67 const char *const name_; 68 llvm::sys::Mutex lock_; 69 DataType data_; 70}; 71 72/// An instance of this class records the time in ns between its 73/// construction and destruction into a DataVectorStats<int64_t>. 74class Timer { 75public: 76 Timer(DataVectorStats<int64_t> &stat) 77 : stat_(stat), start_time_(this->GetTime()) {} 78 ~Timer() { 79 int64_t end_time = this->GetTime(); 80 int64_t elapsed = end_time - this->start_time_; 81 stat_.RecordDataPoint(elapsed); 82 } 83private: 84 // Returns the current time in nanoseconds. It doesn't matter 85 // what these ns count from since we only use them to compute time 86 // changes. 87 static int64_t GetTime(); 88 89 DataVectorStats<int64_t> &stat_; 90 const int64_t start_time_; 91}; 92 93#endif // UTIL_STATS_H