Ignore:
File:
1 edited

Legend:

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

    rd5caf79 re131833c  
    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}
Note: See TracChangeset for help on using the changeset viewer.