|
@@ -3,6 +3,7 @@
|
|
|
#include "hist.h"
|
|
|
#include "session.h"
|
|
|
#include "sort.h"
|
|
|
+#include "evlist.h"
|
|
|
#include "evsel.h"
|
|
|
#include "annotate.h"
|
|
|
#include <math.h>
|
|
@@ -14,13 +15,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
|
|
|
static bool hists__filter_entry_by_symbol(struct hists *hists,
|
|
|
struct hist_entry *he);
|
|
|
|
|
|
-struct callchain_param callchain_param = {
|
|
|
- .mode = CHAIN_GRAPH_REL,
|
|
|
- .min_percent = 0.5,
|
|
|
- .order = ORDER_CALLEE,
|
|
|
- .key = CCKEY_FUNCTION
|
|
|
-};
|
|
|
-
|
|
|
u16 hists__col_len(struct hists *hists, enum hist_column col)
|
|
|
{
|
|
|
return hists->col_len[col];
|
|
@@ -516,6 +510,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
|
|
|
{
|
|
|
u64 cost;
|
|
|
struct mem_info *mi = iter->priv;
|
|
|
+ struct hists *hists = evsel__hists(iter->evsel);
|
|
|
struct hist_entry *he;
|
|
|
|
|
|
if (mi == NULL)
|
|
@@ -532,7 +527,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
|
|
|
* and this is indirectly achieved by passing period=weight here
|
|
|
* and the he_stat__add_period() function.
|
|
|
*/
|
|
|
- he = __hists__add_entry(&iter->evsel->hists, al, iter->parent, NULL, mi,
|
|
|
+ he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
|
|
|
cost, cost, 0, true);
|
|
|
if (!he)
|
|
|
return -ENOMEM;
|
|
@@ -546,13 +541,14 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
|
|
|
struct addr_location *al __maybe_unused)
|
|
|
{
|
|
|
struct perf_evsel *evsel = iter->evsel;
|
|
|
+ struct hists *hists = evsel__hists(evsel);
|
|
|
struct hist_entry *he = iter->he;
|
|
|
int err = -EINVAL;
|
|
|
|
|
|
if (he == NULL)
|
|
|
goto out;
|
|
|
|
|
|
- hists__inc_nr_samples(&evsel->hists, he->filtered);
|
|
|
+ hists__inc_nr_samples(hists, he->filtered);
|
|
|
|
|
|
err = hist_entry__append_callchain(he, iter->sample);
|
|
|
|
|
@@ -618,6 +614,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
|
|
|
{
|
|
|
struct branch_info *bi;
|
|
|
struct perf_evsel *evsel = iter->evsel;
|
|
|
+ struct hists *hists = evsel__hists(evsel);
|
|
|
struct hist_entry *he = NULL;
|
|
|
int i = iter->curr;
|
|
|
int err = 0;
|
|
@@ -631,12 +628,12 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
|
|
|
* The report shows the percentage of total branches captured
|
|
|
* and not events sampled. Thus we use a pseudo period of 1.
|
|
|
*/
|
|
|
- he = __hists__add_entry(&evsel->hists, al, iter->parent, &bi[i], NULL,
|
|
|
+ he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
|
|
|
1, 1, 0, true);
|
|
|
if (he == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- hists__inc_nr_samples(&evsel->hists, he->filtered);
|
|
|
+ hists__inc_nr_samples(hists, he->filtered);
|
|
|
|
|
|
out:
|
|
|
iter->he = he;
|
|
@@ -668,7 +665,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
|
|
|
struct perf_sample *sample = iter->sample;
|
|
|
struct hist_entry *he;
|
|
|
|
|
|
- he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
|
|
|
+ he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
|
|
|
sample->period, sample->weight,
|
|
|
sample->transaction, true);
|
|
|
if (he == NULL)
|
|
@@ -691,7 +688,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
|
|
|
|
|
|
iter->he = NULL;
|
|
|
|
|
|
- hists__inc_nr_samples(&evsel->hists, he->filtered);
|
|
|
+ hists__inc_nr_samples(evsel__hists(evsel), he->filtered);
|
|
|
|
|
|
return hist_entry__append_callchain(he, sample);
|
|
|
}
|
|
@@ -724,12 +721,13 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
struct addr_location *al)
|
|
|
{
|
|
|
struct perf_evsel *evsel = iter->evsel;
|
|
|
+ struct hists *hists = evsel__hists(evsel);
|
|
|
struct perf_sample *sample = iter->sample;
|
|
|
struct hist_entry **he_cache = iter->priv;
|
|
|
struct hist_entry *he;
|
|
|
int err = 0;
|
|
|
|
|
|
- he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
|
|
|
+ he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
|
|
|
sample->period, sample->weight,
|
|
|
sample->transaction, true);
|
|
|
if (he == NULL)
|
|
@@ -746,7 +744,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
*/
|
|
|
callchain_cursor_commit(&callchain_cursor);
|
|
|
|
|
|
- hists__inc_nr_samples(&evsel->hists, he->filtered);
|
|
|
+ hists__inc_nr_samples(hists, he->filtered);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -802,7 +800,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
|
|
|
+ he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
|
|
|
sample->period, sample->weight,
|
|
|
sample->transaction, false);
|
|
|
if (he == NULL)
|
|
@@ -1408,6 +1406,21 @@ int hists__link(struct hists *leader, struct hists *other)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
|
|
|
+{
|
|
|
+ struct perf_evsel *pos;
|
|
|
+ size_t ret = 0;
|
|
|
+
|
|
|
+ evlist__for_each(evlist, pos) {
|
|
|
+ ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
|
|
|
+ ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
u64 hists__total_period(struct hists *hists)
|
|
|
{
|
|
|
return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
|
|
@@ -1434,3 +1447,31 @@ int perf_hist_config(const char *var, const char *value)
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+static int hists_evsel__init(struct perf_evsel *evsel)
|
|
|
+{
|
|
|
+ struct hists *hists = evsel__hists(evsel);
|
|
|
+
|
|
|
+ memset(hists, 0, sizeof(*hists));
|
|
|
+ hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
|
|
|
+ hists->entries_in = &hists->entries_in_array[0];
|
|
|
+ hists->entries_collapsed = RB_ROOT;
|
|
|
+ hists->entries = RB_ROOT;
|
|
|
+ pthread_mutex_init(&hists->lock, NULL);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * XXX We probably need a hists_evsel__exit() to free the hist_entries
|
|
|
+ * stored in the rbtree...
|
|
|
+ */
|
|
|
+
|
|
|
+int hists__init(void)
|
|
|
+{
|
|
|
+ int err = perf_evsel__object_config(sizeof(struct hists_evsel),
|
|
|
+ hists_evsel__init, NULL);
|
|
|
+ if (err)
|
|
|
+ fputs("FATAL ERROR: Couldn't setup hists class\n", stderr);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|