stdout_metrics_exporter.cc (4023B)
1 /* 2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 #include "api/test/metrics/stdout_metrics_exporter.h" 11 12 #include <cmath> 13 #include <cstdint> 14 #include <cstdio> 15 #include <optional> 16 #include <string> 17 18 #include "absl/flags/flag.h" 19 #include "absl/strings/str_cat.h" 20 #include "api/array_view.h" 21 #include "api/test/metrics/metric.h" 22 #include "rtc_base/strings/string_builder.h" 23 #include "test/test_flags.h" 24 25 namespace webrtc { 26 namespace test { 27 namespace { 28 29 // Returns positive integral part of the number. 30 int64_t IntegralPart(double value) { 31 return std::lround(std::floor(std::abs(value))); 32 } 33 34 void AppendWithPrecision(double value, 35 int digits_after_comma, 36 StringBuilder& out) { 37 int64_t multiplier = std::lround(std::pow(10, digits_after_comma)); 38 int64_t integral_part = IntegralPart(value); 39 double decimal_part = std::abs(value) - integral_part; 40 41 // If decimal part has leading zeros then when it will be multiplied on 42 // `multiplier`, leading zeros will be lost. To preserve them we add "1" 43 // so then leading digit will be greater than 0 and won't be removed. 44 // 45 // During conversion to the string leading digit has to be stripped. 46 // 47 // Also due to rounding it may happen that leading digit may be incremented, 48 // like with `digits_after_comma` 3 number 1.9995 will be rounded to 2. In 49 // such case this increment has to be propagated to the `integral_part`. 50 int64_t decimal_holder = std::lround((1 + decimal_part) * multiplier); 51 if (decimal_holder >= 2 * multiplier) { 52 // Rounding incremented added leading digit, so we need to transfer 1 to 53 // integral part. 54 integral_part++; 55 decimal_holder -= multiplier; 56 } 57 // Remove trailing zeros. 58 while (decimal_holder % 10 == 0) { 59 decimal_holder /= 10; 60 } 61 62 // Print serialized number to output. 63 if (value < 0) { 64 out << "-"; 65 } 66 out << integral_part; 67 if (decimal_holder != 1) { 68 out << "." << std::to_string(decimal_holder).substr(1, digits_after_comma); 69 } 70 } 71 72 std::string TestCaseAndMetadata(const Metric& metric) { 73 if (absl::GetFlag(FLAGS_isolated_script_test_perf_output).empty()) { 74 if (metric.metric_metadata.contains("video_stream")) { 75 return absl::StrCat(metric.test_case, "/", 76 metric.metric_metadata.at("video_stream"), "_", 77 metric.metric_metadata.at("sender"), "_", 78 metric.metric_metadata.at("receiver")); 79 } 80 if (metric.metric_metadata.contains("peer")) { 81 return absl::StrCat(metric.test_case, "/", 82 metric.metric_metadata.at("peer")); 83 } 84 } 85 return metric.test_case; 86 } 87 88 } // namespace 89 90 StdoutMetricsExporter::StdoutMetricsExporter() : output_(stdout) {} 91 92 bool StdoutMetricsExporter::Export(ArrayView<const Metric> metrics) { 93 for (const Metric& metric : metrics) { 94 PrintMetric(metric); 95 } 96 return true; 97 } 98 99 void StdoutMetricsExporter::PrintMetric(const Metric& metric) { 100 StringBuilder value_stream; 101 value_stream << TestCaseAndMetadata(metric) << " / " << metric.name 102 << "= {mean="; 103 if (metric.stats.mean.has_value()) { 104 AppendWithPrecision(*metric.stats.mean, 8, value_stream); 105 } else { 106 value_stream << "-"; 107 } 108 value_stream << ", stddev="; 109 if (metric.stats.stddev.has_value()) { 110 AppendWithPrecision(*metric.stats.stddev, 8, value_stream); 111 } else { 112 value_stream << "-"; 113 } 114 value_stream << "} " << ToString(metric.unit) << " (" 115 << ToString(metric.improvement_direction) << ")"; 116 117 fprintf(output_, "RESULT: %s\n", value_stream.str().c_str()); 118 } 119 120 } // namespace test 121 } // namespace webrtc