diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/libwebrtc/test/testsupport/perf_test_histogram_writer.cc | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/testsupport/perf_test_histogram_writer.cc b/third_party/libwebrtc/test/testsupport/perf_test_histogram_writer.cc new file mode 100644 index 0000000000..93924ba16c --- /dev/null +++ b/third_party/libwebrtc/test/testsupport/perf_test_histogram_writer.cc @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/testsupport/perf_test_histogram_writer.h" + +#include <stdlib.h> + +#include <map> +#include <memory> + +#include "absl/strings/string_view.h" +#include "api/numerics/samples_stats_counter.h" +#include "rtc_base/logging.h" +#include "rtc_base/strings/string_builder.h" +#include "rtc_base/synchronization/mutex.h" +#include "third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.h" +#include "third_party/catapult/tracing/tracing/value/histogram.h" + +namespace webrtc { +namespace test { + +namespace { + +namespace proto = catapult::tracing::tracing::proto; + +std::string AsJsonString(const std::string string) { + return "\"" + string + "\""; +} + +class PerfTestHistogramWriter : public PerfTestResultWriter { + public: + PerfTestHistogramWriter() : mutex_() {} + void ClearResults() override { + MutexLock lock(&mutex_); + histograms_.clear(); + } + + void LogResult(absl::string_view graph_name, + absl::string_view trace_name, + const double value, + absl::string_view units, + const bool important, + ImproveDirection improve_direction) override { + (void)important; + AddSample(graph_name, trace_name, value, units, improve_direction); + } + void LogResultMeanAndError(absl::string_view graph_name, + absl::string_view trace_name, + const double mean, + const double error, + absl::string_view units, + const bool important, + ImproveDirection improve_direction) override { + RTC_LOG(LS_WARNING) << "Discarding stddev, not supported by histograms"; + (void)error; + (void)important; + + AddSample(graph_name, trace_name, mean, units, improve_direction); + } + void LogResultList(absl::string_view graph_name, + absl::string_view trace_name, + const rtc::ArrayView<const double> values, + absl::string_view units, + const bool important, + ImproveDirection improve_direction) override { + (void)important; + for (double value : values) { + AddSample(graph_name, trace_name, value, units, improve_direction); + } + } + std::string Serialize() const override { + proto::HistogramSet histogram_set; + + MutexLock lock(&mutex_); + for (const auto& histogram : histograms_) { + std::unique_ptr<proto::Histogram> proto = histogram.second->toProto(); + histogram_set.mutable_histograms()->AddAllocated(proto.release()); + } + + std::string output; + bool ok = histogram_set.SerializeToString(&output); + RTC_DCHECK(ok) << "Failed to serialize histogram set to string"; + return output; + } + + private: + void AddSample(absl::string_view original_graph_name, + absl::string_view trace_name, + const double value, + absl::string_view units, + ImproveDirection improve_direction) { + // WebRTC annotates the units into the metric name when they are not + // supported by the Histogram API. + std::string graph_name(original_graph_name); + if (units == "dB") { + graph_name += "_dB"; + } else if (units == "fps") { + graph_name += "_fps"; + } else if (units == "%") { + graph_name += "_%"; + } + + // Lookup on graph name + trace name (or measurement + story in catapult + // parlance). There should be several histograms with the same measurement + // if they're for different stories. + rtc::StringBuilder measurement_and_story; + measurement_and_story << graph_name << trace_name; + MutexLock lock(&mutex_); + if (histograms_.count(measurement_and_story.str()) == 0) { + proto::UnitAndDirection unit = ParseUnit(units, improve_direction); + std::unique_ptr<catapult::HistogramBuilder> builder = + std::make_unique<catapult::HistogramBuilder>(graph_name, unit); + + // Set all summary options as false - we don't want to generate + // metric_std, metric_count, and so on for all metrics. + builder->SetSummaryOptions(proto::SummaryOptions()); + histograms_[measurement_and_story.str()] = std::move(builder); + + proto::Diagnostic stories; + proto::GenericSet* generic_set = stories.mutable_generic_set(); + generic_set->add_values(AsJsonString(std::string(trace_name))); + histograms_[measurement_and_story.str()]->AddDiagnostic( + catapult::kStoriesDiagnostic, stories); + } + + if (units == "bps") { + // Bps has been interpreted as bits per second in WebRTC tests. + histograms_[measurement_and_story.str()]->AddSample(value / 8); + } else { + histograms_[measurement_and_story.str()]->AddSample(value); + } + } + + proto::UnitAndDirection ParseUnit(absl::string_view units, + ImproveDirection improve_direction) { + RTC_DCHECK(units.find('_') == std::string::npos) + << "The unit_bigger|smallerIsBetter syntax isn't supported in WebRTC, " + "use the enum instead."; + + proto::UnitAndDirection result; + result.set_improvement_direction(ParseDirection(improve_direction)); + if (units == "bps") { + result.set_unit(proto::BYTES_PER_SECOND); + } else if (units == "dB") { + result.set_unit(proto::UNITLESS); + } else if (units == "fps") { + result.set_unit(proto::HERTZ); + } else if (units == "frames") { + result.set_unit(proto::COUNT); + } else if (units == "ms") { + result.set_unit(proto::MS_BEST_FIT_FORMAT); + } else if (units == "%") { + result.set_unit(proto::UNITLESS); + } else { + proto::Unit unit = catapult::UnitFromJsonUnit(std::string(units)); + + // UnitFromJsonUnit returns UNITLESS if it doesn't recognize the unit. + if (unit == proto::UNITLESS && units != "unitless") { + RTC_LOG(LS_WARNING) << "Unit " << units << " is unsupported."; + } + + result.set_unit(unit); + } + return result; + } + + proto::ImprovementDirection ParseDirection( + ImproveDirection improve_direction) { + switch (improve_direction) { + case ImproveDirection::kNone: + return proto::NOT_SPECIFIED; + case ImproveDirection::kSmallerIsBetter: + return proto::SMALLER_IS_BETTER; + case ImproveDirection::kBiggerIsBetter: + return proto::BIGGER_IS_BETTER; + default: + RTC_DCHECK_NOTREACHED() << "Invalid enum value " << improve_direction; + } + } + + private: + mutable Mutex mutex_; + std::map<std::string, std::unique_ptr<catapult::HistogramBuilder>> histograms_ + RTC_GUARDED_BY(&mutex_); +}; + +} // namespace + +PerfTestResultWriter* CreateHistogramWriter() { + return new PerfTestHistogramWriter(); +} + +} // namespace test +} // namespace webrtc |