| // Copyright 2022 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef ML_BENCHMARK_DRIVER_COMMON_UTILS_H_ | |
| #define ML_BENCHMARK_DRIVER_COMMON_UTILS_H_ | |
| #include <algorithm> | |
| #include <cstdint> | |
| #include <string> | |
| #include <vector> | |
| #include <base/check.h> | |
| #include "proto/benchmark_config.pb.h" | |
| namespace chrome { | |
| namespace ml_benchmark { | |
| // The percentiles expected to be reported in percentile_latencies_in_us in | |
| // BenchmarkResults. May also be used for custom metrics, such as CPU time. | |
| constexpr int32_t kLatencyPercentiles[] = {50, 90, 95, 99}; | |
| // Serializes a BenchmarkResults into a buffer as expected by benchmark_start. | |
| // Allocates a buffer, whose location and size are returned in `results_data` | |
| // and `results_size`, and must be freed using FreeSerializedResults. | |
| int32_t SerializeResults(const BenchmarkResults& results, | |
| void** results_data, | |
| int32_t* results_size); | |
| // Generates a BenchmarkResults proto containing an error code and message, | |
| // and directly serializes it into a buffer as expected by benchmark_start. | |
| // Allocates a buffer, whose location and size are returned in `results_data` | |
| // and `results_size`, and must be freed using FreeSerializedResults. | |
| int32_t SerializeError(const std::string& error_message, | |
| BenchmarkReturnStatus status, | |
| void** results_data, | |
| int32_t* results_size); | |
| // Frees a buffer returned by SerializeResults or SerializeError, as needed by | |
| // free_benchmark_results. Does nothing if called with nullptr. | |
| void FreeSerializedResults(void* results_data); | |
| // Taken from chromium source cc/base/rolling_time_delta_history.cc | |
| // http://shortn/_mIhMWhPIUF and simplified since we're using a vector | |
| // and can index directly. | |
| // `samples` should be sorted before calling. | |
| // Returns the smallest sample that is greater than or equal to the specified | |
| // percent of samples. If there aren't any samples, returns 0. | |
| template <typename T> | |
| T ComputePercentile(const std::vector<T>& samples, double percent) { | |
| if (samples.size() == 0) | |
| return T(0); | |
| CHECK(std::is_sorted(samples.begin(), samples.end())); | |
| double fraction = percent / 100.0; | |
| if (fraction <= 0.0) | |
| return *(samples.begin()); | |
| if (fraction >= 1.0) | |
| return *(samples.rbegin()); | |
| size_t index = static_cast<size_t>(std::ceil(fraction * samples.size())) - 1; | |
| return samples[index]; | |
| } | |
| // Fills in percentile_latencies_in_us in `results` with the percentiles | |
| // expected by the framework, as listed in kLatencyPercentiles. | |
| // The percentiles are extracted from `latencies`, which must be given in | |
| // microseconds, and must be sorted before calling. | |
| template <typename T> | |
| void SetPercentileLatencies(BenchmarkResults& results, | |
| const std::vector<T>& latencies) { | |
| auto& percentile_latencies = *results.mutable_percentile_latencies_in_us(); | |
| for (const int32_t percentile : kLatencyPercentiles) { | |
| percentile_latencies[percentile] = ComputePercentile(latencies, percentile); | |
| } | |
| } | |
| } // namespace ml_benchmark | |
| } // namespace chrome | |
| #endif // ML_BENCHMARK_DRIVER_COMMON_UTILS_H_ |