^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2016 Facebook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sys/resource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <bpf/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "bpf_util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define min(a, b) ((a) < (b) ? (a) : (b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #ifndef offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) # define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define container_of(ptr, type, member) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) const typeof( ((type *)0)->member ) *__mptr = (ptr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) (type *)( (char *)__mptr - offsetof(type,member) );})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int nr_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static unsigned long long *dist_keys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static unsigned int dist_key_counts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct list_head {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct list_head *next, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline void INIT_LIST_HEAD(struct list_head *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) list->next = list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) list->prev = list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static inline int list_empty(const struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return head->next == head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static inline void __list_add(struct list_head *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct list_head *prev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct list_head *next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) next->prev = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) new->next = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) new->prev = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) prev->next = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline void list_add(struct list_head *new, struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) __list_add(new, head, head->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static inline void __list_del(struct list_head *prev, struct list_head *next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) next->prev = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) prev->next = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static inline void __list_del_entry(struct list_head *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) __list_del(entry->prev, entry->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static inline void list_move(struct list_head *list, struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) __list_del_entry(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) list_add(list, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define list_entry(ptr, type, member) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) container_of(ptr, type, member)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define list_last_entry(ptr, type, member) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) list_entry((ptr)->prev, type, member)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct pfect_lru_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned long long key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct pfect_lru {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct pfect_lru_node *free_nodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int cur_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned int lru_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned int nr_unique;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned int nr_misses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void pfect_lru_init(struct pfect_lru *lru, unsigned int lru_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int nr_possible_elems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) lru->map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) sizeof(unsigned long long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) sizeof(struct pfect_lru_node *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) nr_possible_elems, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) assert(lru->map_fd != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) lru->free_nodes = malloc(lru_size * sizeof(struct pfect_lru_node));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) assert(lru->free_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) INIT_LIST_HEAD(&lru->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) lru->cur_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) lru->lru_size = lru_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) lru->nr_unique = lru->nr_misses = lru->total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void pfect_lru_destroy(struct pfect_lru *lru)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) close(lru->map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) free(lru->free_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int pfect_lru_lookup_or_insert(struct pfect_lru *lru,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) unsigned long long key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct pfect_lru_node *node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int seen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) lru->total++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!bpf_map_lookup_elem(lru->map_fd, &key, &node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) list_move(&node->list, &lru->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) seen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (lru->cur_size < lru->lru_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) node = &lru->free_nodes[lru->cur_size++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) INIT_LIST_HEAD(&node->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct pfect_lru_node *null_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) node = list_last_entry(&lru->list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct pfect_lru_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bpf_map_update_elem(lru->map_fd, &node->key, &null_node, BPF_EXIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) node->key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) list_move(&node->list, &lru->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) lru->nr_misses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (seen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) assert(!bpf_map_update_elem(lru->map_fd, &key, &node, BPF_EXIST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) lru->nr_unique++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) assert(!bpf_map_update_elem(lru->map_fd, &key, &node, BPF_NOEXIST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return seen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static unsigned int read_keys(const char *dist_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned long long **keys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct stat fst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned long long *retkeys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned int counts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int dist_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) char *b, *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dist_fd = open(dist_file, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) assert(dist_fd != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) assert(fstat(dist_fd, &fst) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) b = malloc(fst.st_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) assert(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) assert(read(dist_fd, b, fst.st_size) == fst.st_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) close(dist_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) for (i = 0; i < fst.st_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (b[i] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) counts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) counts++; /* in case the last line has no \n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) retkeys = malloc(counts * sizeof(unsigned long long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) assert(retkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) counts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) for (l = strtok(b, "\n"); l; l = strtok(NULL, "\n"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) retkeys[counts++] = strtoull(l, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) free(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *keys = retkeys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return counts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int create_map(int map_type, int map_flags, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) map_fd = bpf_create_map(map_type, sizeof(unsigned long long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) sizeof(unsigned long long), size, map_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (map_fd == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) perror("bpf_create_map");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int sched_next_online(int pid, int next_to_try)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cpu_set_t cpuset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (next_to_try == nr_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) while (next_to_try < nr_cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) CPU_ZERO(&cpuset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) CPU_SET(next_to_try++, &cpuset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return next_to_try;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static void run_parallel(unsigned int tasks, void (*fn)(int i, void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int next_sched_cpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) pid_t pid[tasks];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) for (i = 0; i < tasks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pid[i] = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (pid[i] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) next_sched_cpu = sched_next_online(0, next_sched_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) fn(i, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) } else if (pid[i] == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) printf("couldn't spawn #%d process\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* It is mostly redundant and just allow the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * process to update next_shced_cpu for the next child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) next_sched_cpu = sched_next_online(pid[i], next_sched_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (i = 0; i < tasks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) assert(waitpid(pid[i], &status, 0) == pid[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) assert(status == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static void do_test_lru_dist(int task, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) unsigned int nr_misses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct pfect_lru pfect_lru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) unsigned long long key, value = 1234;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) unsigned int lru_map_fd = ((unsigned int *)data)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) unsigned int lru_size = ((unsigned int *)data)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) unsigned long long key_offset = task * dist_key_counts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) pfect_lru_init(&pfect_lru, lru_size, dist_key_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) for (i = 0; i < dist_key_counts; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) key = dist_keys[i] + key_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) pfect_lru_lookup_or_insert(&pfect_lru, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!bpf_map_lookup_elem(lru_map_fd, &key, &value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (bpf_map_update_elem(lru_map_fd, &key, &value, BPF_NOEXIST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) printf("bpf_map_update_elem(lru_map_fd, %llu): errno:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) key, errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) assert(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) nr_misses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) printf(" task:%d BPF LRU: nr_unique:%u(/%u) nr_misses:%u(/%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) task, pfect_lru.nr_unique, dist_key_counts, nr_misses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dist_key_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) printf(" task:%d Perfect LRU: nr_unique:%u(/%u) nr_misses:%u(/%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) task, pfect_lru.nr_unique, pfect_lru.total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) pfect_lru.nr_misses, pfect_lru.total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) pfect_lru_destroy(&pfect_lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) close(lru_map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static void test_parallel_lru_dist(int map_type, int map_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int nr_tasks, unsigned int lru_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int child_data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int lru_map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) printf("%s (map_type:%d map_flags:0x%X):\n", __func__, map_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) map_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (map_flags & BPF_F_NO_COMMON_LRU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) lru_map_fd = create_map(map_type, map_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) nr_cpus * lru_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) lru_map_fd = create_map(map_type, map_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) nr_tasks * lru_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) assert(lru_map_fd != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) child_data[0] = lru_map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) child_data[1] = lru_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) run_parallel(nr_tasks, do_test_lru_dist, child_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) close(lru_map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void test_lru_loss0(int map_type, int map_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) unsigned long long key, value[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) unsigned int old_unused_losses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) unsigned int new_unused_losses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) unsigned int used_losses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) map_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) assert(sched_next_online(0, 0) != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (map_flags & BPF_F_NO_COMMON_LRU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) map_fd = create_map(map_type, map_flags, 900 * nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) map_fd = create_map(map_type, map_flags, 900);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) assert(map_fd != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) value[0] = 1234;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) for (key = 1; key <= 1000; key++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int start_key, end_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) assert(bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) start_key = 101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) end_key = min(key, 900);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) while (start_key <= end_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) bpf_map_lookup_elem(map_fd, &start_key, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) start_key++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) for (key = 1; key <= 1000; key++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (bpf_map_lookup_elem(map_fd, &key, value)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (key <= 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) old_unused_losses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) else if (key <= 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) used_losses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) new_unused_losses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) close(map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) printf("older-elem-losses:%d(/100) active-elem-losses:%d(/800) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) "newer-elem-losses:%d(/100)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) old_unused_losses, used_losses, new_unused_losses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void test_lru_loss1(int map_type, int map_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) unsigned long long key, value[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) unsigned int nr_losses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) map_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) assert(sched_next_online(0, 0) != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (map_flags & BPF_F_NO_COMMON_LRU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) map_fd = create_map(map_type, map_flags, 1000 * nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) map_fd = create_map(map_type, map_flags, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) assert(map_fd != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) value[0] = 1234;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) for (key = 1; key <= 1000; key++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) for (key = 1; key <= 1000; key++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (bpf_map_lookup_elem(map_fd, &key, value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) nr_losses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) close(map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) printf("nr_losses:%d(/1000)\n", nr_losses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static void do_test_parallel_lru_loss(int task, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) const unsigned int nr_stable_elems = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) const unsigned int nr_repeats = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int map_fd = *(int *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned long long stable_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) unsigned long long key, value[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned long long next_ins_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) unsigned int nr_losses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) stable_base = task * nr_repeats * 2 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) next_ins_key = stable_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) value[0] = 1234;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) for (i = 0; i < nr_stable_elems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) assert(bpf_map_update_elem(map_fd, &next_ins_key, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) BPF_NOEXIST) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) next_ins_key++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) for (i = 0; i < nr_repeats; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) int rn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) rn = rand();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (rn % 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) key = rn % nr_stable_elems + stable_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) bpf_map_lookup_elem(map_fd, &key, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) bpf_map_update_elem(map_fd, &next_ins_key, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) BPF_NOEXIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) next_ins_key++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) key = stable_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) for (i = 0; i < nr_stable_elems; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (bpf_map_lookup_elem(map_fd, &key, value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) nr_losses++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) key++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) printf(" task:%d nr_losses:%u\n", task, nr_losses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void test_parallel_lru_loss(int map_type, int map_flags, int nr_tasks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) printf("%s (map_type:%d map_flags:0x%X):\n", __func__, map_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) map_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* Give 20% more than the active working set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (map_flags & BPF_F_NO_COMMON_LRU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) map_fd = create_map(map_type, map_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) nr_cpus * (1000 + 200));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) map_fd = create_map(map_type, map_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) nr_tasks * (1000 + 200));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) assert(map_fd != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) run_parallel(nr_tasks, do_test_parallel_lru_loss, &map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) close(map_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int map_flags[] = {0, BPF_F_NO_COMMON_LRU};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) const char *dist_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int nr_tasks = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int lru_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (argc < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) printf("Usage: %s <dist-file> <lru-size> <nr-tasks>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) dist_file = argv[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) lru_size = atoi(argv[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) nr_tasks = atoi(argv[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) setbuf(stdout, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) assert(!setrlimit(RLIMIT_MEMLOCK, &r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) srand(time(NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) nr_cpus = bpf_num_possible_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) assert(nr_cpus != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) printf("nr_cpus:%d\n\n", nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) nr_tasks = min(nr_tasks, nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) dist_key_counts = read_keys(dist_file, &dist_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (!dist_key_counts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) printf("%s has no key\n", dist_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) for (f = 0; f < sizeof(map_flags) / sizeof(*map_flags); f++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) test_lru_loss0(BPF_MAP_TYPE_LRU_HASH, map_flags[f]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) test_lru_loss1(BPF_MAP_TYPE_LRU_HASH, map_flags[f]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) test_parallel_lru_loss(BPF_MAP_TYPE_LRU_HASH, map_flags[f],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) nr_tasks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) test_parallel_lru_dist(BPF_MAP_TYPE_LRU_HASH, map_flags[f],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) nr_tasks, lru_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) free(dist_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }