akaros/tests/interference.c
<<
>>
Prefs
   1#include <stdint.h>
   2#include <stdlib.h>
   3
   4#ifdef __akaros__
   5
   6#include <parlib/stdio.h>
   7#include <parlib/uthread.h>
   8#include <parlib/timing.h>
   9#include <parlib/event.h>
  10#include <benchutil/measure.h>
  11
  12static void ev_handle_null(struct event_msg *ev_msg, unsigned int ev_type,
  13                           void *data)
  14{
  15}
  16
  17static void os_init(void)
  18{
  19        uthread_mcp_init();
  20        register_ev_handler(EV_FREE_APPLE_PIE, ev_handle_null, NULL);
  21}
  22
  23#else
  24
  25/* Build on linux from $AKAROS_ROOT:
  26 * gcc -static --std=gnu99 tests/interference.c -o lin-interference
  27 */
  28
  29#include <stdio.h>
  30#include "../user/parlib/include/parlib/tsc-compat.h"
  31#include "misc-compat.h"
  32
  33struct sample_stats {
  34        int (*get_sample)(void **data, int i, int j, uint64_t *sample);
  35        uint64_t                avg_time;
  36        uint64_t                var_time;
  37        uint64_t                max_time;
  38        uint64_t                min_time;
  39        unsigned int            lat_50;
  40        unsigned int            lat_75;
  41        unsigned int            lat_90;
  42        unsigned int            lat_99;
  43        uint64_t                total_samples;
  44};
  45
  46void compute_stats(void **data, int nr_i, int nr_j, struct sample_stats *stats)
  47{
  48        /* TODO: could try to link against benchutil. */
  49}
  50
  51static void os_init(void)
  52{
  53        printf("Linux: If you get a segfault, make sure rdpmc is allowed.\n"
  54               "Linux: Set /sys/bus/event_source/devices/cpu/rdpmc = 2 on recent kernels (4.0), or 1 for older kernels.\n");
  55}
  56
  57#endif
  58
  59static uint64_t *delays;
  60
  61static int get_delay(void **data, int i, int j, uint64_t *sample)
  62{
  63        uint64_t **delay_array = (uint64_t**)data;
  64
  65        *sample = delay_array[i][j];
  66        return 0;
  67}
  68
  69static inline __attribute__((always_inline))
  70uint64_t pmc_cycles(void)
  71{
  72        unsigned int a = 0, d = 0;
  73        int ecx = (1 << 30) + 1;
  74
  75        asm volatile("lfence; rdpmc" : "=a"(a), "=d"(d) : "c"(ecx));
  76        return ((uint64_t)a) | (((uint64_t)d) << 32);
  77}
  78
  79int main(int argc, char **argv)
  80{
  81        #define THRESHOLD 200
  82        uint64_t start, diff;
  83        struct sample_stats stats[1];
  84        size_t idx = 0;
  85        size_t nr_below_thresh = 0;
  86        size_t nr_over_thresh = 0;
  87        size_t total = 0;
  88        int pcoreid;
  89        uint64_t low_samples[THRESHOLD] = {0};
  90        int nr_samples = 1000;
  91        uint64_t deadline = sec2tsc(5); /* assumes TSC and cycles are close */
  92
  93        /* Normally we'd use a 2D array, but since we're just one thread, we
  94         * just need our first thread's array. */
  95        delays = malloc(sizeof(uint64_t) * nr_samples);
  96        os_init();
  97        pcoreid = get_pcoreid();
  98        udelay(1000);
  99        deadline += pmc_cycles();
 100
 101        do {
 102                if (idx >= nr_samples)
 103                        break;
 104                total++;
 105                start = pmc_cycles();
 106                diff = pmc_cycles() - start;
 107                if (diff < COUNT_OF(low_samples))
 108                        low_samples[diff]++;
 109                if (diff < THRESHOLD) {
 110                        nr_below_thresh++;
 111                } else {
 112                        nr_over_thresh++;
 113                        delays[idx++] = diff;
 114                }
 115                if (!start) {
 116                        printf("rdpmc got 0, is perf stat -e cycles running? (aborting)\n");
 117                        break;
 118                }
 119        } while (start < deadline);
 120
 121        printf("\n\nStats for interference\n");
 122        stats->get_sample = get_delay;
 123        compute_stats((void**)&delays, 1, idx, stats);
 124
 125        printf("\n\nStats for low rdtsc times (tsc ticks for two rdtscs)\n");
 126        for (int i = 0; i < COUNT_OF(low_samples); i++) {
 127                if (low_samples[i])
 128                        printf("\t[ %2d ] : %lu\n", i, low_samples[i]);
 129        }
 130
 131        printf("Pcoreid was %d (and is now %d)\n\n", pcoreid, get_pcoreid());
 132        printf("Total loops %lu, threshold %u\n", total, THRESHOLD);
 133        printf("Nr over thresh %lu (%f%% total)\n", nr_over_thresh,
 134               nr_over_thresh * 100.0 / total);
 135        printf("Nr below thresh %lu (%f%% total)\n", nr_below_thresh,
 136               nr_below_thresh * 100.0 / total);
 137        return 0;
 138}
 139