linux/samples/bpf/map_perf_test_user.c
<<
>>
Prefs
   1/* Copyright (c) 2016 Facebook
   2 *
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of version 2 of the GNU General Public
   5 * License as published by the Free Software Foundation.
   6 */
   7#define _GNU_SOURCE
   8#include <sched.h>
   9#include <stdio.h>
  10#include <sys/types.h>
  11#include <asm/unistd.h>
  12#include <unistd.h>
  13#include <assert.h>
  14#include <sys/wait.h>
  15#include <stdlib.h>
  16#include <signal.h>
  17#include <linux/bpf.h>
  18#include <string.h>
  19#include <time.h>
  20#include <sys/resource.h>
  21#include "libbpf.h"
  22#include "bpf_load.h"
  23
  24#define MAX_CNT 1000000
  25
  26static __u64 time_get_ns(void)
  27{
  28        struct timespec ts;
  29
  30        clock_gettime(CLOCK_MONOTONIC, &ts);
  31        return ts.tv_sec * 1000000000ull + ts.tv_nsec;
  32}
  33
  34#define HASH_PREALLOC           (1 << 0)
  35#define PERCPU_HASH_PREALLOC    (1 << 1)
  36#define HASH_KMALLOC            (1 << 2)
  37#define PERCPU_HASH_KMALLOC     (1 << 3)
  38
  39static int test_flags = ~0;
  40
  41static void test_hash_prealloc(int cpu)
  42{
  43        __u64 start_time;
  44        int i;
  45
  46        start_time = time_get_ns();
  47        for (i = 0; i < MAX_CNT; i++)
  48                syscall(__NR_getuid);
  49        printf("%d:hash_map_perf pre-alloc %lld events per sec\n",
  50               cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
  51}
  52
  53static void test_percpu_hash_prealloc(int cpu)
  54{
  55        __u64 start_time;
  56        int i;
  57
  58        start_time = time_get_ns();
  59        for (i = 0; i < MAX_CNT; i++)
  60                syscall(__NR_geteuid);
  61        printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n",
  62               cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
  63}
  64
  65static void test_hash_kmalloc(int cpu)
  66{
  67        __u64 start_time;
  68        int i;
  69
  70        start_time = time_get_ns();
  71        for (i = 0; i < MAX_CNT; i++)
  72                syscall(__NR_getgid);
  73        printf("%d:hash_map_perf kmalloc %lld events per sec\n",
  74               cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
  75}
  76
  77static void test_percpu_hash_kmalloc(int cpu)
  78{
  79        __u64 start_time;
  80        int i;
  81
  82        start_time = time_get_ns();
  83        for (i = 0; i < MAX_CNT; i++)
  84                syscall(__NR_getegid);
  85        printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n",
  86               cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
  87}
  88
  89static void loop(int cpu)
  90{
  91        cpu_set_t cpuset;
  92
  93        CPU_ZERO(&cpuset);
  94        CPU_SET(cpu, &cpuset);
  95        sched_setaffinity(0, sizeof(cpuset), &cpuset);
  96
  97        if (test_flags & HASH_PREALLOC)
  98                test_hash_prealloc(cpu);
  99
 100        if (test_flags & PERCPU_HASH_PREALLOC)
 101                test_percpu_hash_prealloc(cpu);
 102
 103        if (test_flags & HASH_KMALLOC)
 104                test_hash_kmalloc(cpu);
 105
 106        if (test_flags & PERCPU_HASH_KMALLOC)
 107                test_percpu_hash_kmalloc(cpu);
 108}
 109
 110static void run_perf_test(int tasks)
 111{
 112        pid_t pid[tasks];
 113        int i;
 114
 115        for (i = 0; i < tasks; i++) {
 116                pid[i] = fork();
 117                if (pid[i] == 0) {
 118                        loop(i);
 119                        exit(0);
 120                } else if (pid[i] == -1) {
 121                        printf("couldn't spawn #%d process\n", i);
 122                        exit(1);
 123                }
 124        }
 125        for (i = 0; i < tasks; i++) {
 126                int status;
 127
 128                assert(waitpid(pid[i], &status, 0) == pid[i]);
 129                assert(status == 0);
 130        }
 131}
 132
 133int main(int argc, char **argv)
 134{
 135        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
 136        char filename[256];
 137        int num_cpu = 8;
 138
 139        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 140        setrlimit(RLIMIT_MEMLOCK, &r);
 141
 142        if (argc > 1)
 143                test_flags = atoi(argv[1]) ? : test_flags;
 144
 145        if (argc > 2)
 146                num_cpu = atoi(argv[2]) ? : num_cpu;
 147
 148        if (load_bpf_file(filename)) {
 149                printf("%s", bpf_log_buf);
 150                return 1;
 151        }
 152
 153        run_perf_test(num_cpu);
 154
 155        return 0;
 156}
 157