PageRenderTime 24ms CodeModel.GetById 10ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/Util/Stats.h

http://unladen-swallow.googlecode.com/
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