Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset e7f9a09 in mainline


Ignore:
Timestamp:
2019-01-21T13:20:31Z (2 years ago)
Author:
Vojtech Horky <vojtech.horky@…>
Branches:
lfn, master
Children:
d17cf8c
Parents:
94ebebf
Message:

hbench: less parameters to benchmark runners

Merge stopwatch as well as error message buffer into one structure to
simplify benchmark runner signature.

Location:
uspace/app/hbench
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/hbench/csv.c

    r94ebebf re7f9a09  
    6262 * nothing.
    6363 *
    64  * @param stopwatch Performance data of the entry.
     64 * @param run Performance data of the entry.
    6565 * @param run_index Run index, use negative values for warm-up.
    6666 * @param bench Benchmark information.
    6767 * @param workload_size Workload size.
    6868 */
    69 void csv_report_add_entry(benchmeter_t *meter, int run_index,
     69void csv_report_add_entry(bench_run_t *run, int run_index,
    7070    benchmark_t *bench, uint64_t workload_size)
    7171{
     
    7676        fprintf(csv_output, "%s,%d,%" PRIu64 ",%lld\n",
    7777            bench->name, run_index, workload_size,
    78             (long long) stopwatch_get_nanos(&meter->stopwatch));
     78            (long long) stopwatch_get_nanos(&run->stopwatch));
    7979}
    8080
  • uspace/app/hbench/doc/doxygroups.h

    r94ebebf re7f9a09  
    1919 * benchmark function to the benchmark_t.
    2020 *
    21  * The benchmarking function has to accept four arguments:
    22  *  @li benchmeter_t: call benchmeter_start and benchmeter_stop around the
     21 * The benchmarking function has to accept two arguments:
     22 *  @li bench_run_t: call bench_run_start and bench_run_stop around the
    2323 *      actual benchmarking code
    2424 *  @li uint64_t: size of the workload - typically number of inner loops in
    2525 *      your benchmark (used to self-calibrate benchmark size)
    26  *  @li char * and size_t giving you access to buffer for storing error message
    27  *  if the benchmark fails (return false from the function itself then)
    2826 *
    2927 * Typically, the structure of the function is following:
    3028 * @code{c}
    31  * static bool runner(benchmeter_t *meter, uint64_t size,
    32  *     char *error, size_t error_size)
     29 * static bool runner(bench_run_t *run, uint64_t size)
    3330 * {
    34  *      benchmeter_start(meter);
     31 *      bench_run_start(run);
    3532 *      for (uint64_t i = 0; i < size; i++) {
    3633 *              // measured action
     34 *              if (something_fails) {
     35 *                  return bench_run_fail(run, "oops: %s (%d)", str_error(rc), rc);
     36 *              }
    3737 *      }
    38  *      benchmeter_stop(meter);
     38 *      bench_run_stop(run);
    3939 *
    4040 *      return true;
  • uspace/app/hbench/fs/dirread.c

    r94ebebf re7f9a09  
    4444 * that the corresponding blocks would be cached after first run.
    4545 */
    46 static bool runner(benchmeter_t *meter, uint64_t size,
    47     char *error, size_t error_size)
     46static bool runner(bench_run_t *run, uint64_t size)
    4847{
    4948        const char *path = bench_param_get("dirname", "/");
    5049
    51         benchmeter_start(meter);
     50        bench_run_start(run);
    5251        for (uint64_t i = 0; i < size; i++) {
    5352                DIR *dir = opendir(path);
    5453                if (dir == NULL) {
    55                         snprintf(error, error_size, "failed to open %s for reading: %s",
     54                        return bench_run_fail(run, "failed to open %s for reading: %s",
    5655                            path, str_error(errno));
    57                         return false;
    5856                }
    5957
     
    6563                closedir(dir);
    6664        }
    67         benchmeter_stop(meter);
     65        bench_run_stop(run);
    6866
    6967        return true;
  • uspace/app/hbench/fs/fileread.c

    r94ebebf re7f9a09  
    4545 * corresponding blocks would be cached after first run.
    4646 */
    47 static bool runner(benchmeter_t *meter, uint64_t size,
    48     char *error, size_t error_size)
     47static bool runner(bench_run_t *run, uint64_t size)
    4948{
    5049        const char *path = bench_param_get("filename", "/data/web/helenos.png");
     
    5251        char *buf = malloc(BUFFER_SIZE);
    5352        if (buf == NULL) {
    54                 snprintf(error, error_size, "failed to allocate %dB buffer", BUFFER_SIZE);
    55                 return false;
     53                return bench_run_fail(run, "failed to allocate %dB buffer", BUFFER_SIZE);
    5654        }
    5755
     
    6058        FILE *file = fopen(path, "r");
    6159        if (file == NULL) {
    62                 snprintf(error, error_size, "failed to open %s for reading: %s",
     60                bench_run_fail(run, "failed to open %s for reading: %s",
    6361                    path, str_error(errno));
    6462                ret = false;
     
    6664        }
    6765
    68         benchmeter_start(meter);
     66        bench_run_start(run);
    6967        for (uint64_t i = 0; i < size; i++) {
    7068                int rc = fseek(file, 0, SEEK_SET);
    7169                if (rc != 0) {
    72                         snprintf(error, error_size, "failed to rewind %s: %s",
     70                        bench_run_fail(run, "failed to rewind %s: %s",
    7371                            path, str_error(errno));
    7472                        ret = false;
     
    7876                        fread(buf, 1, BUFFER_SIZE, file);
    7977                        if (ferror(file)) {
    80                                 snprintf(error, error_size, "failed to read from %s: %s",
     78                                bench_run_fail(run, "failed to read from %s: %s",
    8179                                    path, str_error(errno));
    8280                                ret = false;
     
    8583                }
    8684        }
    87         benchmeter_stop(meter);
     85        bench_run_stop(run);
    8886
    8987leave_close:
  • uspace/app/hbench/hbench.h

    r94ebebf re7f9a09  
    3838
    3939#include <errno.h>
     40#include <stdarg.h>
    4041#include <stdbool.h>
     42#include <stdio.h>
    4143#include <perf.h>
    4244
    43 /** Simple wrapper around system stopwatch.
     45/** Single run information.
     46 *
     47 * Used to store both performance information (now, only wall-clock
     48 * time) as well as information about error.
     49 *
     50 * Use proper access functions when modifying data inside this structure.
    4451 *
    4552 * Eventually, we could collection of hardware counters etc. without
     
    4855typedef struct {
    4956        stopwatch_t stopwatch;
    50 } benchmeter_t;
     57        char *error_buffer;
     58        size_t error_buffer_size;
     59} bench_run_t;
    5160
    52 static inline void benchmeter_init(benchmeter_t *meter)
     61static inline void bench_run_init(bench_run_t *run, char *error_buffer,
     62    size_t error_buffer_size)
    5363{
    54         stopwatch_init(&meter->stopwatch);
     64        stopwatch_init(&run->stopwatch);
     65        run->error_buffer = error_buffer;
     66        run->error_buffer_size = error_buffer_size;
    5567}
    5668
    57 static inline void benchmeter_start(benchmeter_t *meter)
     69static inline void bench_run_start(bench_run_t *run)
    5870{
    59         stopwatch_start(&meter->stopwatch);
     71        stopwatch_start(&run->stopwatch);
    6072}
    6173
    62 static inline void benchmeter_stop(benchmeter_t *meter)
     74static inline void bench_run_stop(bench_run_t *run)
    6375{
    64         stopwatch_stop(&meter->stopwatch);
     76        stopwatch_stop(&run->stopwatch);
    6577}
    6678
    67 typedef bool (*benchmark_entry_t)(benchmeter_t *, uint64_t,
    68     char *, size_t);
    69 typedef bool (*benchmark_helper_t)(char *, size_t);
     79static inline bool bench_run_fail(bench_run_t *run, const char *fmt, ...)
     80{
     81        va_list args;
     82        va_start(args, fmt);
     83        vsnprintf(run->error_buffer, run->error_buffer_size, fmt, args);
     84        va_end(args);
     85
     86        return false;
     87}
     88
     89typedef bool (*benchmark_entry_t)(bench_run_t *, uint64_t);
     90typedef bool (*benchmark_helper_t)(bench_run_t *);
    7091
    7192typedef struct {
     
    81102
    82103extern errno_t csv_report_open(const char *);
    83 extern void csv_report_add_entry(benchmeter_t *, int, benchmark_t *, uint64_t);
     104extern void csv_report_add_entry(bench_run_t *, int, benchmark_t *, uint64_t);
    84105extern void csv_report_close(void);
    85106
  • uspace/app/hbench/ipc/ns_ping.c

    r94ebebf re7f9a09  
    3838#include "../hbench.h"
    3939
    40 static bool runner(benchmeter_t *meter, uint64_t niter,
    41     char *error, size_t error_size)
     40static bool runner(bench_run_t *run, uint64_t niter)
    4241{
    43         benchmeter_start(meter);
     42        bench_run_start(run);
    4443
    4544        for (uint64_t count = 0; count < niter; count++) {
     
    4746
    4847                if (rc != EOK) {
    49                         snprintf(error, error_size,
    50                             "failed sending ping message: %s (%d)",
     48                        return bench_run_fail(run, "failed sending ping message: %s (%d)",
    5149                            str_error(rc), rc);
    52                         return false;
    5350                }
    5451        }
    5552
    56         benchmeter_stop(meter);
     53        bench_run_stop(run);
    5754
    5855        return true;
  • uspace/app/hbench/ipc/ping_pong.c

    r94ebebf re7f9a09  
    4040static ipc_test_t *test = NULL;
    4141
    42 static bool setup(char *error, size_t error_size)
     42static bool setup(bench_run_t *run)
    4343{
    4444        errno_t rc = ipc_test_create(&test);
    4545        if (rc != EOK) {
    46                 snprintf(error, error_size,
     46                return bench_run_fail(run,
    4747                    "failed contacting IPC test server (have you run /srv/test/ipc-test?): %s (%d)",
    4848                    str_error(rc), rc);
    49                 return false;
    5049        }
    5150
     
    5352}
    5453
    55 static bool teardown(char *error, size_t error_size)
     54static bool teardown(bench_run_t *run)
    5655{
    5756        ipc_test_destroy(test);
     
    5958}
    6059
    61 static bool runner(benchmeter_t *meter, uint64_t niter,
    62     char *error, size_t error_size)
     60static bool runner(bench_run_t *run, uint64_t niter)
    6361{
    64         benchmeter_start(meter);
     62        bench_run_start(run);
    6563
    6664        for (uint64_t count = 0; count < niter; count++) {
     
    6866
    6967                if (rc != EOK) {
    70                         snprintf(error, error_size,
    71                             "failed sending ping message: %s (%d)",
     68                        return bench_run_fail(run, "failed sending ping message: %s (%d)",
    7269                            str_error(rc), rc);
    73                         return false;
    7470                }
    7571        }
    7672
    77         benchmeter_stop(meter);
     73        bench_run_stop(run);
    7874
    7975        return true;
  • uspace/app/hbench/main.c

    r94ebebf re7f9a09  
    5353#define MAX_ERROR_STR_LENGTH 1024
    5454
    55 static void short_report(benchmeter_t *meter, int run_index,
     55static void short_report(bench_run_t *info, int run_index,
    5656    benchmark_t *bench, uint64_t workload_size)
    5757{
    58         csv_report_add_entry(meter, run_index, bench, workload_size);
    59 
    60         usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(&meter->stopwatch));
     58        csv_report_add_entry(info, run_index, bench, workload_size);
     59
     60        usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(&info->stopwatch));
    6161
    6262        printf("Completed %" PRIu64 " operations in %llu us",
    6363            workload_size, duration_usec);
    6464        if (duration_usec > 0) {
    65                 double nanos = stopwatch_get_nanos(&meter->stopwatch);
     65                double nanos = stopwatch_get_nanos(&info->stopwatch);
    6666                double thruput = (double) workload_size / (nanos / 1000000000.0l);
    6767                printf(", %.0f ops/s.\n", thruput);
     
    111111 *
    112112 */
    113 static void compute_stats(benchmeter_t *meter, size_t stopwatch_count,
     113static void compute_stats(bench_run_t *runs, size_t run_count,
    114114    uint64_t workload_size, double precision, double *out_duration_avg,
    115115    double *out_duration_sigma, double *out_thruput_avg)
     
    119119        double nanos_sum2 = 0.0;
    120120
    121         for (size_t i = 0; i < stopwatch_count; i++) {
    122                 double nanos = stopwatch_get_nanos(&meter[i].stopwatch);
     121        for (size_t i = 0; i < run_count; i++) {
     122                double nanos = stopwatch_get_nanos(&runs[i].stopwatch);
    123123                double thruput = (double) workload_size / nanos;
    124124
     
    127127                nanos_sum2 += nanos * nanos;
    128128        }
    129         *out_duration_avg = nanos_sum / stopwatch_count;
     129        *out_duration_avg = nanos_sum / run_count;
    130130        double sigma2 = (nanos_sum2 - nanos_sum * (*out_duration_avg)) /
    131             ((double) stopwatch_count - 1);
     131            ((double) run_count - 1);
    132132        // FIXME: implement sqrt properly
    133133        *out_duration_sigma = estimate_square_root(sigma2, precision);
    134         *out_thruput_avg = 1.0 / (inv_thruput_sum / stopwatch_count);
    135 }
    136 
    137 static void summary_stats(benchmeter_t *meter, size_t meter_count,
     134        *out_thruput_avg = 1.0 / (inv_thruput_sum / run_count);
     135}
     136
     137static void summary_stats(bench_run_t *runs, size_t run_count,
    138138    benchmark_t *bench, uint64_t workload_size)
    139139{
    140140        double duration_avg, duration_sigma, thruput_avg;
    141         compute_stats(meter, meter_count, workload_size, 0.001,
     141        compute_stats(runs, run_count, workload_size, 0.001,
    142142            &duration_avg, &duration_sigma, &thruput_avg);
    143143
     
    145145            "%.0f ops/s; Samples: %zu\n",
    146146            workload_size, duration_avg / 1000.0, duration_sigma / 1000.0,
    147             thruput_avg * 1000000000.0, meter_count);
     147            thruput_avg * 1000000000.0, run_count);
    148148}
    149149
     
    152152        printf("Warm up and determine workload size...\n");
    153153
     154        /*
     155         * We share this buffer across all runs as we know that it is
     156         * used only on failure (and we abort after first error).
     157         */
    154158        char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1);
    155159        if (error_msg == NULL) {
     
    159163        str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "");
    160164
     165        bench_run_t helper_run;
     166        bench_run_init(&helper_run, error_msg, MAX_ERROR_STR_LENGTH);
     167
    161168        bool ret = true;
    162169
    163170        if (bench->setup != NULL) {
    164                 ret = bench->setup(error_msg, MAX_ERROR_STR_LENGTH);
     171                ret = bench->setup(&helper_run);
    165172                if (!ret) {
    166173                        goto leave_error;
     
    180187                workload_size = ((uint64_t) 1) << bits;
    181188
    182                 benchmeter_t meter;
    183                 benchmeter_init(&meter);
    184 
    185                 bool ok = bench->entry(&meter, workload_size,
    186                     error_msg, MAX_ERROR_STR_LENGTH);
     189                bench_run_t run;
     190                bench_run_init(&run, error_msg, MAX_ERROR_STR_LENGTH);
     191
     192                bool ok = bench->entry(&run, workload_size);
    187193                if (!ok) {
    188194                        goto leave_error;
    189195                }
    190                 short_report(&meter, -1, bench, workload_size);
    191 
    192                 nsec_t duration = stopwatch_get_nanos(&meter.stopwatch);
     196                short_report(&run, -1, bench, workload_size);
     197
     198                nsec_t duration = stopwatch_get_nanos(&run.stopwatch);
    193199                if (duration > SEC2NSEC(MIN_DURATION_SECS)) {
    194200                        break;
     
    198204        printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES);
    199205
    200         benchmeter_t *meter = calloc(NUM_SAMPLES, sizeof(benchmeter_t));
    201         if (meter == NULL) {
     206        bench_run_t *runs = calloc(NUM_SAMPLES, sizeof(bench_run_t));
     207        if (runs == NULL) {
    202208                snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory");
    203209                goto leave_error;
    204210        }
    205211        for (int i = 0; i < NUM_SAMPLES; i++) {
    206                 benchmeter_init(&meter[i]);
    207 
    208                 bool ok = bench->entry(&meter[i], workload_size,
    209                     error_msg, MAX_ERROR_STR_LENGTH);
     212                bench_run_init(&runs[i], error_msg, MAX_ERROR_STR_LENGTH);
     213
     214                bool ok = bench->entry(&runs[i], workload_size);
    210215                if (!ok) {
    211                         free(meter);
     216                        free(runs);
    212217                        goto leave_error;
    213218                }
    214                 short_report(&meter[i], i, bench, workload_size);
    215         }
    216 
    217         summary_stats(meter, NUM_SAMPLES, bench, workload_size);
     219                short_report(&runs[i], i, bench, workload_size);
     220        }
     221
     222        summary_stats(runs, NUM_SAMPLES, bench, workload_size);
    218223        printf("\nBenchmark completed\n");
    219224
    220         free(meter);
     225        free(runs);
    221226
    222227        goto leave;
     
    228233leave:
    229234        if (bench->teardown != NULL) {
    230                 bool ok = bench->teardown(error_msg, MAX_ERROR_STR_LENGTH);
     235                bool ok = bench->teardown(&helper_run);
    231236                if (!ok) {
    232237                        printf("Error: %s\n", error_msg);
  • uspace/app/hbench/malloc/malloc1.c

    r94ebebf re7f9a09  
    3636#include "../hbench.h"
    3737
    38 static bool runner(benchmeter_t *meter, uint64_t size,
    39     char *error, size_t error_size)
     38static bool runner(bench_run_t *run, uint64_t size)
    4039{
    41         benchmeter_start(meter);
     40        bench_run_start(run);
    4241        for (uint64_t i = 0; i < size; i++) {
    4342                void *p = malloc(1);
    4443                if (p == NULL) {
    45                         snprintf(error, error_size,
     44                        return bench_run_fail(run,
    4645                            "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
    4746                            i, size);
    48                         return false;
    4947                }
    5048                free(p);
    5149        }
    52         benchmeter_stop(meter);
     50        bench_run_stop(run);
    5351
    5452        return true;
  • uspace/app/hbench/malloc/malloc2.c

    r94ebebf re7f9a09  
    3535#include "../hbench.h"
    3636
    37 static bool runner(benchmeter_t *meter, uint64_t niter,
    38     char *error, size_t error_size)
     37static bool runner(bench_run_t *run, uint64_t niter)
    3938{
    40         benchmeter_start(meter);
     39        bench_run_start(run);
    4140
    4241        void **p = malloc(niter * sizeof(void *));
    4342        if (p == NULL) {
    44                 snprintf(error, error_size,
    45                     "failed to allocate backend array (%" PRIu64 "B)",
     43                return bench_run_fail(run, "failed to allocate backend array (%" PRIu64 "B)",
    4644                    niter * sizeof(void *));
    47                 return false;
    4845        }
    4946
     
    5148                p[count] = malloc(1);
    5249                if (p[count] == NULL) {
    53                         snprintf(error, error_size,
    54                             "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
    55                             count, niter);
    5650                        for (uint64_t j = 0; j < count; j++) {
    5751                                free(p[j]);
    5852                        }
    5953                        free(p);
    60                         return false;
     54                        return bench_run_fail(run,
     55                            "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
     56                            count, niter);
    6157                }
    6258        }
     
    6763        free(p);
    6864
    69         benchmeter_stop(meter);
     65        bench_run_stop(run);
    7066
    7167        return true;
  • uspace/app/hbench/synch/fibril_mutex.c

    r94ebebf re7f9a09  
    6565}
    6666
    67 static bool runner(benchmeter_t *meter, uint64_t size,
    68     char *error, size_t error_size)
     67static bool runner(bench_run_t *run, uint64_t size)
    6968{
    7069        shared_t shared;
     
    7675        fibril_add_ready(other);
    7776
    78         benchmeter_start(meter);
     77        bench_run_start(run);
    7978        for (uint64_t i = 0; i < size; i++) {
    8079                fibril_mutex_lock(&shared.mutex);
     
    8281                fibril_mutex_unlock(&shared.mutex);
    8382        }
    84         benchmeter_stop(meter);
     83        bench_run_stop(run);
    8584
    8685        while (!atomic_load(&shared.done)) {
Note: See TracChangeset for help on using the changeset viewer.