| Index: testing/perf/scoped_histogram_result_printer.cc
|
| diff --git a/testing/perf/scoped_histogram_result_printer.cc b/testing/perf/scoped_histogram_result_printer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f39d47063f0b8e3f3ff60681866c0af339c41257
|
| --- /dev/null
|
| +++ b/testing/perf/scoped_histogram_result_printer.cc
|
| @@ -0,0 +1,157 @@
|
| +// Copyright (c) 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "testing/perf/scoped_histogram_result_printer.h"
|
| +
|
| +#include <cmath>
|
| +#include <memory>
|
| +
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/metrics/histogram_samples.h"
|
| +#include "base/metrics/statistics_recorder.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "testing/perf/perf_test.h"
|
| +
|
| +namespace {
|
| +
|
| +class TestBasedPrinter {
|
| + public:
|
| + TestBasedPrinter(const ::testing::UnitTest* test, std::string units)
|
| + : units_(std::move(units)) {
|
| + DCHECK(test);
|
| + test_info_ = test->current_test_info();
|
| + DCHECK(test_info_);
|
| + }
|
| +
|
| + void PrintHistogram(const base::HistogramSamples& samples,
|
| + const std::string& measurement) {
|
| + std::int64_t total_sum = samples.sum();
|
| + base::HistogramBase::Count total_count =
|
| + static_cast<double>(samples.redundant_count());
|
| + double mean = static_cast<double>(total_sum) / total_count;
|
| +
|
| + double standard_deviation = 0;
|
| + for (auto sample_iter = samples.Iterator(); !sample_iter->Done();
|
| + sample_iter->Next()) {
|
| + base::HistogramBase::Sample min, max;
|
| + base::HistogramBase::Count count;
|
| + sample_iter->Get(&min, &max, &count);
|
| +
|
| + double bucket_mean = (static_cast<double>(min) + max) / 2;
|
| +
|
| + standard_deviation +=
|
| + (bucket_mean - mean) * (bucket_mean - mean) *
|
| + (static_cast<double>(count) / // we do division on every iteration
|
| + total_count); // to get better precision
|
| + }
|
| + standard_deviation = std::sqrt(standard_deviation);
|
| +
|
| + perf_test::PrintResultMeanAndError(
|
| + test_info_->test_case_name(), test_info_->name(), measurement,
|
| + std::to_string(mean) + ", " + std::to_string(standard_deviation),
|
| + units_, true);
|
| + }
|
| +
|
| + private:
|
| + const ::testing::TestInfo* test_info_ = nullptr;
|
| + std::string units_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +namespace perf_test {
|
| +
|
| +HistogramPrinter TestBasedPerfTestPrinter(const ::testing::UnitTest* test,
|
| + std::string units) {
|
| + auto printer = base::WrapUnique(new TestBasedPrinter(test, std::move(units)));
|
| + return base::Bind(&TestBasedPrinter::PrintHistogram,
|
| + base::Owned(printer.release()));
|
| +}
|
| +
|
| +// ScopedHistogramResultPrinter::HistogramInfo---------------------------------
|
| +
|
| +class ScopedHistogramResultPrinter::HistogramInfo {
|
| + public:
|
| + HistogramInfo(std::string name,
|
| + std::string measurement,
|
| + bool is_nice,
|
| + std::unique_ptr<base::HistogramSamples> before_samples)
|
| + : name_(std::move(name)),
|
| + measurement_(std::move(measurement)),
|
| + is_nice_(is_nice),
|
| + before_samples_(std::move(before_samples)) {}
|
| +
|
| + const std::string& name() const { return name_; }
|
| + const std::string& measurement() const { return measurement_; }
|
| + bool is_nice() const { return is_nice_; }
|
| + const base::HistogramSamples* before_samples() const {
|
| + return before_samples_.get();
|
| + }
|
| +
|
| + private:
|
| + std::string name_;
|
| + std::string measurement_;
|
| + bool is_nice_;
|
| + std::unique_ptr<base::HistogramSamples> before_samples_;
|
| +};
|
| +
|
| +// ScopedHistogramResultPrinter------------------------------------------------
|
| +
|
| +ScopedHistogramResultPrinter::ScopedHistogramResultPrinter(
|
| + HistogramPrinter printer)
|
| + : printer_(printer) {}
|
| +
|
| +void ScopedHistogramResultPrinter::AddHistogramStrict(std::string name,
|
| + std::string measurement) {
|
| + const bool is_nice = false;
|
| + AddHistogram(std::move(name), std::move(measurement), is_nice);
|
| +}
|
| +
|
| +void ScopedHistogramResultPrinter::AddHistogramNice(std::string name,
|
| + std::string measurement) {
|
| + const bool is_nice = true;
|
| + AddHistogram(std::move(name), std::move(measurement), is_nice);
|
| +}
|
| +
|
| +void ScopedHistogramResultPrinter::AddHistogram(std::string name,
|
| + std::string measurement,
|
| + const bool is_nice) {
|
| + std::unique_ptr<base::HistogramSamples> samples_before;
|
| +
|
| + base::HistogramBase* histogram =
|
| + base::StatisticsRecorder::FindHistogram(name);
|
| +
|
| + if (histogram)
|
| + samples_before = histogram->SnapshotSamples();
|
| +
|
| + histograms_.emplace_back(std::move(name), std::move(measurement), is_nice,
|
| + std::move(samples_before));
|
| +}
|
| +
|
| +ScopedHistogramResultPrinter::~ScopedHistogramResultPrinter() {
|
| + for (const HistogramInfo& histogram_info : histograms_) {
|
| + base::HistogramBase* histogram =
|
| + base::StatisticsRecorder::FindHistogram(histogram_info.name());
|
| +
|
| + if (histogram) {
|
| + std::unique_ptr<base::HistogramSamples> samples_after(
|
| + histogram->SnapshotSamples());
|
| + DCHECK(samples_after);
|
| +
|
| + if (histogram_info.before_samples())
|
| + samples_after->Subtract(*histogram_info.before_samples());
|
| +
|
| + if (samples_after->redundant_count())
|
| + printer_.Run(*samples_after, histogram_info.measurement());
|
| + else
|
| + EXPECT_TRUE(histogram_info.is_nice()) << "Nothing was added in "
|
| + << histogram_info.name();
|
| + } else {
|
| + EXPECT_TRUE(histogram_info.is_nice())
|
| + << "Expected histogram " << histogram_info.name() << " wasn't found";
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace perf_test
|
|
|