OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "testing/perf/scoped_histogram_result_printer.h" |
| 6 |
| 7 #include <cmath> |
| 8 #include <memory> |
| 9 |
| 10 #include "base/memory/ptr_util.h" |
| 11 #include "base/metrics/histogram_samples.h" |
| 12 #include "base/metrics/statistics_recorder.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "testing/perf/perf_test.h" |
| 15 |
| 16 namespace { |
| 17 |
| 18 class TestBasedPrinter { |
| 19 public: |
| 20 TestBasedPrinter(const ::testing::UnitTest* test, std::string units) |
| 21 : units_(std::move(units)) { |
| 22 DCHECK(test); |
| 23 test_info_ = test->current_test_info(); |
| 24 DCHECK(test_info_); |
| 25 } |
| 26 |
| 27 void PrintHistogram(const base::HistogramSamples& samples, |
| 28 const std::string& measurement) { |
| 29 std::int64_t total_sum = samples.sum(); |
| 30 base::HistogramBase::Count total_count = |
| 31 static_cast<double>(samples.redundant_count()); |
| 32 double mean = static_cast<double>(total_sum) / total_count; |
| 33 |
| 34 double standard_deviation = 0; |
| 35 for (auto sample_iter = samples.Iterator(); !sample_iter->Done(); |
| 36 sample_iter->Next()) { |
| 37 base::HistogramBase::Sample min, max; |
| 38 base::HistogramBase::Count count; |
| 39 sample_iter->Get(&min, &max, &count); |
| 40 |
| 41 double bucket_mean = (static_cast<double>(min) + max) / 2; |
| 42 |
| 43 standard_deviation += |
| 44 (bucket_mean - mean) * (bucket_mean - mean) * |
| 45 (static_cast<double>(count) / // we do division on every iteration |
| 46 total_count); // to get better precision |
| 47 } |
| 48 standard_deviation = std::sqrt(standard_deviation); |
| 49 |
| 50 perf_test::PrintResultMeanAndError( |
| 51 test_info_->test_case_name(), test_info_->name(), measurement, |
| 52 std::to_string(mean) + ", " + std::to_string(standard_deviation), |
| 53 units_, true); |
| 54 } |
| 55 |
| 56 private: |
| 57 const ::testing::TestInfo* test_info_ = nullptr; |
| 58 std::string units_; |
| 59 }; |
| 60 |
| 61 } // namespace |
| 62 |
| 63 namespace perf_test { |
| 64 |
| 65 HistogramPrinter TestBasedPerfTestPrinter(const ::testing::UnitTest* test, |
| 66 std::string units) { |
| 67 auto printer = base::WrapUnique(new TestBasedPrinter(test, std::move(units))); |
| 68 return base::Bind(&TestBasedPrinter::PrintHistogram, |
| 69 base::Owned(printer.release())); |
| 70 } |
| 71 |
| 72 // ScopedHistogramResultPrinter::HistogramInfo--------------------------------- |
| 73 |
| 74 class ScopedHistogramResultPrinter::HistogramInfo { |
| 75 public: |
| 76 HistogramInfo(std::string name, |
| 77 std::string measurement, |
| 78 bool is_nice, |
| 79 std::unique_ptr<base::HistogramSamples> before_samples) |
| 80 : name_(std::move(name)), |
| 81 measurement_(std::move(measurement)), |
| 82 is_nice_(is_nice), |
| 83 before_samples_(std::move(before_samples)) {} |
| 84 |
| 85 const std::string& name() const { return name_; } |
| 86 const std::string& measurement() const { return measurement_; } |
| 87 bool is_nice() const { return is_nice_; } |
| 88 const base::HistogramSamples* before_samples() const { |
| 89 return before_samples_.get(); |
| 90 } |
| 91 |
| 92 private: |
| 93 std::string name_; |
| 94 std::string measurement_; |
| 95 bool is_nice_; |
| 96 std::unique_ptr<base::HistogramSamples> before_samples_; |
| 97 }; |
| 98 |
| 99 // ScopedHistogramResultPrinter------------------------------------------------ |
| 100 |
| 101 ScopedHistogramResultPrinter::ScopedHistogramResultPrinter( |
| 102 HistogramPrinter printer) |
| 103 : printer_(printer) {} |
| 104 |
| 105 void ScopedHistogramResultPrinter::AddHistogramStrict(std::string name, |
| 106 std::string measurement) { |
| 107 const bool is_nice = false; |
| 108 AddHistogram(std::move(name), std::move(measurement), is_nice); |
| 109 } |
| 110 |
| 111 void ScopedHistogramResultPrinter::AddHistogramNice(std::string name, |
| 112 std::string measurement) { |
| 113 const bool is_nice = true; |
| 114 AddHistogram(std::move(name), std::move(measurement), is_nice); |
| 115 } |
| 116 |
| 117 void ScopedHistogramResultPrinter::AddHistogram(std::string name, |
| 118 std::string measurement, |
| 119 const bool is_nice) { |
| 120 std::unique_ptr<base::HistogramSamples> samples_before; |
| 121 |
| 122 base::HistogramBase* histogram = |
| 123 base::StatisticsRecorder::FindHistogram(name); |
| 124 |
| 125 if (histogram) |
| 126 samples_before = histogram->SnapshotSamples(); |
| 127 |
| 128 histograms_.emplace_back(std::move(name), std::move(measurement), is_nice, |
| 129 std::move(samples_before)); |
| 130 } |
| 131 |
| 132 ScopedHistogramResultPrinter::~ScopedHistogramResultPrinter() { |
| 133 for (const HistogramInfo& histogram_info : histograms_) { |
| 134 base::HistogramBase* histogram = |
| 135 base::StatisticsRecorder::FindHistogram(histogram_info.name()); |
| 136 |
| 137 if (histogram) { |
| 138 std::unique_ptr<base::HistogramSamples> samples_after( |
| 139 histogram->SnapshotSamples()); |
| 140 DCHECK(samples_after); |
| 141 |
| 142 if (histogram_info.before_samples()) |
| 143 samples_after->Subtract(*histogram_info.before_samples()); |
| 144 |
| 145 if (samples_after->redundant_count()) |
| 146 printer_.Run(*samples_after, histogram_info.measurement()); |
| 147 else |
| 148 EXPECT_TRUE(histogram_info.is_nice()) << "Nothing was added in " |
| 149 << histogram_info.name(); |
| 150 } else { |
| 151 EXPECT_TRUE(histogram_info.is_nice()) |
| 152 << "Expected histogram " << histogram_info.name() << " wasn't found"; |
| 153 } |
| 154 } |
| 155 } |
| 156 |
| 157 } // namespace perf_test |
OLD | NEW |