Changeset 3bd74758 in mainline for uspace/app/perf/malloc/malloc2.c


Ignore:
Timestamp:
2018-12-28T09:32:11Z (5 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
  • uspace/app/perf/malloc/malloc2.c

    r8ee106b r3bd74758  
    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>
    3431#include "../perf.h"
    3532
    36 #define MIN_DURATION_SECS  10
    37 #define NUM_SAMPLES 10
     33bool bench_malloc2(stopwatch_t *stopwatch, uint64_t niter,
     34    char *error, size_t error_size)
     35{
     36        stopwatch_start(stopwatch);
    3837
    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;
     38        void **p = malloc(niter * sizeof(void *));
     39        if (p == NULL) {
     40                snprintf(error, error_size,
     41                    "failed to allocate backend array (%" PRIu64 "B)",
     42                    niter * sizeof(void *));
     43                return false;
    5544        }
    5645
    57         for (count = 0; count < niter; count++)
     46        for (uint64_t count = 0; count < niter; count++) {
     47                p[count] = malloc(1);
     48                if (p[count] == NULL) {
     49                        snprintf(error, error_size,
     50                            "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
     51                            count, niter);
     52                        for (uint64_t j = 0; j < count; j++) {
     53                                free(p[j]);
     54                        }
     55                        free(p);
     56                        return false;
     57                }
     58        }
     59
     60        for (uint64_t count = 0; count < niter; count++)
    5861                free(p[count]);
    5962
    6063        free(p);
    6164
    62         struct timespec now;
    63         getuptime(&now);
     65        stopwatch_stop(stopwatch);
    6466
    65         *rduration = ts_sub_diff(&now, &start) / 1000;
    66         return EOK;
     67        return true;
    6768}
    68 
    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 }
Note: See TracChangeset for help on using the changeset viewer.