Skip to content

Commit 9bd7ddd

Browse files
namhyungacmel
authored andcommitted
perf annotate-data: Update sample histogram for type
The annotated_data_type__update_samples() to get histogram for data type access. It'll be called by perf annotate to show which fields in the data type are accessed frequently. Signed-off-by: Namhyung Kim <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: [email protected] Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 4a111ca commit 9bd7ddd

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

tools/perf/util/annotate-data.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "debuginfo.h"
1414
#include "debug.h"
1515
#include "dso.h"
16+
#include "evsel.h"
17+
#include "evlist.h"
1618
#include "map.h"
1719
#include "map_symbol.h"
1820
#include "strbuf.h"
@@ -302,6 +304,44 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip,
302304
return result;
303305
}
304306

307+
static int alloc_data_type_histograms(struct annotated_data_type *adt, int nr_entries)
308+
{
309+
int i;
310+
size_t sz = sizeof(struct type_hist);
311+
312+
sz += sizeof(struct type_hist_entry) * adt->self.size;
313+
314+
/* Allocate a table of pointers for each event */
315+
adt->nr_histograms = nr_entries;
316+
adt->histograms = calloc(nr_entries, sizeof(*adt->histograms));
317+
if (adt->histograms == NULL)
318+
return -ENOMEM;
319+
320+
/*
321+
* Each histogram is allocated for the whole size of the type.
322+
* TODO: Probably we can move the histogram to members.
323+
*/
324+
for (i = 0; i < nr_entries; i++) {
325+
adt->histograms[i] = zalloc(sz);
326+
if (adt->histograms[i] == NULL)
327+
goto err;
328+
}
329+
return 0;
330+
331+
err:
332+
while (--i >= 0)
333+
free(adt->histograms[i]);
334+
free(adt->histograms);
335+
return -ENOMEM;
336+
}
337+
338+
static void delete_data_type_histograms(struct annotated_data_type *adt)
339+
{
340+
for (int i = 0; i < adt->nr_histograms; i++)
341+
free(adt->histograms[i]);
342+
free(adt->histograms);
343+
}
344+
305345
void annotated_data_type__tree_delete(struct rb_root *root)
306346
{
307347
struct annotated_data_type *pos;
@@ -312,7 +352,48 @@ void annotated_data_type__tree_delete(struct rb_root *root)
312352
rb_erase(node, root);
313353
pos = rb_entry(node, struct annotated_data_type, node);
314354
delete_members(&pos->self);
355+
delete_data_type_histograms(pos);
315356
free(pos->self.type_name);
316357
free(pos);
317358
}
318359
}
360+
361+
/**
362+
* annotated_data_type__update_samples - Update histogram
363+
* @adt: Data type to update
364+
* @evsel: Event to update
365+
* @offset: Offset in the type
366+
* @nr_samples: Number of samples at this offset
367+
* @period: Event count at this offset
368+
*
369+
* This function updates type histogram at @ofs for @evsel. Samples are
370+
* aggregated before calling this function so it can be called with more
371+
* than one samples at a certain offset.
372+
*/
373+
int annotated_data_type__update_samples(struct annotated_data_type *adt,
374+
struct evsel *evsel, int offset,
375+
int nr_samples, u64 period)
376+
{
377+
struct type_hist *h;
378+
379+
if (adt == NULL)
380+
return 0;
381+
382+
if (adt->histograms == NULL) {
383+
int nr = evsel->evlist->core.nr_entries;
384+
385+
if (alloc_data_type_histograms(adt, nr) < 0)
386+
return -1;
387+
}
388+
389+
if (offset < 0 || offset >= adt->self.size)
390+
return -1;
391+
392+
h = adt->histograms[evsel->core.idx];
393+
394+
h->nr_samples += nr_samples;
395+
h->addr[offset].nr_samples += nr_samples;
396+
h->period += period;
397+
h->addr[offset].period += period;
398+
return 0;
399+
}

tools/perf/util/annotate-data.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/rbtree.h>
88
#include <linux/types.h>
99

10+
struct evsel;
1011
struct map_symbol;
1112

1213
/**
@@ -29,16 +30,42 @@ struct annotated_member {
2930
int size;
3031
};
3132

33+
/**
34+
* struct type_hist_entry - Histogram entry per offset
35+
* @nr_samples: Number of samples
36+
* @period: Count of event
37+
*/
38+
struct type_hist_entry {
39+
int nr_samples;
40+
u64 period;
41+
};
42+
43+
/**
44+
* struct type_hist - Type histogram for each event
45+
* @nr_samples: Total number of samples in this data type
46+
* @period: Total count of the event in this data type
47+
* @offset: Array of histogram entry
48+
*/
49+
struct type_hist {
50+
u64 nr_samples;
51+
u64 period;
52+
struct type_hist_entry addr[];
53+
};
54+
3255
/**
3356
* struct annotated_data_type - Data type to profile
3457
* @node: RB-tree node for dso->type_tree
3558
* @self: Actual type information
59+
* @nr_histogram: Number of histogram entries
60+
* @histograms: An array of pointers to histograms
3661
*
3762
* This represents a data type accessed by samples in the profile data.
3863
*/
3964
struct annotated_data_type {
4065
struct rb_node node;
4166
struct annotated_member self;
67+
int nr_histograms;
68+
struct type_hist **histograms;
4269
};
4370

4471
extern struct annotated_data_type unknown_type;
@@ -49,6 +76,11 @@ extern struct annotated_data_type unknown_type;
4976
struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip,
5077
int reg, int offset);
5178

79+
/* Update type access histogram at the given offset */
80+
int annotated_data_type__update_samples(struct annotated_data_type *adt,
81+
struct evsel *evsel, int offset,
82+
int nr_samples, u64 period);
83+
5284
/* Release all data type information in the tree */
5385
void annotated_data_type__tree_delete(struct rb_root *root);
5486

@@ -61,6 +93,16 @@ find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused,
6193
return NULL;
6294
}
6395

96+
static inline int
97+
annotated_data_type__update_samples(struct annotated_data_type *adt __maybe_unused,
98+
struct evsel *evsel __maybe_unused,
99+
int offset __maybe_unused,
100+
int nr_samples __maybe_unused,
101+
u64 period __maybe_unused)
102+
{
103+
return -1;
104+
}
105+
64106
static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe_unused)
65107
{
66108
}

tools/perf/util/annotate.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3679,6 +3679,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
36793679
struct disasm_line *dl;
36803680
struct annotated_insn_loc loc;
36813681
struct annotated_op_loc *op_loc;
3682+
struct annotated_data_type *mem_type;
36823683
u64 ip = he->ip;
36833684
int i;
36843685

@@ -3709,7 +3710,13 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
37093710
if (!op_loc->mem_ref)
37103711
continue;
37113712

3712-
return find_data_type(ms, ip, op_loc->reg, op_loc->offset);
3713+
mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset);
3714+
3715+
annotated_data_type__update_samples(mem_type, evsel,
3716+
op_loc->offset,
3717+
he->stat.nr_events,
3718+
he->stat.period);
3719+
return mem_type;
37133720
}
37143721
return NULL;
37153722
}

0 commit comments

Comments
 (0)