📄 slabinfo.c
字号:
int used_slabs = 0; char b1[20], b2[20], b3[20], b4[20]; unsigned long long max = 1ULL << 63; /* Object size */ unsigned long long min_objsize = max, max_objsize = 0, avg_objsize; /* Number of partial slabs in a slabcache */ unsigned long long min_partial = max, max_partial = 0, avg_partial, total_partial = 0; /* Number of slabs in a slab cache */ unsigned long long min_slabs = max, max_slabs = 0, avg_slabs, total_slabs = 0; /* Size of the whole slab */ unsigned long long min_size = max, max_size = 0, avg_size, total_size = 0; /* Bytes used for object storage in a slab */ unsigned long long min_used = max, max_used = 0, avg_used, total_used = 0; /* Waste: Bytes used for alignment and padding */ unsigned long long min_waste = max, max_waste = 0, avg_waste, total_waste = 0; /* Number of objects in a slab */ unsigned long long min_objects = max, max_objects = 0, avg_objects, total_objects = 0; /* Waste per object */ unsigned long long min_objwaste = max, max_objwaste = 0, avg_objwaste, total_objwaste = 0; /* Memory per object */ unsigned long long min_memobj = max, max_memobj = 0, avg_memobj, total_objsize = 0; /* Percentage of partial slabs per slab */ unsigned long min_ppart = 100, max_ppart = 0, avg_ppart, total_ppart = 0; /* Number of objects in partial slabs */ unsigned long min_partobj = max, max_partobj = 0, avg_partobj, total_partobj = 0; /* Percentage of partial objects of all objects in a slab */ unsigned long min_ppartobj = 100, max_ppartobj = 0, avg_ppartobj, total_ppartobj = 0; for (s = slabinfo; s < slabinfo + slabs; s++) { unsigned long long size; unsigned long used; unsigned long long wasted; unsigned long long objwaste; long long objects_in_partial_slabs; unsigned long percentage_partial_slabs; unsigned long percentage_partial_objs; if (!s->slabs || !s->objects) continue; used_slabs++; size = slab_size(s); used = s->objects * s->object_size; wasted = size - used; objwaste = s->slab_size - s->object_size; objects_in_partial_slabs = s->objects - (s->slabs - s->partial - s ->cpu_slabs) * s->objs_per_slab; if (objects_in_partial_slabs < 0) objects_in_partial_slabs = 0; percentage_partial_slabs = s->partial * 100 / s->slabs; if (percentage_partial_slabs > 100) percentage_partial_slabs = 100; percentage_partial_objs = objects_in_partial_slabs * 100 / s->objects; if (percentage_partial_objs > 100) percentage_partial_objs = 100; if (s->object_size < min_objsize) min_objsize = s->object_size; if (s->partial < min_partial) min_partial = s->partial; if (s->slabs < min_slabs) min_slabs = s->slabs; if (size < min_size) min_size = size; if (wasted < min_waste) min_waste = wasted; if (objwaste < min_objwaste) min_objwaste = objwaste; if (s->objects < min_objects) min_objects = s->objects; if (used < min_used) min_used = used; if (objects_in_partial_slabs < min_partobj) min_partobj = objects_in_partial_slabs; if (percentage_partial_slabs < min_ppart) min_ppart = percentage_partial_slabs; if (percentage_partial_objs < min_ppartobj) min_ppartobj = percentage_partial_objs; if (s->slab_size < min_memobj) min_memobj = s->slab_size; if (s->object_size > max_objsize) max_objsize = s->object_size; if (s->partial > max_partial) max_partial = s->partial; if (s->slabs > max_slabs) max_slabs = s->slabs; if (size > max_size) max_size = size; if (wasted > max_waste) max_waste = wasted; if (objwaste > max_objwaste) max_objwaste = objwaste; if (s->objects > max_objects) max_objects = s->objects; if (used > max_used) max_used = used; if (objects_in_partial_slabs > max_partobj) max_partobj = objects_in_partial_slabs; if (percentage_partial_slabs > max_ppart) max_ppart = percentage_partial_slabs; if (percentage_partial_objs > max_ppartobj) max_ppartobj = percentage_partial_objs; if (s->slab_size > max_memobj) max_memobj = s->slab_size; total_partial += s->partial; total_slabs += s->slabs; total_size += size; total_waste += wasted; total_objects += s->objects; total_used += used; total_partobj += objects_in_partial_slabs; total_ppart += percentage_partial_slabs; total_ppartobj += percentage_partial_objs; total_objwaste += s->objects * objwaste; total_objsize += s->objects * s->slab_size; } if (!total_objects) { printf("No objects\n"); return; } if (!used_slabs) { printf("No slabs\n"); return; } /* Per slab averages */ avg_partial = total_partial / used_slabs; avg_slabs = total_slabs / used_slabs; avg_size = total_size / used_slabs; avg_waste = total_waste / used_slabs; avg_objects = total_objects / used_slabs; avg_used = total_used / used_slabs; avg_partobj = total_partobj / used_slabs; avg_ppart = total_ppart / used_slabs; avg_ppartobj = total_ppartobj / used_slabs; /* Per object object sizes */ avg_objsize = total_used / total_objects; avg_objwaste = total_objwaste / total_objects; avg_partobj = total_partobj * 100 / total_objects; avg_memobj = total_objsize / total_objects; printf("Slabcache Totals\n"); printf("----------------\n"); printf("Slabcaches : %3d Aliases : %3d->%-3d Active: %3d\n", slabs, aliases, alias_targets, used_slabs); store_size(b1, total_size);store_size(b2, total_waste); store_size(b3, total_waste * 100 / total_used); printf("Memory used: %6s # Loss : %6s MRatio:%6s%%\n", b1, b2, b3); store_size(b1, total_objects);store_size(b2, total_partobj); store_size(b3, total_partobj * 100 / total_objects); printf("# Objects : %6s # PartObj: %6s ORatio:%6s%%\n", b1, b2, b3); printf("\n"); printf("Per Cache Average Min Max Total\n"); printf("---------------------------------------------------------\n"); store_size(b1, avg_objects);store_size(b2, min_objects); store_size(b3, max_objects);store_size(b4, total_objects); printf("#Objects %10s %10s %10s %10s\n", b1, b2, b3, b4); store_size(b1, avg_slabs);store_size(b2, min_slabs); store_size(b3, max_slabs);store_size(b4, total_slabs); printf("#Slabs %10s %10s %10s %10s\n", b1, b2, b3, b4); store_size(b1, avg_partial);store_size(b2, min_partial); store_size(b3, max_partial);store_size(b4, total_partial); printf("#PartSlab %10s %10s %10s %10s\n", b1, b2, b3, b4); store_size(b1, avg_ppart);store_size(b2, min_ppart); store_size(b3, max_ppart); store_size(b4, total_partial * 100 / total_slabs); printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n", b1, b2, b3, b4); store_size(b1, avg_partobj);store_size(b2, min_partobj); store_size(b3, max_partobj); store_size(b4, total_partobj); printf("PartObjs %10s %10s %10s %10s\n", b1, b2, b3, b4); store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj); store_size(b3, max_ppartobj); store_size(b4, total_partobj * 100 / total_objects); printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n", b1, b2, b3, b4); store_size(b1, avg_size);store_size(b2, min_size); store_size(b3, max_size);store_size(b4, total_size); printf("Memory %10s %10s %10s %10s\n", b1, b2, b3, b4); store_size(b1, avg_used);store_size(b2, min_used); store_size(b3, max_used);store_size(b4, total_used); printf("Used %10s %10s %10s %10s\n", b1, b2, b3, b4); store_size(b1, avg_waste);store_size(b2, min_waste); store_size(b3, max_waste);store_size(b4, total_waste); printf("Loss %10s %10s %10s %10s\n", b1, b2, b3, b4); printf("\n"); printf("Per Object Average Min Max\n"); printf("---------------------------------------------\n"); store_size(b1, avg_memobj);store_size(b2, min_memobj); store_size(b3, max_memobj); printf("Memory %10s %10s %10s\n", b1, b2, b3); store_size(b1, avg_objsize);store_size(b2, min_objsize); store_size(b3, max_objsize); printf("User %10s %10s %10s\n", b1, b2, b3); store_size(b1, avg_objwaste);store_size(b2, min_objwaste); store_size(b3, max_objwaste); printf("Loss %10s %10s %10s\n", b1, b2, b3);}void sort_slabs(void){ struct slabinfo *s1,*s2; for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) { for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) { int result; if (sort_size) result = slab_size(s1) < slab_size(s2); else result = strcasecmp(s1->name, s2->name); if (show_inverted) result = -result; if (result > 0) { struct slabinfo t; memcpy(&t, s1, sizeof(struct slabinfo)); memcpy(s1, s2, sizeof(struct slabinfo)); memcpy(s2, &t, sizeof(struct slabinfo)); } } }}void sort_aliases(void){ struct aliasinfo *a1,*a2; for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) { for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) { char *n1, *n2; n1 = a1->name; n2 = a2->name; if (show_alias && !show_inverted) { n1 = a1->ref; n2 = a2->ref; } if (strcasecmp(n1, n2) > 0) { struct aliasinfo t; memcpy(&t, a1, sizeof(struct aliasinfo)); memcpy(a1, a2, sizeof(struct aliasinfo)); memcpy(a2, &t, sizeof(struct aliasinfo)); } } }}void link_slabs(void){ struct aliasinfo *a; struct slabinfo *s; for (a = aliasinfo; a < aliasinfo + aliases; a++) { for (s = slabinfo; s < slabinfo + slabs; s++) if (strcmp(a->ref, s->name) == 0) { a->slab = s; s->refs++; break; } if (s == slabinfo + slabs) fatal("Unresolved alias %s\n", a->ref); }}void alias(void){ struct aliasinfo *a; char *active = NULL; sort_aliases(); link_slabs(); for(a = aliasinfo; a < aliasinfo + aliases; a++) { if (!show_single_ref && a->slab->refs == 1) continue; if (!show_inverted) { if (active) { if (strcmp(a->slab->name, active) == 0) { printf(" %s", a->name); continue; } } printf("\n%-12s <- %s", a->slab->name, a->name); active = a->slab->name; } else printf("%-20s -> %s\n", a->name, a->slab->name); } if (active) printf("\n");}void rename_slabs(void){ struct slabinfo *s; struct aliasinfo *a; for (s = slabinfo; s < slabinfo + slabs; s++) { if (*s->name != ':') continue; if (s->refs > 1 && !show_first_alias) continue; a = find_one_alias(s); if (a) s->name = a->name; else { s->name = "*"; actual_slabs--; } }}int slab_mismatch(char *slab){ return regexec(&pattern, slab, 0, NULL, 0);}void read_slab_dir(void){ DIR *dir; struct dirent *de; struct slabinfo *slab = slabinfo; struct aliasinfo *alias = aliasinfo; char *p; char *t; int count; if (chdir("/sys/slab")) fatal("SYSFS support for SLUB not active\n"); dir = opendir("."); while ((de = readdir(dir))) { if (de->d_name[0] == '.' || (de->d_name[0] != ':' && slab_mismatch(de->d_name))) continue; switch (de->d_type) { case DT_LNK: alias->name = strdup(de->d_name); count = readlink(de->d_name, buffer, sizeof(buffer)); if (count < 0) fatal("Cannot read symlink %s\n", de->d_name); buffer[count] = 0; p = buffer + count; while (p > buffer && p[-1] != '/') p--; alias->ref = strdup(p); alias++; break; case DT_DIR: if (chdir(de->d_name)) fatal("Unable to access slab %s\n", slab->name); slab->name = strdup(de->d_name); slab->alias = 0; slab->refs = 0; slab->aliases = get_obj("aliases"); slab->align = get_obj("align"); slab->cache_dma = get_obj("cache_dma"); slab->cpu_slabs = get_obj("cpu_slabs"); slab->destroy_by_rcu = get_obj("destroy_by_rcu"); slab->hwcache_align = get_obj("hwcache_align"); slab->object_size = get_obj("object_size"); slab->objects = get_obj("objects"); slab->objs_per_slab = get_obj("objs_per_slab"); slab->order = get_obj("order"); slab->partial = get_obj("partial"); slab->partial = get_obj_and_str("partial", &t); decode_numa_list(slab->numa_partial, t); free(t); slab->poison = get_obj("poison"); slab->reclaim_account = get_obj("reclaim_account"); slab->red_zone = get_obj("red_zone"); slab->sanity_checks = get_obj("sanity_checks"); slab->slab_size = get_obj("slab_size"); slab->slabs = get_obj_and_str("slabs", &t); decode_numa_list(slab->numa, t); free(t); slab->store_user = get_obj("store_user"); slab->trace = get_obj("trace"); chdir(".."); if (slab->name[0] == ':') alias_targets++; slab++; break; default : fatal("Unknown file type %lx\n", de->d_type); } } closedir(dir); slabs = slab - slabinfo; actual_slabs = slabs; aliases = alias - aliasinfo; if (slabs > MAX_SLABS) fatal("Too many slabs\n"); if (aliases > MAX_ALIASES) fatal("Too many aliases\n");}void output_slabs(void){ struct slabinfo *slab; for (slab = slabinfo; slab < slabinfo + slabs; slab++) { if (slab->alias) continue; if (show_numa) slab_numa(slab, 0); else if (show_track) show_tracking(slab); else if (validate) slab_validate(slab); else if (shrink) slab_shrink(slab); else if (set_debug) slab_debug(slab); else if (show_ops) ops(slab); else if (show_slab) slabcache(slab); else if (show_report) report(slab); }}struct option opts[] = { { "aliases", 0, NULL, 'a' }, { "debug", 2, NULL, 'd' }, { "empty", 0, NULL, 'e' }, { "first-alias", 0, NULL, 'f' }, { "help", 0, NULL, 'h' }, { "inverted", 0, NULL, 'i'}, { "numa", 0, NULL, 'n' }, { "ops", 0, NULL, 'o' }, { "report", 0, NULL, 'r' }, { "shrink", 0, NULL, 's' }, { "slabs", 0, NULL, 'l' }, { "track", 0, NULL, 't'}, { "validate", 0, NULL, 'v' }, { "zero", 0, NULL, 'z' }, { "1ref", 0, NULL, '1'}, { NULL, 0, NULL, 0 }};int main(int argc, char *argv[]){ int c; int err; char *pattern_source; page_size = getpagesize(); while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS", opts, NULL)) != -1) switch (c) { case '1': show_single_ref = 1; break; case 'a': show_alias = 1; break; case 'd': set_debug = 1; if (!debug_opt_scan(optarg)) fatal("Invalid debug option '%s'\n", optarg); break; case 'e': show_empty = 1; break; case 'f': show_first_alias = 1; break; case 'h': usage(); return 0; case 'i': show_inverted = 1; break; case 'n': show_numa = 1; break; case 'o': show_ops = 1; break; case 'r': show_report = 1; break; case 's': shrink = 1; break; case 'l': show_slab = 1; break; case 't': show_track = 1; break; case 'v': validate = 1; break; case 'z': skip_zero = 0; break; case 'T': show_totals = 1; break; case 'S': sort_size = 1; break; default: fatal("%s: Invalid option '%c'\n", argv[0], optopt); } if (!show_slab && !show_alias && !show_track && !show_report && !validate && !shrink && !set_debug && !show_ops) show_slab = 1; if (argc > optind) pattern_source = argv[optind]; else pattern_source = ".*"; err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB); if (err) fatal("%s: Invalid pattern '%s' code %d\n", argv[0], pattern_source, err); read_slab_dir(); if (show_alias) alias(); else if (show_totals) totals(); else { link_slabs(); rename_slabs(); sort_slabs(); output_slabs(); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -