Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/perf/malloc/malloc2.c

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