Ignore:
File:
1 edited

Legend:

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

    re131833c rd5caf79  
    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>
     31#include "../benchlist.h"
    3432#include "../perf.h"
    3533
    36 #define MIN_DURATION_SECS  10
    37 #define NUM_SAMPLES 10
     34static bool runner(stopwatch_t *stopwatch, uint64_t niter,
     35    char *error, size_t error_size)
     36{
     37        stopwatch_start(stopwatch);
    3838
    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;
     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;
    5545        }
    5646
    57         for (count = 0; count < niter; count++)
     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++)
    5862                free(p[count]);
    5963
    6064        free(p);
    6165
    62         struct timespec now;
    63         getuptime(&now);
     66        stopwatch_stop(stopwatch);
    6467
    65         *rduration = ts_sub_diff(&now, &start) / 1000;
    66         return EOK;
     68        return true;
    6769}
    6870
    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 }
     71benchmark_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};
Note: See TracChangeset for help on using the changeset viewer.