/* * Copyright (c) 2022 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 "api/test/metrics/print_result_proxy_metrics_exporter.h" #include #include #include "api/array_view.h" #include "api/test/metrics/metric.h" #include "test/testsupport/perf_test.h" namespace webrtc { namespace test { namespace { std::string ToPrintResultUnit(Unit unit) { switch (unit) { case Unit::kMilliseconds: return "msBestFitFormat"; case Unit::kPercent: return "n%"; case Unit::kBytes: return "sizeInBytes"; case Unit::kKilobitsPerSecond: // PrintResults prefer Chrome Perf Dashboard units, which doesn't have // kpbs units, so we change the unit and value accordingly. return "bytesPerSecond"; case Unit::kHertz: return "Hz"; case Unit::kUnitless: return "unitless"; case Unit::kCount: return "count"; } } double ToPrintResultValue(double value, Unit unit) { switch (unit) { case Unit::kKilobitsPerSecond: // PrintResults prefer Chrome Perf Dashboard units, which doesn't have // kpbs units, so we change the unit and value accordingly. return value * 1000 / 8; default: return value; } } ImproveDirection ToPrintResultImproveDirection(ImprovementDirection direction) { switch (direction) { case ImprovementDirection::kBiggerIsBetter: return ImproveDirection::kBiggerIsBetter; case ImprovementDirection::kNeitherIsBetter: return ImproveDirection::kNone; case ImprovementDirection::kSmallerIsBetter: return ImproveDirection::kSmallerIsBetter; } } bool IsEmpty(const Metric::Stats& stats) { return !stats.mean.has_value() && !stats.stddev.has_value() && !stats.min.has_value() && !stats.max.has_value(); } bool NameEndsWithConnected(const std::string& name) { static const std::string suffix = "_connected"; return name.size() >= suffix.size() && 0 == name.compare(name.size() - suffix.size(), suffix.size(), suffix); } } // namespace bool PrintResultProxyMetricsExporter::Export( rtc::ArrayView metrics) { static const std::unordered_set per_call_metrics{ "actual_encode_bitrate", "encode_frame_rate", "harmonic_framerate", "max_skipped", "min_psnr_dB", "retransmission_bitrate", "sent_packets_loss", "transmission_bitrate", "dropped_frames", "frames_in_flight", "rendered_frames", "average_receive_rate", "average_send_rate", "bytes_discarded_no_receiver", "bytes_received", "bytes_sent", "packets_discarded_no_receiver", "packets_received", "packets_sent", "payload_bytes_received", "payload_bytes_sent", "cpu_usage"}; for (const Metric& metric : metrics) { if (metric.time_series.samples.empty() && IsEmpty(metric.stats)) { // If there were no data collected for the metric it is expected that 0 // will be exported, so add 0 to the samples. PrintResult(metric.name, /*modifier=*/"", metric.test_case, ToPrintResultValue(0, metric.unit), ToPrintResultUnit(metric.unit), /*important=*/false, ToPrintResultImproveDirection(metric.improvement_direction)); continue; } if (metric.time_series.samples.empty()) { PrintResultMeanAndError( metric.name, /*modifier=*/"", metric.test_case, ToPrintResultValue(*metric.stats.mean, metric.unit), ToPrintResultValue(*metric.stats.stddev, metric.unit), ToPrintResultUnit(metric.unit), /*important=*/false, ToPrintResultImproveDirection(metric.improvement_direction)); continue; } if (metric.time_series.samples.size() == 1lu && (per_call_metrics.count(metric.name) > 0 || NameEndsWithConnected(metric.name))) { // Increase backwards compatibility for 1 value use case. PrintResult( metric.name, /*modifier=*/"", metric.test_case, ToPrintResultValue(metric.time_series.samples[0].value, metric.unit), ToPrintResultUnit(metric.unit), /*important=*/false, ToPrintResultImproveDirection(metric.improvement_direction)); continue; } SamplesStatsCounter counter; for (size_t i = 0; i < metric.time_series.samples.size(); ++i) { counter.AddSample(SamplesStatsCounter::StatsSample{ .value = ToPrintResultValue(metric.time_series.samples[i].value, metric.unit), .time = metric.time_series.samples[i].timestamp, .metadata = metric.time_series.samples[i].sample_metadata}); } PrintResult(metric.name, /*modifier=*/"", metric.test_case, counter, ToPrintResultUnit(metric.unit), /*important=*/false, ToPrintResultImproveDirection(metric.improvement_direction)); } return true; } } // namespace test } // namespace webrtc