Changeset 3bd74758 in mainline for uspace/app/perf/ipc/ping_pong.c


Ignore:
Timestamp:
2018-12-28T09:32:11Z (6 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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified 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 }
Note: See TracChangeset for help on using the changeset viewer.