aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrii Nakryiko <andriin@fb.com>2019-02-28 18:31:23 -0500
committerDaniel Borkmann <daniel@iogearbox.net>2019-02-28 19:31:47 -0500
commit51edf5f6e015c48b62e24ab2fbcad8885ca1c74e (patch)
treef62542a11348c36a6e3ef331659a7d17f0e6806c
parent1baabdc1089eb807cdcabebad50b36c8b9895a48 (diff)
btf: allow to customize dedup hash table size
Default size of dedup table (16k) is good enough for most binaries, even typical vmlinux images. But there are cases of binaries with huge amount of BTF types (e.g., allyesconfig variants of kernel), which benefit from having bigger dedup table size to lower amount of unnecessary hash collisions. Tools like pahole, thus, can tune this parameter to reach optimal performance. This change also serves double purpose of allowing tests to force hash collisions to test some corner cases, used in follow up patch. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--tools/lib/bpf/btf.c53
-rw-r--r--tools/lib/bpf/btf.h1
2 files changed, 37 insertions, 17 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 00a2f06e38fd..820f7fc8ebcc 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -1070,8 +1070,8 @@ done:
1070 return err; 1070 return err;
1071} 1071}
1072 1072
1073#define BTF_DEDUP_TABLE_SIZE_LOG 14 1073#define BTF_DEDUP_TABLE_DEFAULT_SIZE (1 << 14)
1074#define BTF_DEDUP_TABLE_MOD ((1 << BTF_DEDUP_TABLE_SIZE_LOG) - 1) 1074#define BTF_DEDUP_TABLE_MAX_SIZE_LOG 31
1075#define BTF_UNPROCESSED_ID ((__u32)-1) 1075#define BTF_UNPROCESSED_ID ((__u32)-1)
1076#define BTF_IN_PROGRESS_ID ((__u32)-2) 1076#define BTF_IN_PROGRESS_ID ((__u32)-2)
1077 1077
@@ -1128,18 +1128,21 @@ static inline __u32 hash_combine(__u32 h, __u32 value)
1128#undef GOLDEN_RATIO_PRIME 1128#undef GOLDEN_RATIO_PRIME
1129} 1129}
1130 1130
1131#define for_each_hash_node(table, hash, node) \ 1131#define for_each_dedup_cand(d, hash, node) \
1132 for (node = table[hash & BTF_DEDUP_TABLE_MOD]; node; node = node->next) 1132 for (node = d->dedup_table[hash & (d->opts.dedup_table_size - 1)]; \
1133 node; \
1134 node = node->next)
1133 1135
1134static int btf_dedup_table_add(struct btf_dedup *d, __u32 hash, __u32 type_id) 1136static int btf_dedup_table_add(struct btf_dedup *d, __u32 hash, __u32 type_id)
1135{ 1137{
1136 struct btf_dedup_node *node = malloc(sizeof(struct btf_dedup_node)); 1138 struct btf_dedup_node *node = malloc(sizeof(struct btf_dedup_node));
1139 int bucket = hash & (d->opts.dedup_table_size - 1);
1137 1140
1138 if (!node) 1141 if (!node)
1139 return -ENOMEM; 1142 return -ENOMEM;
1140 node->type_id = type_id; 1143 node->type_id = type_id;
1141 node->next = d->dedup_table[hash & BTF_DEDUP_TABLE_MOD]; 1144 node->next = d->dedup_table[bucket];
1142 d->dedup_table[hash & BTF_DEDUP_TABLE_MOD] = node; 1145 d->dedup_table[bucket] = node;
1143 return 0; 1146 return 0;
1144} 1147}
1145 1148
@@ -1177,7 +1180,7 @@ static void btf_dedup_table_free(struct btf_dedup *d)
1177 if (!d->dedup_table) 1180 if (!d->dedup_table)
1178 return; 1181 return;
1179 1182
1180 for (i = 0; i < (1 << BTF_DEDUP_TABLE_SIZE_LOG); i++) { 1183 for (i = 0; i < d->opts.dedup_table_size; i++) {
1181 while (d->dedup_table[i]) { 1184 while (d->dedup_table[i]) {
1182 tmp = d->dedup_table[i]; 1185 tmp = d->dedup_table[i];
1183 d->dedup_table[i] = tmp->next; 1186 d->dedup_table[i] = tmp->next;
@@ -1212,19 +1215,37 @@ static void btf_dedup_free(struct btf_dedup *d)
1212 free(d); 1215 free(d);
1213} 1216}
1214 1217
1218/* Find closest power of two >= to size, capped at 2^max_size_log */
1219static __u32 roundup_pow2_max(__u32 size, int max_size_log)
1220{
1221 int i;
1222
1223 for (i = 0; i < max_size_log && (1U << i) < size; i++)
1224 ;
1225 return 1U << i;
1226}
1227
1228
1215static struct btf_dedup *btf_dedup_new(struct btf *btf, struct btf_ext *btf_ext, 1229static struct btf_dedup *btf_dedup_new(struct btf *btf, struct btf_ext *btf_ext,
1216 const struct btf_dedup_opts *opts) 1230 const struct btf_dedup_opts *opts)
1217{ 1231{
1218 struct btf_dedup *d = calloc(1, sizeof(struct btf_dedup)); 1232 struct btf_dedup *d = calloc(1, sizeof(struct btf_dedup));
1219 int i, err = 0; 1233 int i, err = 0;
1234 __u32 sz;
1220 1235
1221 if (!d) 1236 if (!d)
1222 return ERR_PTR(-ENOMEM); 1237 return ERR_PTR(-ENOMEM);
1223 1238
1239 d->opts.dont_resolve_fwds = opts && opts->dont_resolve_fwds;
1240 sz = opts && opts->dedup_table_size ? opts->dedup_table_size
1241 : BTF_DEDUP_TABLE_DEFAULT_SIZE;
1242 sz = roundup_pow2_max(sz, BTF_DEDUP_TABLE_MAX_SIZE_LOG);
1243 d->opts.dedup_table_size = sz;
1244
1224 d->btf = btf; 1245 d->btf = btf;
1225 d->btf_ext = btf_ext; 1246 d->btf_ext = btf_ext;
1226 1247
1227 d->dedup_table = calloc(1 << BTF_DEDUP_TABLE_SIZE_LOG, 1248 d->dedup_table = calloc(d->opts.dedup_table_size,
1228 sizeof(struct btf_dedup_node *)); 1249 sizeof(struct btf_dedup_node *));
1229 if (!d->dedup_table) { 1250 if (!d->dedup_table) {
1230 err = -ENOMEM; 1251 err = -ENOMEM;
@@ -1249,8 +1270,6 @@ static struct btf_dedup *btf_dedup_new(struct btf *btf, struct btf_ext *btf_ext,
1249 for (i = 0; i <= btf->nr_types; i++) 1270 for (i = 0; i <= btf->nr_types; i++)
1250 d->hypot_map[i] = BTF_UNPROCESSED_ID; 1271 d->hypot_map[i] = BTF_UNPROCESSED_ID;
1251 1272
1252 d->opts.dont_resolve_fwds = opts && opts->dont_resolve_fwds;
1253
1254done: 1273done:
1255 if (err) { 1274 if (err) {
1256 btf_dedup_free(d); 1275 btf_dedup_free(d);
@@ -1824,7 +1843,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1824 1843
1825 case BTF_KIND_INT: 1844 case BTF_KIND_INT:
1826 h = btf_hash_int(t); 1845 h = btf_hash_int(t);
1827 for_each_hash_node(d->dedup_table, h, cand_node) { 1846 for_each_dedup_cand(d, h, cand_node) {
1828 cand = d->btf->types[cand_node->type_id]; 1847 cand = d->btf->types[cand_node->type_id];
1829 if (btf_equal_int(t, cand)) { 1848 if (btf_equal_int(t, cand)) {
1830 new_id = cand_node->type_id; 1849 new_id = cand_node->type_id;
@@ -1835,7 +1854,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1835 1854
1836 case BTF_KIND_ENUM: 1855 case BTF_KIND_ENUM:
1837 h = btf_hash_enum(t); 1856 h = btf_hash_enum(t);
1838 for_each_hash_node(d->dedup_table, h, cand_node) { 1857 for_each_dedup_cand(d, h, cand_node) {
1839 cand = d->btf->types[cand_node->type_id]; 1858 cand = d->btf->types[cand_node->type_id];
1840 if (btf_equal_enum(t, cand)) { 1859 if (btf_equal_enum(t, cand)) {
1841 new_id = cand_node->type_id; 1860 new_id = cand_node->type_id;
@@ -1846,7 +1865,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1846 1865
1847 case BTF_KIND_FWD: 1866 case BTF_KIND_FWD:
1848 h = btf_hash_common(t); 1867 h = btf_hash_common(t);
1849 for_each_hash_node(d->dedup_table, h, cand_node) { 1868 for_each_dedup_cand(d, h, cand_node) {
1850 cand = d->btf->types[cand_node->type_id]; 1869 cand = d->btf->types[cand_node->type_id];
1851 if (btf_equal_common(t, cand)) { 1870 if (btf_equal_common(t, cand)) {
1852 new_id = cand_node->type_id; 1871 new_id = cand_node->type_id;
@@ -2263,7 +2282,7 @@ static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id)
2263 return 0; 2282 return 0;
2264 2283
2265 h = btf_hash_struct(t); 2284 h = btf_hash_struct(t);
2266 for_each_hash_node(d->dedup_table, h, cand_node) { 2285 for_each_dedup_cand(d, h, cand_node) {
2267 int eq; 2286 int eq;
2268 2287
2269 btf_dedup_clear_hypot_map(d); 2288 btf_dedup_clear_hypot_map(d);
@@ -2350,7 +2369,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
2350 t->type = ref_type_id; 2369 t->type = ref_type_id;
2351 2370
2352 h = btf_hash_common(t); 2371 h = btf_hash_common(t);
2353 for_each_hash_node(d->dedup_table, h, cand_node) { 2372 for_each_dedup_cand(d, h, cand_node) {
2354 cand = d->btf->types[cand_node->type_id]; 2373 cand = d->btf->types[cand_node->type_id];
2355 if (btf_equal_common(t, cand)) { 2374 if (btf_equal_common(t, cand)) {
2356 new_id = cand_node->type_id; 2375 new_id = cand_node->type_id;
@@ -2373,7 +2392,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
2373 info->index_type = ref_type_id; 2392 info->index_type = ref_type_id;
2374 2393
2375 h = btf_hash_array(t); 2394 h = btf_hash_array(t);
2376 for_each_hash_node(d->dedup_table, h, cand_node) { 2395 for_each_dedup_cand(d, h, cand_node) {
2377 cand = d->btf->types[cand_node->type_id]; 2396 cand = d->btf->types[cand_node->type_id];
2378 if (btf_equal_array(t, cand)) { 2397 if (btf_equal_array(t, cand)) {
2379 new_id = cand_node->type_id; 2398 new_id = cand_node->type_id;
@@ -2404,7 +2423,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
2404 } 2423 }
2405 2424
2406 h = btf_hash_fnproto(t); 2425 h = btf_hash_fnproto(t);
2407 for_each_hash_node(d->dedup_table, h, cand_node) { 2426 for_each_dedup_cand(d, h, cand_node) {
2408 cand = d->btf->types[cand_node->type_id]; 2427 cand = d->btf->types[cand_node->type_id];
2409 if (btf_equal_fnproto(t, cand)) { 2428 if (btf_equal_fnproto(t, cand)) {
2410 new_id = cand_node->type_id; 2429 new_id = cand_node->type_id;
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index b60bb7cf5fff..28a1e1e59861 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -90,6 +90,7 @@ LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
90LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext); 90LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
91 91
92struct btf_dedup_opts { 92struct btf_dedup_opts {
93 unsigned int dedup_table_size;
93 bool dont_resolve_fwds; 94 bool dont_resolve_fwds;
94}; 95};
95 96