Changes in / [b9f1585:7acd787] in mainline


Ignore:
Location:
uspace
Files:
4 added
6 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/perf/Makefile

    rb9f1585 r7acd787  
    3434
    3535SOURCES = \
    36         benchlist.c \
    3736        perf.c \
    3837        ipc/ns_ping.c \
  • uspace/app/perf/ipc/ns_ping.c

    rb9f1585 r7acd787  
    2727 */
    2828
     29#include <math.h>
    2930#include <stdio.h>
     31#include <stdlib.h>
     32#include <time.h>
    3033#include <ns.h>
    3134#include <async.h>
    3235#include <errno.h>
    33 #include <str_error.h>
    34 #include "../benchlist.h"
    3536#include "../perf.h"
    3637
    37 static bool runner(stopwatch_t *stopwatch, uint64_t niter,
    38     char *error, size_t error_size)
     38#define MIN_DURATION_SECS  10
     39#define NUM_SAMPLES 10
     40
     41static errno_t ping_pong_measure(uint64_t niter, uint64_t *rduration)
    3942{
    40         stopwatch_start(stopwatch);
     43        struct timespec start;
     44        uint64_t count;
    4145
    42         for (uint64_t count = 0; count < niter; count++) {
    43                 errno_t rc = ns_ping();
     46        getuptime(&start);
    4447
    45                 if (rc != EOK) {
    46                         snprintf(error, error_size,
    47                             "failed sending ping message: %s (%d)",
    48                             str_error(rc), rc);
    49                         return false;
     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;
    5054                }
    5155        }
    5256
    53         stopwatch_stop(stopwatch);
     57        struct timespec now;
     58        getuptime(&now);
    5459
    55         return true;
     60        *rduration = ts_sub_diff(&now, &start) / 1000;
     61        return EOK;
    5662}
    5763
    58 benchmark_t bench_ns_ping = {
    59         .name = "ns_ping",
    60         .desc = "Name service IPC ping-pong benchmark",
    61         .entry = &runner,
    62         .setup = NULL,
    63         .teardown = NULL
    64 };
     64static 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
     76const 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/ping_pong.c

    rb9f1585 r7acd787  
    2727 */
    2828
     29#include <math.h>
    2930#include <stdio.h>
     31#include <stdlib.h>
     32#include <time.h>
    3033#include <ipc_test.h>
    3134#include <async.h>
    3235#include <errno.h>
    33 #include <str_error.h>
    34 #include "../benchlist.h"
    3536#include "../perf.h"
    3637
    37 static ipc_test_t *test = NULL;
     38#define MIN_DURATION_SECS  10
     39#define NUM_SAMPLES 10
    3840
    39 static bool setup(char *error, size_t error_size)
     41static errno_t ping_pong_measure(ipc_test_t *test, uint64_t niter,
     42    uint64_t *rduration)
    4043{
    41         errno_t rc = ipc_test_create(&test);
    42         if (rc != EOK) {
    43                 snprintf(error, error_size,
    44                     "failed contacting IPC test server: %s (%d)",
    45                     str_error(rc), rc);
    46                 return false;
    47         }
     44        struct timespec start;
     45        uint64_t count;
    4846
    49         return true;
    50 }
     47        getuptime(&start);
    5148
    52 static bool teardown(char *error, size_t error_size)
    53 {
    54         ipc_test_destroy(test);
    55         return true;
    56 }
     49        for (count = 0; count < niter; count++) {
     50                errno_t retval = ipc_test_ping(test);
    5751
    58 static bool runner(stopwatch_t *stopwatch, uint64_t niter,
    59     char *error, size_t error_size)
    60 {
    61         stopwatch_start(stopwatch);
    62 
    63         for (uint64_t count = 0; count < niter; count++) {
    64                 errno_t rc = ipc_test_ping(test);
    65 
    66                 if (rc != EOK) {
    67                         snprintf(error, error_size,
    68                             "failed sending ping message: %s (%d)",
    69                             str_error(rc), rc);
    70                         return false;
     52                if (retval != EOK) {
     53                        printf("Error sending ping message.\n");
     54                        return EIO;
    7155                }
    7256        }
    7357
    74         stopwatch_stop(stopwatch);
     58        struct timespec now;
     59        getuptime(&now);
    7560
    76         return true;
     61        *rduration = ts_sub_diff(&now, &start) / 1000;
     62        return EOK;
    7763}
    7864
    79 benchmark_t bench_ping_pong = {
    80         .name = "ping_pong",
    81         .desc = "IPC ping-pong benchmark",
    82         .entry = &runner,
    83         .setup = &setup,
    84         .teardown = &teardown
    85 };
     65static 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
     77const 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;
     146error:
     147        ipc_test_destroy(test);
     148        return msg;
     149}
  • uspace/app/perf/malloc/malloc1.c

    rb9f1585 r7acd787  
    3030#include <stdio.h>
    3131#include <stdlib.h>
    32 #include "../benchlist.h"
     32#include <time.h>
     33#include <errno.h>
    3334#include "../perf.h"
    3435
    35 static bool runner(stopwatch_t *stopwatch, uint64_t size,
    36     char *error, size_t error_size)
     36#define MIN_DURATION_SECS  10
     37#define NUM_SAMPLES 10
     38
     39static errno_t malloc1_measure(uint64_t niter, uint64_t *rduration)
    3740{
    38         stopwatch_start(stopwatch);
    39         for (uint64_t i = 0; i < size; i++) {
    40                 void *p = malloc(1);
    41                 if (p == NULL) {
    42                         snprintf(error, error_size,
    43                             "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
    44                             i, size);
    45                         return false;
    46                 }
     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;
    4751                free(p);
    4852        }
    49         stopwatch_stop(stopwatch);
    5053
    51         return true;
     54        struct timespec now;
     55        getuptime(&now);
     56
     57        *rduration = ts_sub_diff(&now, &start) / 1000;
     58        return EOK;
    5259}
    5360
    54 benchmark_t bench_malloc1 = {
    55         .name = "malloc1",
    56         .desc = "User-space memory allocator benchmark, repeatedly allocate one block",
    57         .entry = &runner,
    58         .setup = NULL,
    59         .teardown = NULL
    60 };
     61static 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
     73const 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;
     136error:
     137        return msg;
     138}
  • uspace/app/perf/malloc/malloc2.c

    rb9f1585 r7acd787  
    2727 */
    2828
     29#include <math.h>
     30#include <stdio.h>
    2931#include <stdlib.h>
    30 #include <stdio.h>
    31 #include "../benchlist.h"
     32#include <time.h>
     33#include <errno.h>
    3234#include "../perf.h"
    3335
    34 static bool runner(stopwatch_t *stopwatch, uint64_t niter,
    35     char *error, size_t error_size)
     36#define MIN_DURATION_SECS  10
     37#define NUM_SAMPLES 10
     38
     39static errno_t malloc2_measure(uint64_t niter, uint64_t *rduration)
    3640{
    37         stopwatch_start(stopwatch);
     41        struct timespec start;
     42        uint64_t count;
     43        void **p;
    3844
    39         void **p = malloc(niter * sizeof(void *));
    40         if (p == NULL) {
    41                 snprintf(error, error_size,
    42                     "failed to allocate backend array (%" PRIu64 "B)",
    43                     niter * sizeof(void *));
    44                 return false;
     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;
    4555        }
    4656
    47         for (uint64_t count = 0; count < niter; count++) {
    48                 p[count] = malloc(1);
    49                 if (p[count] == NULL) {
    50                         snprintf(error, error_size,
    51                             "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
    52                             count, niter);
    53                         for (uint64_t j = 0; j < count; j++) {
    54                                 free(p[j]);
    55                         }
    56                         free(p);
    57                         return false;
    58                 }
    59         }
    60 
    61         for (uint64_t count = 0; count < niter; count++)
     57        for (count = 0; count < niter; count++)
    6258                free(p[count]);
    6359
    6460        free(p);
    6561
    66         stopwatch_stop(stopwatch);
     62        struct timespec now;
     63        getuptime(&now);
    6764
    68         return true;
     65        *rduration = ts_sub_diff(&now, &start) / 1000;
     66        return EOK;
    6967}
    7068
    71 benchmark_t bench_malloc2 = {
    72         .name = "malloc2",
    73         .desc = "User-space memory allocator benchmark, allocate many small blocks",
    74         .entry = &runner,
    75         .setup = NULL,
    76         .teardown = NULL
    77 };
     69static 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
     81const 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;
     144error:
     145        return msg;
     146}
  • uspace/app/perf/perf.c

    rb9f1585 r7acd787  
    11/*
    22 * Copyright (c) 2018 Jiri Svoboda
    3  * Copyright (c) 2018 Vojtech Horky
    43 * All rights reserved.
    54 *
     
    3534 */
    3635
    37 #include <assert.h>
    38 #include <math.h>
    3936#include <stdio.h>
    4037#include <stddef.h>
    4138#include <stdlib.h>
    4239#include <str.h>
    43 #include <time.h>
    44 #include <errno.h>
    45 #include <perf.h>
    46 #include <types/casting.h>
    4740#include "perf.h"
    48 #include "benchlist.h"
    4941
    50 #define MIN_DURATION_SECS 10
    51 #define NUM_SAMPLES 10
    52 #define MAX_ERROR_STR_LENGTH 1024
    53 
    54 static void short_report(stopwatch_t *stopwatch, int run_index,
    55     benchmark_t *bench, uint64_t workload_size)
    56 {
    57         usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(stopwatch));
    58 
    59         printf("Completed %" PRIu64 " operations in %llu us",
    60             workload_size, duration_usec);
    61         if (duration_usec > 0) {
    62                 double nanos = stopwatch_get_nanos(stopwatch);
    63                 double thruput = (double) workload_size / (nanos / 1000000000.0l);
    64                 printf(", %.0f ops/s.\n", thruput);
    65         } else {
    66                 printf(".\n");
    67         }
    68 }
    69 
    70 /*
    71  * This is a temporary solution until we have proper sqrt() implementation
    72  * in libmath.
    73  *
    74  * The algorithm uses Babylonian method [1].
    75  *
    76  * [1] https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
    77  */
    78 static double estimate_square_root(double value, double precision)
    79 {
    80         double estimate = 1.;
    81         double prev_estimate = estimate + 10 * precision;
    82 
    83         while (fabs(estimate - prev_estimate) > precision) {
    84                 prev_estimate = estimate;
    85                 estimate = (prev_estimate + value / prev_estimate) / 2.;
    86         }
    87 
    88         return estimate;
    89 }
    90 
    91 /*
    92  * Compute available statistics from given stopwatches.
    93  *
    94  * We compute normal mean for average duration of the workload and geometric
    95  * mean for average thruput. Note that geometric mean is necessary to compute
    96  * average throughput correctly - consider the following example:
    97  *  - we run always 60 operations,
    98  *  - first run executes in 30 s (i.e. 2 ops/s)
    99  *  - and second one in 10 s (6 ops/s).
    100  * Then, naively, average throughput would be (2+6)/2 = 4 [ops/s]. However, we
    101  * actually executed 60 + 60 ops in 30 + 10 seconds. So the actual average
    102  * throughput is 3 ops/s (which is exactly what geometric mean means).
    103  *
    104  */
    105 static void compute_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
    106     uint64_t workload_size, double precision, double *out_duration_avg,
    107     double *out_duration_sigma, double *out_thruput_avg)
    108 {
    109         double inv_thruput_sum = 0.0;
    110         double nanos_sum = 0.0;
    111         double nanos_sum2 = 0.0;
    112 
    113         for (size_t i = 0; i < stopwatch_count; i++) {
    114                 double nanos = stopwatch_get_nanos(&stopwatch[i]);
    115                 double thruput = (double) workload_size / nanos;
    116 
    117                 inv_thruput_sum += 1.0 / thruput;
    118                 nanos_sum += nanos;
    119                 nanos_sum2 += nanos * nanos;
    120         }
    121         *out_duration_avg = nanos_sum / stopwatch_count;
    122         double sigma2 = (nanos_sum2 - nanos_sum * (*out_duration_avg)) /
    123             ((double) stopwatch_count - 1);
    124         // FIXME: implement sqrt properly
    125         *out_duration_sigma = estimate_square_root(sigma2, precision);
    126         *out_thruput_avg = 1.0 / (inv_thruput_sum / stopwatch_count);
    127 }
    128 
    129 static void summary_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
    130     benchmark_t *bench, uint64_t workload_size)
    131 {
    132         double duration_avg, duration_sigma, thruput_avg;
    133         compute_stats(stopwatch, stopwatch_count, workload_size, 0.001,
    134             &duration_avg, &duration_sigma, &thruput_avg);
    135 
    136         printf("Average: %" PRIu64 " ops in %.0f us (sd %.0f us); "
    137             "%.0f ops/s; Samples: %zu\n",
    138             workload_size, duration_avg / 1000.0, duration_sigma / 1000.0,
    139             thruput_avg * 1000000000.0, stopwatch_count);
    140 }
     42benchmark_t benchmarks[] = {
     43#include "ipc/ns_ping.def"
     44#include "ipc/ping_pong.def"
     45#include "malloc/malloc1.def"
     46#include "malloc/malloc2.def"
     47        { NULL, NULL, NULL }
     48};
    14149
    14250static bool run_benchmark(benchmark_t *bench)
    14351{
    144         printf("Warm up and determine workload size...\n");
     52        /* Execute the benchmarl */
     53        const char *ret = bench->entry();
    14554
    146         char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1);
    147         if (error_msg == NULL) {
    148                 printf("Out of memory!\n");
    149                 return false;
    150         }
    151         str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "");
    152 
    153         bool ret = true;
    154 
    155         if (bench->setup != NULL) {
    156                 ret = bench->setup(error_msg, MAX_ERROR_STR_LENGTH);
    157                 if (!ret) {
    158                         goto leave_error;
    159                 }
     55        if (ret == NULL) {
     56                printf("\nBenchmark completed\n");
     57                return true;
    16058        }
    16159
    162         /*
    163          * Find workload size that is big enough to last few seconds.
    164          * We also check that uint64_t is big enough.
    165          */
    166         uint64_t workload_size = 0;
    167         for (size_t bits = 0; bits <= 64; bits++) {
    168                 if (bits == 64) {
    169                         str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "Workload too small even for 1 << 63");
    170                         goto leave_error;
    171                 }
    172                 workload_size = ((uint64_t) 1) << bits;
    173 
    174                 stopwatch_t stopwatch = STOPWATCH_INITIALIZE_STATIC;
    175 
    176                 bool ok = bench->entry(&stopwatch, workload_size,
    177                     error_msg, MAX_ERROR_STR_LENGTH);
    178                 if (!ok) {
    179                         goto leave_error;
    180                 }
    181                 short_report(&stopwatch, -1, bench, workload_size);
    182 
    183                 nsec_t duration = stopwatch_get_nanos(&stopwatch);
    184                 if (duration > SEC2NSEC(MIN_DURATION_SECS)) {
    185                         break;
    186                 }
    187         }
    188 
    189         printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES);
    190 
    191         stopwatch_t *stopwatch = calloc(NUM_SAMPLES, sizeof(stopwatch_t));
    192         if (stopwatch == NULL) {
    193                 snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory");
    194                 goto leave_error;
    195         }
    196         for (int i = 0; i < NUM_SAMPLES; i++) {
    197                 stopwatch_init(&stopwatch[i]);
    198 
    199                 bool ok = bench->entry(&stopwatch[i], workload_size,
    200                     error_msg, MAX_ERROR_STR_LENGTH);
    201                 if (!ok) {
    202                         free(stopwatch);
    203                         goto leave_error;
    204                 }
    205                 short_report(&stopwatch[i], i, bench, workload_size);
    206         }
    207 
    208         summary_stats(stopwatch, NUM_SAMPLES, bench, workload_size);
    209         printf("\nBenchmark completed\n");
    210 
    211         free(stopwatch);
    212 
    213         goto leave;
    214 
    215 leave_error:
    216         printf("Error: %s\n", error_msg);
    217         ret = false;
    218 
    219 leave:
    220         if (bench->teardown != NULL) {
    221                 bool ok = bench->teardown(error_msg, MAX_ERROR_STR_LENGTH);
    222                 if (!ok) {
    223                         printf("Error: %s\n", error_msg);
    224                         ret = false;
    225                 }
    226         }
    227 
    228         free(error_msg);
    229 
    230         return ret;
     60        printf("\n%s\n", ret);
     61        return false;
    23162}
    23263
    23364static int run_benchmarks(void)
    23465{
    235         unsigned int count_ok = 0;
    236         unsigned int count_fail = 0;
     66        benchmark_t *bench;
     67        unsigned int i = 0;
     68        unsigned int n = 0;
    23769
    23870        char *failed_names = NULL;
     
    24072        printf("\n*** Running all benchmarks ***\n\n");
    24173
    242         for (size_t it = 0; it < benchmark_count; it++) {
    243                 printf("%s (%s)\n", benchmarks[it]->name, benchmarks[it]->desc);
    244                 if (run_benchmark(benchmarks[it])) {
    245                         count_ok++;
     74        for (bench = benchmarks; bench->name != NULL; bench++) {
     75                printf("%s (%s)\n", bench->name, bench->desc);
     76                if (run_benchmark(bench)) {
     77                        i++;
    24678                        continue;
    24779                }
    24880
    24981                if (!failed_names) {
    250                         failed_names = str_dup(benchmarks[it]->name);
     82                        failed_names = str_dup(bench->name);
    25183                } else {
    25284                        char *f = NULL;
    253                         asprintf(&f, "%s, %s", failed_names, benchmarks[it]->name);
     85                        asprintf(&f, "%s, %s", failed_names, bench->name);
    25486                        if (!f) {
    25587                                printf("Out of memory.\n");
     
    25991                        failed_names = f;
    26092                }
    261                 count_fail++;
     93                n++;
    26294        }
    26395
    264         printf("\nCompleted, %u benchmarks run, %u succeeded.\n",
    265             count_ok + count_fail, count_ok);
     96        printf("\nCompleted, %u benchmarks run, %u succeeded.\n", i + n, i);
    26697        if (failed_names)
    26798                printf("Failed benchmarks: %s\n", failed_names);
    26899
    269         return count_fail;
     100        return n;
    270101}
    271102
     
    273104{
    274105        size_t len = 0;
    275         for (size_t i = 0; i < benchmark_count; i++) {
    276                 size_t len_now = str_length(benchmarks[i]->name);
    277                 if (len_now > len)
    278                         len = len_now;
     106        benchmark_t *bench;
     107        for (bench = benchmarks; bench->name != NULL; bench++) {
     108                if (str_length(bench->name) > len)
     109                        len = str_length(bench->name);
    279110        }
    280111
    281         assert(can_cast_size_t_to_int(len) && "benchmark name length overflow");
     112        unsigned int _len = (unsigned int) len;
     113        if ((_len != len) || (((int) _len) < 0)) {
     114                printf("Command length overflow\n");
     115                return;
     116        }
    282117
    283         for (size_t i = 0; i < benchmark_count; i++)
    284                 printf("%-*s %s\n", (int) len, benchmarks[i]->name, benchmarks[i]->desc);
     118        for (bench = benchmarks; bench->name != NULL; bench++)
     119                printf("%-*s %s\n", _len, bench->name, bench->desc);
    285120
    286         printf("%-*s Run all benchmarks\n", (int) len, "*");
     121        printf("%-*s Run all benchmarks\n", _len, "*");
    287122}
    288123
     
    300135        }
    301136
    302         for (size_t i = 0; i < benchmark_count; i++) {
    303                 if (str_cmp(argv[1], benchmarks[i]->name) == 0) {
    304                         return (run_benchmark(benchmarks[i]) ? 0 : -1);
     137        benchmark_t *bench;
     138        for (bench = benchmarks; bench->name != NULL; bench++) {
     139                if (str_cmp(argv[1], bench->name) == 0) {
     140                        return (run_benchmark(bench) ? 0 : -1);
    305141                }
    306142        }
  • uspace/app/perf/perf.h

    rb9f1585 r7acd787  
    3737
    3838#include <stdbool.h>
    39 #include <perf.h>
    4039
    41 typedef bool (*benchmark_entry_t)(stopwatch_t *, uint64_t,
    42     char *, size_t);
    43 typedef bool (*benchmark_helper_t)(char *, size_t);
     40typedef const char *(*benchmark_entry_t)(void);
    4441
    4542typedef struct {
     
    4744        const char *desc;
    4845        benchmark_entry_t entry;
    49         benchmark_helper_t setup;
    50         benchmark_helper_t teardown;
    5146} benchmark_t;
     47
     48extern const char *bench_malloc1(void);
     49extern const char *bench_malloc2(void);
     50extern const char *bench_ns_ping(void);
     51extern const char *bench_ping_pong(void);
     52
     53extern benchmark_t benchmarks[];
    5254
    5355#endif
  • uspace/app/tester/tester.c

    rb9f1585 r7acd787  
    3535 */
    3636
    37 #include <assert.h>
    3837#include <stdio.h>
    3938#include <stddef.h>
     
    4140#include <str.h>
    4241#include <io/log.h>
    43 #include <types/casting.h>
    4442#include "tester.h"
    4543
     
    146144        }
    147145
    148         assert(can_cast_size_t_to_int(len) && "test name length overflow");
     146        unsigned int _len = (unsigned int) len;
     147        if ((_len != len) || (((int) _len) < 0)) {
     148                printf("Command length overflow\n");
     149                return;
     150        }
    149151
    150152        for (test = tests; test->name != NULL; test++)
    151                 printf("%-*s %s%s\n", (int) len, test->name, test->desc,
     153                printf("%-*s %s%s\n", _len, test->name, test->desc,
    152154                    (test->safe ? "" : " (unsafe)"));
    153155
    154         printf("%-*s Run all safe tests\n", (int) len, "*");
     156        printf("%-*s Run all safe tests\n", _len, "*");
    155157}
    156158
  • uspace/lib/c/Makefile

    rb9f1585 r7acd787  
    189189TEST_SOURCES = \
    190190        test/adt/circ_buf.c \
    191         test/casting.c \
    192191        test/fibril/timer.c \
    193192        test/main.c \
     
    197196        test/stdio/scanf.c \
    198197        test/odict.c \
    199         test/perf.c \
    200198        test/perm.c \
    201199        test/qsort.c \
  • uspace/lib/c/test/main.c

    rb9f1585 r7acd787  
    3232PCUT_INIT;
    3333
    34 PCUT_IMPORT(casting);
    3534PCUT_IMPORT(circ_buf);
    3635PCUT_IMPORT(fibril_timer);
     
    3837PCUT_IMPORT(mem);
    3938PCUT_IMPORT(odict);
    40 PCUT_IMPORT(perf);
    4139PCUT_IMPORT(perm);
    4240PCUT_IMPORT(qsort);
Note: See TracChangeset for help on using the changeset viewer.