Re: [PATCH 6/6] perf kmem: Print gfp flags in human readable string

From: Arnaldo Carvalho de Melo
Date: Thu Mar 26 2015 - 10:10:18 EST


Em Thu, Mar 26, 2015 at 03:00:36PM +0900, Namhyung Kim escreveu:
> Save libtraceevent output and print it in the header.
>
> # perf kmem stat --page --caller
> # GFP flags
> # ---------
> # 00000010: GFP_NOIO
> # 000000d0: GFP_KERNEL
> # 00000200: GFP_NOWARN
> # 000084d0: GFP_KERNEL|GFP_REPEAT|GFP_ZERO
> # 000200d2: GFP_HIGHUSER
> # 000200da: GFP_HIGHUSER_MOVABLE
> # 000280da: GFP_HIGHUSER_MOVABLE|GFP_ZERO
> # 002084d0: GFP_KERNEL|GFP_REPEAT|GFP_ZERO|GFP_NOTRACK
> # 0102005a: GFP_NOFS|GFP_HARDWALL|GFP_MOVABLE
>
> ---------------------------------------------------------------------------------------------------------
> Total alloc (KB) | Hits | Order | Migration type | GFP flags | Callsite
> ---------------------------------------------------------------------------------------------------------
> 60 | 15 | 0 | UNMOVABLE | 002084d0 | pte_alloc_one
> 40 | 10 | 0 | MOVABLE | 000280da | handle_mm_fault
> 24 | 6 | 0 | MOVABLE | 000200da | do_wp_page
> 24 | 6 | 0 | UNMOVABLE | 000000d0 | __pollwait
> ...

Perhaps you could compact it further by doing things like:

# 00000010: NIO: GFP_NOIO
# 000000d0: K: GFP_KERNEL
# 00000200: NW: GFP_NOWARN
# 000084d0: K|R|Z: GFP_KERNEL|GFP_REPEAT|GFP_ZERO
# 000200d2: HU: GFP_HIGHUSER
# 000200da: HUM: GFP_HIGHUSER_MOVABLE
# 000280da: HUM|Z: GFP_HIGHUSER_MOVABLE|GFP_ZERO
# 002084d0: K|R|Z|NT: GFP_KERNEL|GFP_REPEAT|GFP_ZERO|GFP_NOTRACK
# 0102005a: NFS|HW|M: GFP_NOFS|GFP_HARDWALL|GFP_MOVABLE

-------------------------------------------------------------------------
Total(KB) | Hits | Ord | Migr.| GFP flg | Callsite
-------------------------------------------------------------------------
60 | 15 | 0 | UNMV | K|R|Z|NT | pte_alloc_one
40 | 10 | 0 | MV | HUM|Z | handle_mm_fault
24 | 6 | 0 | MV | HUM | do_wp_page
24 | 6 | 0 | UNMV | K | __pollwait

I.e. using mnemonics instead of a hex number for the GFP flag, reducing
the need to lookup the header.

Just my 2 cents :-)

- Arnaldo

>
> Requested-by: Joonsoo Kim <js1304@xxxxxxxxx>
> Suggested-by: Minchan Kim <minchan@xxxxxxxxxx>
> Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
> ---
> tools/perf/builtin-kmem.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 81 insertions(+)
>
> diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
> index c09e332f7f38..502f6944a04c 100644
> --- a/tools/perf/builtin-kmem.c
> +++ b/tools/perf/builtin-kmem.c
> @@ -545,6 +545,72 @@ static bool valid_page(u64 pfn_or_page)
> return true;
> }
>
> +struct gfp_flag {
> + unsigned int flags;
> + char *human_readable;
> +};
> +
> +static struct gfp_flag *gfps;
> +static int nr_gfps;
> +
> +static int gfpcmp(const void *a, const void *b)
> +{
> + const struct gfp_flag *fa = a;
> + const struct gfp_flag *fb = b;
> +
> + return fa->flags - fb->flags;
> +}
> +
> +static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
> + unsigned int gfp_flags)
> +{
> + struct pevent_record record = {
> + .cpu = sample->cpu,
> + .data = sample->raw_data,
> + .size = sample->raw_size,
> + };
> + struct trace_seq seq;
> + char *str;
> +
> + if (nr_gfps) {
> + struct gfp_flag key = {
> + .flags = gfp_flags,
> + };
> +
> + if (bsearch(&key, gfps, nr_gfps, sizeof(*gfps), gfpcmp))
> + return 0;
> + }
> +
> + trace_seq_init(&seq);
> + pevent_event_info(&seq, evsel->tp_format, &record);
> +
> + str = strtok(seq.buffer, " ");
> + while (str) {
> + if (!strncmp(str, "gfp_flags=", 10)) {
> + struct gfp_flag *new;
> +
> + new = realloc(gfps, (nr_gfps + 1) * sizeof(*gfps));
> + if (new == NULL)
> + return -ENOMEM;
> +
> + gfps = new;
> + new += nr_gfps++;
> +
> + new->flags = gfp_flags;
> + new->human_readable = strdup(str + 10);
> + if (new->human_readable == NULL)
> + return -ENOMEM;
> +
> + qsort(gfps, nr_gfps, sizeof(*gfps), gfpcmp);
> + }
> +
> + str = strtok(NULL, " ");
> + }
> +
> + trace_seq_destroy(&seq);
> + return 0;
> +}
> +
> static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
> struct perf_sample *sample)
> {
> @@ -577,6 +643,9 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
> return 0;
> }
>
> + if (parse_gfp_flags(evsel, sample, gfp_flags) < 0)
> + return -1;
> +
> callsite = find_callsite(evsel, sample);
>
> /*
> @@ -877,6 +946,16 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
> printf("%.105s\n", graph_dotted_line);
> }
>
> +static void print_gfp_flags(void)
> +{
> + int i;
> +
> + printf("# GFP flags\n");
> + printf("# ---------\n");
> + for (i = 0; i < nr_gfps; i++)
> + printf("# %08x: %s\n", gfps[i].flags, gfps[i].human_readable);
> +}
> +
> static void print_slab_summary(void)
> {
> printf("\nSUMMARY (SLAB allocator)");
> @@ -946,6 +1025,8 @@ static void print_slab_result(struct perf_session *session)
>
> static void print_page_result(struct perf_session *session)
> {
> + if (caller_flag || alloc_flag)
> + print_gfp_flags();
> if (caller_flag)
> __print_page_caller_result(session, caller_lines);
> if (alloc_flag)
> --
> 2.3.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/