Changeset 3bd74758 in mainline


Ignore:
Timestamp:
2018-12-28T09:32:11Z (5 years ago)
Author:
Vojtech Horky <vojtech.horky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c7de81b
Parents:
8ee106b
Message:

perf: huge refactoring

The overall aim of this refactoring was to remove duplicate code in all
benchmarks that was responsible (a) for computing proper workload size
and (b) for computing final statistics.

After the refactoring, the actual benchmark code is quite short and
takes care of the actual work only.

The harness code was factored out into perf.c that is now responsible
for computing the workload size and then runs the actual benchmark.

As an extra feature, we pass stopwatch_t into the benchmark code that is
only responsible for starting/stopping. Duration is then queried outside
the benchmark code.

Location:
uspace/app/perf
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/perf/ipc/ns_ping.c

    r8ee106b r3bd74758  
    2727 */
    2828
    29 #include <math.h>
    3029#include <stdio.h>
    31 #include <stdlib.h>
    32 #include <time.h>
    3330#include <ns.h>
    3431#include <async.h>
    3532#include <errno.h>
     33#include <str_error.h>
    3634#include "../perf.h"
    3735
    38 #define MIN_DURATION_SECS  10
    39 #define NUM_SAMPLES 10
     36bool bench_ns_ping(stopwatch_t *stopwatch, uint64_t niter,
     37    char *error, size_t error_size)
     38{
     39        stopwatch_start(stopwatch);
    4040
    41 static errno_t ping_pong_measure(uint64_t niter, uint64_t *rduration)
    42 {
    43         struct timespec start;
    44         uint64_t count;
     41        for (uint64_t count = 0; count < niter; count++) {
     42                errno_t rc = ns_ping();
    4543
    46         getuptime(&start);
    47 
    48         for (count = 0; count < niter; count++) {
    49                 errno_t retval = ns_ping();
    50 
    51                 if (retval != EOK) {
    52                         printf("Error sending ping message.\n");
    53                         return EIO;
     44                if (rc != EOK) {
     45                        snprintf(error, error_size,
     46                            "failed sending ping message: %s (%d)",
     47                            str_error(rc), rc);
     48                        return false;
    5449                }
    5550        }
    5651
    57         struct timespec now;
    58         getuptime(&now);
     52        stopwatch_stop(stopwatch);
    5953
    60         *rduration = ts_sub_diff(&now, &start) / 1000;
    61         return EOK;
     54        return true;
    6255}
    63 
    64 static void ping_pong_report(uint64_t niter, uint64_t duration)
    65 {
    66         printf("Completed %" PRIu64 " round trips in %" PRIu64 " us",
    67             niter, duration);
    68 
    69         if (duration > 0) {
    70                 printf(", %" PRIu64 " rt/s.\n", niter * 1000 * 1000 / duration);
    71         } else {
    72                 printf(".\n");
    73         }
    74 }
    75 
    76 const char *bench_ns_ping(void)
    77 {
    78         errno_t rc;
    79         uint64_t duration;
    80         uint64_t dsmp[NUM_SAMPLES];
    81 
    82         printf("Warm up and determine work size...\n");
    83 
    84         struct timespec start;
    85         getuptime(&start);
    86 
    87         uint64_t niter = 1;
    88 
    89         while (true) {
    90                 rc = ping_pong_measure(niter, &duration);
    91                 if (rc != EOK)
    92                         return "Failed.";
    93 
    94                 ping_pong_report(niter, duration);
    95 
    96                 if (duration >= MIN_DURATION_SECS * 1000000)
    97                         break;
    98 
    99                 niter *= 2;
    100         }
    101 
    102         printf("Measure %d samples...\n", NUM_SAMPLES);
    103 
    104         int i;
    105 
    106         for (i = 0; i < NUM_SAMPLES; i++) {
    107                 rc = ping_pong_measure(niter, &dsmp[i]);
    108                 if (rc != EOK)
    109                         return "Failed.";
    110 
    111                 ping_pong_report(niter, dsmp[i]);
    112         }
    113 
    114         double sum = 0.0;
    115 
    116         for (i = 0; i < NUM_SAMPLES; i++)
    117                 sum += (double)niter / ((double)dsmp[i] / 1000000.0l);
    118 
    119         double avg = sum / NUM_SAMPLES;
    120 
    121         double qd = 0.0;
    122         double d;
    123         for (i = 0; i < NUM_SAMPLES; i++) {
    124                 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg;
    125                 qd += d * d;
    126         }
    127 
    128         double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt
    129 
    130         printf("Average: %.0f rt/s Std.dev^2: %.0f rt/s Samples: %d\n",
    131             avg, stddev, NUM_SAMPLES);
    132 
    133         return NULL;
    134 }
  • uspace/app/perf/ipc/ns_ping.def

    r8ee106b r3bd74758  
    22        "ns_ping",
    33        "Name service IPC ping-pong benchmark",
    4         &bench_ns_ping
     4        &bench_ns_ping,
     5        NULL, NULL
    56},
  • uspace/app/perf/ipc/ping_pong.c

    r8ee106b r3bd74758  
    2727 */
    2828
    29 #include <math.h>
    3029#include <stdio.h>
    31 #include <stdlib.h>
    32 #include <time.h>
    3330#include <ipc_test.h>
    3431#include <async.h>
    3532#include <errno.h>
     33#include <str_error.h>
    3634#include "../perf.h"
    3735
    38 #define MIN_DURATION_SECS  10
    39 #define NUM_SAMPLES 10
     36static ipc_test_t *test = NULL;
    4037
    41 static errno_t ping_pong_measure(ipc_test_t *test, uint64_t niter,
    42     uint64_t *rduration)
     38bool bench_ping_pong_setup(char *error, size_t error_size)
    4339{
    44         struct timespec start;
    45         uint64_t count;
     40        errno_t rc = ipc_test_create(&test);
     41        if (rc != EOK) {
     42                snprintf(error, error_size,
     43                    "failed contacting IPC test server: %s (%d)",
     44                    str_error(rc), rc);
     45                return false;
     46        }
    4647
    47         getuptime(&start);
     48        return true;
     49}
    4850
    49         for (count = 0; count < niter; count++) {
    50                 errno_t retval = ipc_test_ping(test);
     51bool bench_ping_pong_teardown(char *error, size_t error_size)
     52{
     53        ipc_test_destroy(test);
     54        return true;
     55}
    5156
    52                 if (retval != EOK) {
    53                         printf("Error sending ping message.\n");
    54                         return EIO;
     57bool bench_ping_pong(stopwatch_t *stopwatch, uint64_t niter,
     58    char *error, size_t error_size)
     59{
     60        stopwatch_start(stopwatch);
     61
     62        for (uint64_t count = 0; count < niter; count++) {
     63                errno_t rc = ipc_test_ping(test);
     64
     65                if (rc != EOK) {
     66                        snprintf(error, error_size,
     67                            "failed sending ping message: %s (%d)",
     68                            str_error(rc), rc);
     69                        return false;
    5570                }
    5671        }
    5772
    58         struct timespec now;
    59         getuptime(&now);
     73        stopwatch_stop(stopwatch);
    6074
    61         *rduration = ts_sub_diff(&now, &start) / 1000;
    62         return EOK;
     75        return true;
    6376}
    64 
    65 static void ping_pong_report(uint64_t niter, uint64_t duration)
    66 {
    67         printf("Completed %" PRIu64 " round trips in %" PRIu64 " us",
    68             niter, duration);
    69 
    70         if (duration > 0) {
    71                 printf(", %" PRIu64 " rt/s.\n", niter * 1000 * 1000 / duration);
    72         } else {
    73                 printf(".\n");
    74         }
    75 }
    76 
    77 const char *bench_ping_pong(void)
    78 {
    79         errno_t rc;
    80         uint64_t duration;
    81         uint64_t dsmp[NUM_SAMPLES];
    82         ipc_test_t *test;
    83         const char *msg;
    84 
    85         rc = ipc_test_create(&test);
    86         if (rc != EOK)
    87                 return "Failed contacting IPC test server.";
    88 
    89         printf("Warm up and determine work size...\n");
    90 
    91         struct timespec start;
    92         getuptime(&start);
    93 
    94         uint64_t niter = 1;
    95 
    96         while (true) {
    97                 rc = ping_pong_measure(test, niter, &duration);
    98                 if (rc != EOK) {
    99                         msg = "Failed.";
    100                         goto error;
    101                 }
    102 
    103                 ping_pong_report(niter, duration);
    104 
    105                 if (duration >= MIN_DURATION_SECS * 1000000)
    106                         break;
    107 
    108                 niter *= 2;
    109         }
    110 
    111         printf("Measure %d samples...\n", NUM_SAMPLES);
    112 
    113         int i;
    114 
    115         for (i = 0; i < NUM_SAMPLES; i++) {
    116                 rc = ping_pong_measure(test, niter, &dsmp[i]);
    117                 if (rc != EOK) {
    118                         msg = "Failed.";
    119                         goto error;
    120                 }
    121 
    122                 ping_pong_report(niter, dsmp[i]);
    123         }
    124 
    125         double sum = 0.0;
    126 
    127         for (i = 0; i < NUM_SAMPLES; i++)
    128                 sum += (double)niter / ((double)dsmp[i] / 1000000.0l);
    129 
    130         double avg = sum / NUM_SAMPLES;
    131 
    132         double qd = 0.0;
    133         double d;
    134         for (i = 0; i < NUM_SAMPLES; i++) {
    135                 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg;
    136                 qd += d * d;
    137         }
    138 
    139         double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt
    140 
    141         printf("Average: %.0f rt/s Std.dev^2: %.0f rt/s Samples: %d\n",
    142             avg, stddev, NUM_SAMPLES);
    143 
    144         ipc_test_destroy(test);
    145         return NULL;
    146 error:
    147         ipc_test_destroy(test);
    148         return msg;
    149 }
  • uspace/app/perf/ipc/ping_pong.def

    r8ee106b r3bd74758  
    22        "ping_pong",
    33        "IPC ping-pong benchmark",
    4         &bench_ping_pong
     4        &bench_ping_pong,
     5        &bench_ping_pong_setup, &bench_ping_pong_teardown
    56},
  • uspace/app/perf/malloc/malloc1.c

    r8ee106b r3bd74758  
    3030#include <stdio.h>
    3131#include <stdlib.h>
    32 #include <time.h>
    33 #include <errno.h>
    3432#include "../perf.h"
    3533
    36 #define MIN_DURATION_SECS  10
    37 #define NUM_SAMPLES 10
    38 
    39 static errno_t malloc1_measure(uint64_t niter, uint64_t *rduration)
     34bool bench_malloc1(stopwatch_t *stopwatch, uint64_t size,
     35    char *error, size_t error_size)
    4036{
    41         struct timespec start;
    42         uint64_t count;
    43         void *p;
    44 
    45         getuptime(&start);
    46 
    47         for (count = 0; count < niter; count++) {
    48                 p = malloc(1);
    49                 if (p == NULL)
    50                         return ENOMEM;
     37        stopwatch_start(stopwatch);
     38        for (uint64_t i = 0; i < size; i++) {
     39                void *p = malloc(1);
     40                if (p == NULL) {
     41                        snprintf(error, error_size,
     42                            "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
     43                            i, size);
     44                        return false;
     45                }
    5146                free(p);
    5247        }
     48        stopwatch_stop(stopwatch);
    5349
    54         struct timespec now;
    55         getuptime(&now);
    56 
    57         *rduration = ts_sub_diff(&now, &start) / 1000;
    58         return EOK;
     50        return true;
    5951}
    60 
    61 static void malloc1_report(uint64_t niter, uint64_t duration)
    62 {
    63         printf("Completed %" PRIu64 " allocations and deallocations in %" PRIu64 " us",
    64             niter, duration);
    65 
    66         if (duration > 0) {
    67                 printf(", %" PRIu64 " cycles/s.\n", niter * 1000 * 1000 / duration);
    68         } else {
    69                 printf(".\n");
    70         }
    71 }
    72 
    73 const char *bench_malloc1(void)
    74 {
    75         errno_t rc;
    76         uint64_t duration;
    77         uint64_t dsmp[NUM_SAMPLES];
    78         const char *msg;
    79 
    80         printf("Warm up and determine work size...\n");
    81 
    82         struct timespec start;
    83         getuptime(&start);
    84 
    85         uint64_t niter = 1;
    86 
    87         while (true) {
    88                 rc = malloc1_measure(niter, &duration);
    89                 if (rc != EOK) {
    90                         msg = "Failed.";
    91                         goto error;
    92                 }
    93 
    94                 malloc1_report(niter, duration);
    95 
    96                 if (duration >= MIN_DURATION_SECS * 1000000)
    97                         break;
    98 
    99                 niter *= 2;
    100         }
    101 
    102         printf("Measure %d samples...\n", NUM_SAMPLES);
    103 
    104         int i;
    105 
    106         for (i = 0; i < NUM_SAMPLES; i++) {
    107                 rc = malloc1_measure(niter, &dsmp[i]);
    108                 if (rc != EOK) {
    109                         msg = "Failed.";
    110                         goto error;
    111                 }
    112 
    113                 malloc1_report(niter, dsmp[i]);
    114         }
    115 
    116         double sum = 0.0;
    117 
    118         for (i = 0; i < NUM_SAMPLES; i++)
    119                 sum += (double)niter / ((double)dsmp[i] / 1000000.0l);
    120 
    121         double avg = sum / NUM_SAMPLES;
    122 
    123         double qd = 0.0;
    124         double d;
    125         for (i = 0; i < NUM_SAMPLES; i++) {
    126                 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg;
    127                 qd += d * d;
    128         }
    129 
    130         double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt
    131 
    132         printf("Average: %.0f cycles/s Std.dev^2: %.0f cycles/s Samples: %d\n",
    133             avg, stddev, NUM_SAMPLES);
    134 
    135         return NULL;
    136 error:
    137         return msg;
    138 }
  • uspace/app/perf/malloc/malloc1.def

    r8ee106b r3bd74758  
    22        "malloc1",
    33        "User-space memory allocator benchmark, repeatedly allocate one block",
    4         &bench_malloc1
     4        &bench_malloc1,
     5        NULL, NULL
    56},
  • uspace/app/perf/malloc/malloc2.c

    r8ee106b r3bd74758  
    2727 */
    2828
    29 #include <math.h>
     29#include <stdlib.h>
    3030#include <stdio.h>
    31 #include <stdlib.h>
    32 #include <time.h>
    33 #include <errno.h>
    3431#include "../perf.h"
    3532
    36 #define MIN_DURATION_SECS  10
    37 #define NUM_SAMPLES 10
     33bool bench_malloc2(stopwatch_t *stopwatch, uint64_t niter,
     34    char *error, size_t error_size)
     35{
     36        stopwatch_start(stopwatch);
    3837
    39 static errno_t malloc2_measure(uint64_t niter, uint64_t *rduration)
    40 {
    41         struct timespec start;
    42         uint64_t count;
    43         void **p;
    44 
    45         getuptime(&start);
    46 
    47         p = malloc(niter * sizeof(void *));
    48         if (p == NULL)
    49                 return ENOMEM;
    50 
    51         for (count = 0; count < niter; count++) {
    52                 p[count] = malloc(1);
    53                 if (p[count] == NULL)
    54                         return ENOMEM;
     38        void **p = malloc(niter * sizeof(void *));
     39        if (p == NULL) {
     40                snprintf(error, error_size,
     41                    "failed to allocate backend array (%" PRIu64 "B)",
     42                    niter * sizeof(void *));
     43                return false;
    5544        }
    5645
    57         for (count = 0; count < niter; count++)
     46        for (uint64_t count = 0; count < niter; count++) {
     47                p[count] = malloc(1);
     48                if (p[count] == NULL) {
     49                        snprintf(error, error_size,
     50                            "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
     51                            count, niter);
     52                        for (uint64_t j = 0; j < count; j++) {
     53                                free(p[j]);
     54                        }
     55                        free(p);
     56                        return false;
     57                }
     58        }
     59
     60        for (uint64_t count = 0; count < niter; count++)
    5861                free(p[count]);
    5962
    6063        free(p);
    6164
    62         struct timespec now;
    63         getuptime(&now);
     65        stopwatch_stop(stopwatch);
    6466
    65         *rduration = ts_sub_diff(&now, &start) / 1000;
    66         return EOK;
     67        return true;
    6768}
    68 
    69 static void malloc2_report(uint64_t niter, uint64_t duration)
    70 {
    71         printf("Completed %" PRIu64 " allocations and deallocations in %" PRIu64 " us",
    72             niter, duration);
    73 
    74         if (duration > 0) {
    75                 printf(", %" PRIu64 " cycles/s.\n", niter * 1000 * 1000 / duration);
    76         } else {
    77                 printf(".\n");
    78         }
    79 }
    80 
    81 const char *bench_malloc2(void)
    82 {
    83         errno_t rc;
    84         uint64_t duration;
    85         uint64_t dsmp[NUM_SAMPLES];
    86         const char *msg;
    87 
    88         printf("Warm up and determine work size...\n");
    89 
    90         struct timespec start;
    91         getuptime(&start);
    92 
    93         uint64_t niter = 1;
    94 
    95         while (true) {
    96                 rc = malloc2_measure(niter, &duration);
    97                 if (rc != EOK) {
    98                         msg = "Failed.";
    99                         goto error;
    100                 }
    101 
    102                 malloc2_report(niter, duration);
    103 
    104                 if (duration >= MIN_DURATION_SECS * 1000000)
    105                         break;
    106 
    107                 niter *= 2;
    108         }
    109 
    110         printf("Measure %d samples...\n", NUM_SAMPLES);
    111 
    112         int i;
    113 
    114         for (i = 0; i < NUM_SAMPLES; i++) {
    115                 rc = malloc2_measure(niter, &dsmp[i]);
    116                 if (rc != EOK) {
    117                         msg = "Failed.";
    118                         goto error;
    119                 }
    120 
    121                 malloc2_report(niter, dsmp[i]);
    122         }
    123 
    124         double sum = 0.0;
    125 
    126         for (i = 0; i < NUM_SAMPLES; i++)
    127                 sum += (double)niter / ((double)dsmp[i] / 1000000.0l);
    128 
    129         double avg = sum / NUM_SAMPLES;
    130 
    131         double qd = 0.0;
    132         double d;
    133         for (i = 0; i < NUM_SAMPLES; i++) {
    134                 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg;
    135                 qd += d * d;
    136         }
    137 
    138         double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt
    139 
    140         printf("Average: %.0f cycles/s Std.dev^2: %.0f cycles/s Samples: %d\n",
    141             avg, stddev, NUM_SAMPLES);
    142 
    143         return NULL;
    144 error:
    145         return msg;
    146 }
  • uspace/app/perf/malloc/malloc2.def

    r8ee106b r3bd74758  
    22        "malloc2",
    33        "User-space memory allocator benchmark, allocate many small blocks",
    4         &bench_malloc2
     4        &bench_malloc2,
     5        NULL, NULL
    56},
  • uspace/app/perf/perf.c

    r8ee106b r3bd74758  
    11/*
    22 * Copyright (c) 2018 Jiri Svoboda
     3 * Copyright (c) 2018 Vojtech Horky
    34 * All rights reserved.
    45 *
     
    3839#include <stdlib.h>
    3940#include <str.h>
     41#include <time.h>
     42#include <errno.h>
     43#include <perf.h>
    4044#include "perf.h"
     45
     46#define MIN_DURATION_SECS 10
     47#define NUM_SAMPLES 10
     48#define MAX_ERROR_STR_LENGTH 1024
    4149
    4250benchmark_t benchmarks[] = {
     
    4553#include "malloc/malloc1.def"
    4654#include "malloc/malloc2.def"
    47         { NULL, NULL, NULL }
     55        { NULL, NULL, NULL, NULL, NULL }
    4856};
    4957
     58static void short_report(stopwatch_t *stopwatch, int run_index,
     59    benchmark_t *bench, size_t workload_size)
     60{
     61        usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(stopwatch));
     62
     63        printf("Completed %zu operations in %llu us",
     64            workload_size, duration_usec);
     65        if (duration_usec > 0) {
     66                double cycles = workload_size * 1000 * 1000 / duration_usec;
     67                printf(", %.0f cycles/s.\n", cycles);
     68        } else {
     69                printf(".\n");
     70        }
     71}
     72
     73static void summary_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
     74    benchmark_t *bench, size_t workload_size)
     75{
     76        double sum = 0.0;
     77        double sum_square = 0.0;
     78
     79        for (size_t i = 0; i < stopwatch_count; i++) {
     80                double nanos = stopwatch_get_nanos(&stopwatch[i]);
     81                double thruput = (double) workload_size / (nanos / 1000000000.0l);
     82                sum += thruput;
     83                sum_square += thruput * thruput;
     84        }
     85
     86        double avg = sum / stopwatch_count;
     87
     88        double sd_numer = sum_square + stopwatch_count * avg * avg - 2 * sum * avg;
     89        double sd_square = sd_numer / ((double) stopwatch_count - 1);
     90
     91        printf("Average: %.0f cycles/s Std.dev^2: %.0f cycles/s Samples: %zu\n",
     92            avg, sd_square, stopwatch_count);
     93}
     94
    5095static bool run_benchmark(benchmark_t *bench)
    5196{
    52         /* Execute the benchmarl */
    53         const char *ret = bench->entry();
    54 
    55         if (ret == NULL) {
    56                 printf("\nBenchmark completed\n");
    57                 return true;
    58         }
    59 
    60         printf("\n%s\n", ret);
    61         return false;
     97        printf("Warm up and determine workload size...\n");
     98
     99        char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1);
     100        if (error_msg == NULL) {
     101                printf("Out of memory!\n");
     102                return false;
     103        }
     104        str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "");
     105
     106        bool ret = true;
     107
     108        if (bench->setup != NULL) {
     109                ret = bench->setup(error_msg, MAX_ERROR_STR_LENGTH);
     110                if (!ret) {
     111                        goto leave_error;
     112                }
     113        }
     114
     115        size_t workload_size = 1;
     116
     117        while (true) {
     118                stopwatch_t stopwatch = STOPWATCH_INITIALIZE_STATIC;
     119
     120                bool ok = bench->entry(&stopwatch, workload_size,
     121                    error_msg, MAX_ERROR_STR_LENGTH);
     122                if (!ok) {
     123                        goto leave_error;
     124                }
     125                short_report(&stopwatch, -1, bench, workload_size);
     126
     127                nsec_t duration = stopwatch_get_nanos(&stopwatch);
     128                if (duration > SEC2NSEC(MIN_DURATION_SECS)) {
     129                        break;
     130                }
     131                workload_size *= 2;
     132        }
     133
     134        printf("Workload size set to %zu, measuring %d samples.\n", workload_size, NUM_SAMPLES);
     135
     136        stopwatch_t *stopwatch = calloc(NUM_SAMPLES, sizeof(stopwatch_t));
     137        if (stopwatch == NULL) {
     138                snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory");
     139                goto leave_error;
     140        }
     141        for (int i = 0; i < NUM_SAMPLES; i++) {
     142                stopwatch_init(&stopwatch[i]);
     143
     144                bool ok = bench->entry(&stopwatch[i], workload_size,
     145                    error_msg, MAX_ERROR_STR_LENGTH);
     146                if (!ok) {
     147                        free(stopwatch);
     148                        goto leave_error;
     149                }
     150                short_report(&stopwatch[i], i, bench, workload_size);
     151        }
     152
     153        summary_stats(stopwatch, NUM_SAMPLES, bench, workload_size);
     154        printf("\nBenchmark completed\n");
     155
     156        free(stopwatch);
     157
     158        goto leave;
     159
     160leave_error:
     161        printf("Error: %s\n", error_msg);
     162        ret = false;
     163
     164leave:
     165        if (bench->teardown != NULL) {
     166                bool ok = bench->teardown(error_msg, MAX_ERROR_STR_LENGTH);
     167                if (!ok) {
     168                        printf("Error: %s\n", error_msg);
     169                        ret = false;
     170                }
     171        }
     172
     173        free(error_msg);
     174
     175        return ret;
    62176}
    63177
  • uspace/app/perf/perf.h

    r8ee106b r3bd74758  
    3737
    3838#include <stdbool.h>
     39#include <perf.h>
    3940
    40 typedef const char *(*benchmark_entry_t)(void);
     41typedef bool (*benchmark_entry_t)(stopwatch_t *, uint64_t,
     42    char *, size_t);
     43typedef bool (*benchmark_helper_t)(char *, size_t);
    4144
    4245typedef struct {
     
    4447        const char *desc;
    4548        benchmark_entry_t entry;
     49        benchmark_helper_t setup;
     50        benchmark_helper_t teardown;
    4651} benchmark_t;
    4752
    48 extern const char *bench_malloc1(void);
    49 extern const char *bench_malloc2(void);
    50 extern const char *bench_ns_ping(void);
    51 extern const char *bench_ping_pong(void);
     53extern bool bench_malloc1(stopwatch_t *, uint64_t, char *, size_t);
     54extern bool bench_malloc2(stopwatch_t *, uint64_t, char *, size_t);
     55extern bool bench_ns_ping(stopwatch_t *, uint64_t, char *, size_t);
     56extern bool bench_ping_pong(stopwatch_t *, uint64_t, char *, size_t);
     57extern bool bench_ping_pong_setup(char *, size_t);
     58extern bool bench_ping_pong_teardown(char *, size_t);
    5259
    5360extern benchmark_t benchmarks[];
Note: See TracChangeset for help on using the changeset viewer.