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