mirror of https://github.com/OpenIPC/firmware.git
329 lines
10 KiB
Diff
329 lines
10 KiB
Diff
diff -drupN a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
|
|
--- a/tools/vm/slabinfo.c 2018-08-06 17:23:04.000000000 +0300
|
|
+++ b/tools/vm/slabinfo.c 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -75,6 +75,9 @@ int show_inverted;
|
|
int show_single_ref;
|
|
int show_totals;
|
|
int sort_size;
|
|
+int sort_func;
|
|
+int sort_by_size;
|
|
+int sort_by_char;
|
|
int sort_active;
|
|
int set_debug;
|
|
int show_ops;
|
|
@@ -122,7 +125,9 @@ static void usage(void)
|
|
"-o|--ops Show kmem_cache_ops\n"
|
|
"-s|--shrink Shrink slabs\n"
|
|
"-r|--report Detailed report on single slabs\n"
|
|
- "-S|--Size Sort by size\n"
|
|
+ "-S|--Size Sort slab by size\n"
|
|
+ "-F|--Func Sort func by size\n"
|
|
+ "-C|--Char Sort func by first character of func\n"
|
|
"-t|--tracking Show alloc/free information\n"
|
|
"-T|--Totals Show summary information\n"
|
|
"-v|--validate Validate slabs\n"
|
|
@@ -1337,6 +1342,8 @@ struct option opts[] = {
|
|
{ "shrink", no_argument, NULL, 's' },
|
|
{ "report", no_argument, NULL, 'r' },
|
|
{ "Size", no_argument, NULL, 'S'},
|
|
+ { "Func", no_argument, NULL, 'F'},
|
|
+ { "Char", no_argument, NULL, 'C'},
|
|
{ "tracking", no_argument, NULL, 't'},
|
|
{ "Totals", no_argument, NULL, 'T'},
|
|
{ "validate", no_argument, NULL, 'v' },
|
|
@@ -1349,6 +1356,256 @@ struct option opts[] = {
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
+/*
|
|
+ * Output format:
|
|
+ * Total_size slab_type object_size objects slab_size alloc_calls_info
|
|
+ * */
|
|
+struct slab_func_info{
|
|
+ char slab_name[64]; //slab type
|
|
+ int slab_total_size; //total slab size alloc by func
|
|
+ int slab_object_size; //object size
|
|
+ int slab_size; //slab size
|
|
+ int slab_cnt; //objects num
|
|
+ char *slab_alloc_info; //slab alloc func info
|
|
+ struct slab_func_info *pNext;
|
|
+};
|
|
+
|
|
+static void swap_slab_func_info(struct slab_func_info *A, struct slab_func_info *B)
|
|
+{
|
|
+ char slab_name[64];
|
|
+ int slab_total_size;
|
|
+ int slab_object_size;
|
|
+ int slab_size;
|
|
+ int slab_cnt;
|
|
+ char *slab_alloc_info = NULL;
|
|
+
|
|
+ slab_total_size = (A)->slab_total_size;
|
|
+ (A)->slab_total_size = (B)->slab_total_size;
|
|
+ (B)->slab_total_size = slab_total_size;
|
|
+
|
|
+ slab_object_size = (A)->slab_object_size;
|
|
+ (A)->slab_object_size = (B)->slab_object_size;
|
|
+ (B)->slab_object_size = slab_object_size;
|
|
+
|
|
+ slab_size = (A)->slab_size;
|
|
+ (A)->slab_size = (B)->slab_size;
|
|
+ (B)->slab_size = slab_size;
|
|
+
|
|
+ slab_cnt = (A)->slab_cnt;
|
|
+ (A)->slab_cnt = (B)->slab_cnt;
|
|
+ (B)->slab_cnt = slab_cnt;
|
|
+
|
|
+ strcpy(slab_name, (A)->slab_name);
|
|
+ strcpy((A)->slab_name, (B)->slab_name);
|
|
+ strcpy((B)->slab_name, slab_name);
|
|
+
|
|
+ slab_alloc_info = (A)->slab_alloc_info;
|
|
+ (A)->slab_alloc_info = (B)->slab_alloc_info;
|
|
+ (B)->slab_alloc_info = slab_alloc_info;
|
|
+}
|
|
+
|
|
+//#define SAVE_RESULT_FILE
|
|
+
|
|
+static void sort_func_by_size(struct slab_func_info *info_head, FILE *fp)
|
|
+{
|
|
+ struct slab_func_info *info_p = NULL;
|
|
+ struct slab_func_info *tmp_p = NULL;
|
|
+ struct slab_func_info *tgt_p = NULL;
|
|
+ int total_size = 0;
|
|
+
|
|
+ info_p = info_head;
|
|
+ for (; info_p != NULL; info_p = info_p->pNext) {
|
|
+ total_size = info_p->slab_total_size;
|
|
+ tgt_p = info_p;
|
|
+ for (tmp_p = info_p->pNext; tmp_p != NULL; tmp_p = tmp_p->pNext) {
|
|
+ if (total_size < tmp_p->slab_total_size) {
|
|
+ total_size = tmp_p->slab_total_size;
|
|
+ tgt_p = tmp_p;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ printf("%-12d %-24s %-9d %-7d %-10d %s\n", tgt_p->slab_total_size,
|
|
+ tgt_p->slab_name, tgt_p->slab_object_size, tgt_p->slab_cnt, tgt_p->slab_size, tgt_p->slab_alloc_info);
|
|
+#ifdef SAVE_RESULT_FILE
|
|
+ fprintf(fp, "%-12d %-24s %-10d %-7d %-10d %s\n", tgt_p->slab_total_size,
|
|
+ tgt_p->slab_name, tgt_p->slab_size, tgt_p->slab_cnt, tgt_p->slab_object_size, tgt_p->slab_alloc_info);
|
|
+#endif
|
|
+
|
|
+ swap_slab_func_info(tgt_p, info_p);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void sort_func_by_char(struct slab_func_info *info_head, FILE *fp)
|
|
+{
|
|
+ int i = 0, j = 0;
|
|
+ int had_sort_num = 0;
|
|
+ char *func_char_p = NULL;
|
|
+ struct slab_func_info *info_p = NULL;
|
|
+ struct slab_func_info *had_sort_p = NULL;
|
|
+ char *func_first_char = "abcdefghijklmnopqrstuvwxyzADCDEFGHIJKLMNOPQRSTUVWXYZ_<";
|
|
+ int func_char_len = strlen(func_first_char);
|
|
+
|
|
+ for (i = 0; i < func_char_len; i++, func_first_char++) {
|
|
+ info_p = info_head;
|
|
+ for (j = 0; j < had_sort_num; j++)
|
|
+ info_p = info_p->pNext;
|
|
+ had_sort_p = info_p;
|
|
+ for (; info_p != NULL; info_p = info_p->pNext) {
|
|
+ if (!strncmp(info_p->slab_alloc_info, func_first_char, 1)) {
|
|
+ swap_slab_func_info(had_sort_p, info_p);
|
|
+
|
|
+ printf("%-12d %-24s %-9d %-7d %-10d %s\n", had_sort_p->slab_total_size, had_sort_p->slab_name,
|
|
+ had_sort_p->slab_object_size, had_sort_p->slab_cnt, had_sort_p->slab_size, had_sort_p->slab_alloc_info);
|
|
+#ifdef SAVE_RESULT_FILE
|
|
+ fprintf(fp, "%-12d %-24s %-9d %-7d %-10d %s\n", had_sort_p->slab_total_size, had_sort_p->slab_name,
|
|
+ had_sort_p->slab_object_size, had_sort_p->slab_cnt, had_sort_p->slab_size, had_sort_p->slab_alloc_info);
|
|
+#endif
|
|
+
|
|
+ had_sort_p = had_sort_p->pNext;
|
|
+ had_sort_num++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static int sort_and_show_func(void)
|
|
+{
|
|
+ FILE *fp = NULL;
|
|
+ FILE *fp_output = NULL;
|
|
+ char *str_p = NULL;
|
|
+ struct slabinfo *s = NULL;
|
|
+ char slab_name[64];
|
|
+ char str_one_line[1024];
|
|
+ int slab_size = 0;
|
|
+ int object_size = 0;
|
|
+ struct slab_func_info *info_head = NULL;
|
|
+ struct slab_func_info *info_p = NULL;
|
|
+
|
|
+ info_head = (struct slab_func_info *)malloc(sizeof(struct slab_func_info));
|
|
+ info_head->pNext = NULL;
|
|
+ info_p = info_head;
|
|
+
|
|
+#ifdef SAVE_RESULT_FILE
|
|
+ system("rm /tmp/slab_func_info > /dev/null 2>&1");
|
|
+#endif
|
|
+ /* collect alloc_calls messages and save them in tempfile*/
|
|
+ fp = fopen("/tmp/tempfile", "arw+");
|
|
+ if (fp == NULL) {
|
|
+ printf("open %s file fail!\n", "/tmp/tempfile");
|
|
+ return -1;
|
|
+ }
|
|
+ for (s = slabinfo; s < slabinfo + slabs; s++) {
|
|
+ if (read_slab_obj(s, "alloc_calls")) {
|
|
+ fprintf(fp, "slabname: %s, object_size: %d, slab_size: %d\n",
|
|
+ s->name, s->object_size, s->slab_size);
|
|
+ fwrite(buffer, 1, strlen(buffer), fp);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ rewind(fp);
|
|
+ while (!feof(fp)) {
|
|
+ fgets(str_one_line, 1024, fp);
|
|
+ if (strlen(str_one_line) == 0)
|
|
+ break;
|
|
+
|
|
+ if (!strncmp(str_one_line, "slabname", 8)) { /*get one slab type info*/
|
|
+ /* format: slabname: %s, object_size: %d, slab_size: %d */
|
|
+ str_p = NULL;
|
|
+ str_p = strtok(str_one_line, " ");
|
|
+ str_p = strtok(NULL, ",");
|
|
+ strcpy(slab_name, str_p); /*get slab type*/
|
|
+ str_p = strtok(NULL, " ");
|
|
+ str_p = strtok(NULL, ",");
|
|
+ object_size = atoi(str_p); /*get object size*/
|
|
+ str_p = strtok(NULL, " ");
|
|
+ str_p = strtok(NULL, " ");
|
|
+ slab_size = atoi(str_p); /*get slab size*/
|
|
+ } else if (!strncmp(str_one_line, "No data", 7)) {
|
|
+ /*some of the loss parts*/
|
|
+ continue;
|
|
+ } else if (strlen(str_one_line) < 16) { // wait for fix
|
|
+ continue;
|
|
+ } else {
|
|
+ /*one slab object one time*/
|
|
+ if (info_head->pNext == NULL) {
|
|
+ info_p = info_head;
|
|
+ info_head->pNext = (struct slab_func_info *)malloc(sizeof(struct slab_func_info));
|
|
+ } else {
|
|
+ info_p->pNext = (struct slab_func_info *)malloc(sizeof(struct slab_func_info));
|
|
+ if (info_p->pNext == NULL) {
|
|
+ printf("In %s line %d: malloc fail!\n", __func__, __LINE__);
|
|
+ fclose(fp);
|
|
+ return -1;
|
|
+ }
|
|
+ info_p = info_p->pNext;
|
|
+ }
|
|
+ strcpy(info_p->slab_name, slab_name);
|
|
+ info_p->slab_object_size = object_size;
|
|
+ info_p->slab_size = slab_size;
|
|
+ /*format: objs alloc_func_info*/
|
|
+ str_p = NULL;
|
|
+ str_p = strtok(str_one_line, " ");
|
|
+ info_p->slab_cnt = atoi(str_p); /*get objests num*/
|
|
+ info_p->slab_total_size = info_p->slab_object_size * info_p->slab_cnt;
|
|
+ str_p = strtok(NULL, " "); /*get alloc func info*/
|
|
+ info_p->slab_alloc_info = (char *)malloc(strlen(str_p) + 4);
|
|
+ //info_p->slab_alloc_info = (char *)malloc(strlen(str_p) + 1); //malloc may fail?
|
|
+ if (info_p->slab_alloc_info == NULL) {
|
|
+ printf("In %s line %d: malloc fail!\n", __func__, __LINE__);
|
|
+ fclose(fp);
|
|
+ return -1;
|
|
+ }
|
|
+ strcpy(info_p->slab_alloc_info, str_p);
|
|
+#if 0
|
|
+ printf("In %d line %d: alloc_info = %s\n", __func__, __LINE__, info_p->slab_alloc_info);
|
|
+ printf("In %d line %d: total_size= %d, slab_name %s, alloc_info %s\n", __func__, __LINE__,
|
|
+ info_p->slab_total_size, info_p->slab_name, info_p->slab_alloc_info);
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+
|
|
+#ifdef SAVE_RESULT_FILE
|
|
+ fp_output = fopen("/tmp/slab_func_info", "arw+");
|
|
+ if (fp_output == NULL) {
|
|
+ printf("open %s file fail!\n", "/data/slab_func_info");
|
|
+ fclose(fp);
|
|
+ return -1;
|
|
+ }
|
|
+ fprintf(fp_output, "Total(byte) Slab_type Obj_size Objs Slab_size Alloc_func\n");
|
|
+#endif
|
|
+
|
|
+ printf("Total(byte) Slab_type Obj_size Objs Slab_size Alloc_func\n");
|
|
+ if (sort_by_size) {
|
|
+ /*sort by size*/
|
|
+ sort_func_by_size(info_head, fp_output);
|
|
+ } else if (sort_func_by_char) {
|
|
+ /*sort by the first character of alloc func name*/
|
|
+ sort_func_by_char(info_head, fp_output);
|
|
+ }
|
|
+
|
|
+ /*free sources!*/
|
|
+ /*must free malloc buffer*/
|
|
+ info_p = info_head;
|
|
+ for (; info_p != NULL; info_p = info_p->pNext) {
|
|
+ if (info_p->slab_alloc_info != NULL) {
|
|
+ free(info_p->slab_alloc_info);
|
|
+ info_p->slab_alloc_info = NULL;
|
|
+ }
|
|
+ if (info_p != NULL) {
|
|
+ free(info_p);
|
|
+ // info_p = NULL; /*segmemtation fault!*/
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fclose(fp);
|
|
+#ifdef SAVE_RESULT_FILE
|
|
+ fclose(fp_output);
|
|
+#endif
|
|
+ system("rm /tmp/tempfile > /dev/null 2>&1");
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int c;
|
|
@@ -1357,7 +1614,7 @@ int main(int argc, char *argv[])
|
|
|
|
page_size = getpagesize();
|
|
|
|
- while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSN:LXB",
|
|
+ while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSFCN:LXB",
|
|
opts, NULL)) != -1)
|
|
switch (c) {
|
|
case '1':
|
|
@@ -1419,6 +1676,16 @@ int main(int argc, char *argv[])
|
|
case 'S':
|
|
sort_size = 1;
|
|
break;
|
|
+ case 'F':
|
|
+ sort_size = 1;
|
|
+ sort_func = 1;
|
|
+ sort_by_size = 1;
|
|
+ break;
|
|
+ case 'C':
|
|
+ sort_size = 1;
|
|
+ sort_func = 1;
|
|
+ sort_by_char = 1;
|
|
+ break;
|
|
case 'N':
|
|
if (optarg) {
|
|
output_lines = atoi(optarg);
|
|
@@ -1463,6 +1730,11 @@ int main(int argc, char *argv[])
|
|
xtotals();
|
|
} else if (show_totals) {
|
|
totals();
|
|
+ } else if (sort_func) {
|
|
+ link_slabs();
|
|
+ rename_slabs();
|
|
+ sort_slabs();
|
|
+ sort_and_show_func();
|
|
} else {
|
|
link_slabs();
|
|
rename_slabs();
|