/* * Copyright (C) 2023 The Android Open Source Project * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include #include #include #include "trusty_bench_option_cb.h" /** * enum bench_aggregate_idx - The position of the calculated aggregate in the * aggregate array of the bench_metric_node * @BENCH_AGGREGATE_MIN: index of the current minimum value for this metric. * @BENCH_AGGREGATE_MAX: index of the current maximum value for this metric. * @BENCH_AGGREGATE_AVG: index of the current average value for this metric. * @BENCH_AGGREGATE_COLD:index of the cold run value for this metric. * @BENCH_NUM_AGGREGATE: Number of available aggregates. Indicates the end of * the enum possible values. */ enum bench_aggregate_idx { BENCH_AGGREGATE_MIN = 0, BENCH_AGGREGATE_MAX = 1, BENCH_AGGREGATE_AVG = 2, BENCH_AGGREGATE_COLD = 3, BENCH_NUM_AGGREGATE = 4 }; /** * struct bench_metric_node - holds current aggregate for the metrics of the * current bench. * @cnt: Number of BENCH runs already aggregated. * @tot: Total of all values returned by BENCH_RESULT. * @cold: Value of the metric for the initial cold run. * @aggregates: Array of computed aggregates. * BENCH_AGGREGATE_MIN: Smallest value returned by * BENCH_RESULT. BENCH_AGGREGATE_MAX: Highest value returned by BENCH_RESULT. * BENCH_AGGREGATE_AVG: Average value returned by * BENCH_RESULT. */ struct bench_metric_node { size_t cnt; int64_t tot; int64_t cold; int64_t aggregates[BENCH_NUM_AGGREGATE]; }; /** * struct bench_metric_list_node - holds a metric declared by BENCH_RESULT in * a lk_list node * @node: List node. * @metric: Metric values container. * @name: Name to use in summary table header for this metric. * @param_idx: index of current param in param array this metric node * is aggregating for. * @col_sz: size in bytes needed to print this column. * @bench_result: Function pointer holding the BENCH_RESULT body * Used to get the value to be aggregate for this metric * after each BENCH body run. * @formatted_value_cb: A callback of * trusty_bench_get_formatted_value_callback_t type for * formatting the result value to a string * @param_name_cb: A callback of trusty_bench_get_param_name_callback_t * type for formatting the param name */ struct bench_metric_list_node { struct list_node node; struct bench_metric_node metric; const char* name; size_t param_idx; size_t nb_params; size_t col_sz; int64_t (*bench_result)(void); trusty_bench_get_formatted_value_callback_t formatted_value_cb; trusty_bench_get_param_name_callback_t param_name_cb; trusty_bench_check_results_callback_t check_results_cb; }; /* * Some Helper Functions for human readable output. */ /* Some hardcoded sizes */ #define BENCH_MAX_COL_SIZE 64 #define BENCH_LEFTMOST_COL_SIZE 16 #define BENCH_TITLE_WIDTH 72 /* Total Width of the resulting horizontal Table */ static size_t trusty_bench_table_total_width; /** * trusty_bench_validate_numeric - Utility function to parse Google F1 SQL valid * values except NaN and +/-inf * * @s: string to parse * * Return: true if s is a valid double */ static inline bool trusty_bench_validate_numeric(const char* s) { bool found_dot = false; /* ignore initital spaces */ while (*s != '\0' && (*s == ' ' || *s == '\t')) { ++s; } /* can optionally start with sign */ if (*s == '+' || *s == '-') { ++s; } /* Then digits and one optional dot */ while (*s != '\0' && *s != ' ' && *s != '\t') { switch (*s) { case '.': if (found_dot) { return false; } found_dot = true; break; case 'E': case 'e': found_dot = true; // dot are not allowed anymore // Start Exponent. Ignore Sign. ++s; if (*s == '+' || *s == '-') { ++s; } // Make sure there is an exponent after the E+/-. // Let the loop do the increment if (!isdigit(*s)) { return false; } break; default: // Note: Leading 0 are accepted by SQL SAFE_CAST parsing functions if (!isdigit(*s)) { return false; } break; } ++s; } /* ignore trailing spaces */ while (*s != '\0' && (*s == ' ' || *s == '\t')) { ++s; } if (*s == '\0') { return true; } return false; } /** * trusty_bench_sprint_col_stat - print the value of one statistical * aggregate in a formatted column * @buffer: Buffer in which to write the results. Preallocated. * @buffer_len: Size of the Buffer in bytes. * @val: Value to print * @metric_name: Name of the metric for which this value is to be * formatted */ static inline void trusty_bench_sprint_col_stat( char* buffer, size_t buffer_len, int64_t val, const char* metric_name, trusty_bench_get_formatted_value_callback_t value_format_cb) { if (value_format_cb == NULL) { value_format_cb = trusty_bench_get_formatted_value_cb; } if (value_format_cb == NULL) { snprintf(buffer, buffer_len, "%" PRId64, val); } else { value_format_cb(buffer, buffer_len, val, metric_name); EXPECT_EQ(trusty_bench_validate_numeric(buffer), true, "%s is not a valid double representation.\n", buffer); } } /* Number of CPU on which to bench */ static uint8_t trusty_bench_nb_cpu = 1; static size_t trusty_cur_bench_nb_params = 1; static size_t trusty_bench_multi_cpu_param_idx(size_t param_idx) { return param_idx % trusty_cur_bench_nb_params; } static size_t trusty_bench_cpu_idx(size_t param_idx) { return param_idx / trusty_cur_bench_nb_params; }