[PATCH 02/22] perf tools: Add time sort entry

From: Jiri Olsa
Date: Sun Feb 02 2014 - 16:48:44 EST


Adding time sort entry. It's mainly for displaying the
time for entries for --list display in following patch.

Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Corey Ashford <cjashfor@xxxxxxxxxxxxxxxxxx>
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Cc: Paul Mackerras <paulus@xxxxxxxxx>
Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Cc: David Ahern <dsahern@xxxxxxxxx>
---
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-diff.c | 2 +-
tools/perf/tests/hists_link.c | 4 ++--
tools/perf/util/hist.c | 15 ++++++++-----
tools/perf/util/hist.h | 4 +++-
tools/perf/util/sort.c | 52 +++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/sort.h | 2 ++
tools/perf/util/util.h | 17 ++++++++++++++
8 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 70b2d52..875c117 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -65,7 +65,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
return 0;
}

- he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0,
+ he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0, 0,
true);
if (he == NULL)
return -ENOMEM;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 93912ad..92faed5 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -308,7 +308,7 @@ static int hists__add_entry(struct hists *hists,
u64 weight, u64 transaction)
{
if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
- transaction, true) != NULL)
+ transaction, 0, true) != NULL)
return 0;
return -ENOMEM;
}
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index e4e931e..e3bc8a8 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -223,7 +223,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
goto out;

he = __hists__add_entry(&evsel->hists, &al, NULL,
- NULL, NULL, 1, 1, 0, true);
+ NULL, NULL, 1, 1, 0, 0, true);
if (he == NULL)
goto out;

@@ -246,7 +246,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
goto out;

he = __hists__add_entry(&evsel->hists, &al, NULL,
- NULL, NULL, 1, 1, 0, true);
+ NULL, NULL, 1, 1, 0, 0, true);
if (he == NULL)
goto out;

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b14fa14..cf7d7e0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -157,6 +157,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
if (h->transaction)
hists__new_col_len(hists, HISTC_TRANSACTION,
hist_entry__transaction_len());
+
+ hists__new_col_len(hists, HISTC_TIME, 32);
}

void hists__output_recalc_col_len(struct hists *hists, int max_rows)
@@ -434,7 +436,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
struct branch_info *bi,
struct mem_info *mi,
u64 period, u64 weight, u64 transaction,
- bool sample_self)
+ u64 t, bool sample_self)
{
struct hist_entry entry = {
.thread = al->thread,
@@ -457,6 +459,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
.branch_info = bi,
.mem_info = mi,
.transaction = transaction,
+ .time = t,
};

return add_hist_entry(hists, &entry, al, sample_self);
@@ -516,7 +519,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
* and the he_stat__add_period() function.
*/
he = __hists__add_entry(&iter->evsel->hists, al, iter->parent, NULL, mi,
- cost, cost, 0, true);
+ cost, cost, 0, 0, true);
if (!he)
return -ENOMEM;

@@ -628,7 +631,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
* and not events sampled. Thus we use a pseudo period of 1.
*/
he = __hists__add_entry(&evsel->hists, al, iter->parent, &bi[i], NULL,
- 1, 1, 0, true);
+ 1, 1, 0, 0, true);
if (he == NULL)
return -ENOMEM;

@@ -674,7 +677,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location

he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
sample->period, sample->weight,
- sample->transaction, true);
+ sample->transaction, sample->time, true);
if (he == NULL)
return -ENOMEM;

@@ -730,7 +733,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,

he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
sample->period, sample->weight,
- sample->transaction, true);
+ sample->transaction, sample->time, true);
if (he == NULL)
return -ENOMEM;

@@ -801,7 +804,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,

he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
sample->period, sample->weight,
- sample->transaction, false);
+ sample->transaction, sample->time, false);
if (he == NULL)
return -ENOMEM;

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2f52c4d..851beef 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -69,6 +69,7 @@ enum hist_column {
HISTC_MEM_LVL,
HISTC_MEM_SNOOP,
HISTC_TRANSACTION,
+ HISTC_TIME,
HISTC_NR_COLS, /* Last entry */
};

@@ -87,6 +88,7 @@ struct hists {
const char *symbol_filter_str;
pthread_mutex_t lock;
struct events_stats stats;
+ u64 time_base;
u64 event_stream;
u16 col_len[HISTC_NR_COLS];
};
@@ -131,7 +133,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
struct branch_info *bi,
struct mem_info *mi, u64 period,
u64 weight, u64 transaction,
- bool sample_self);
+ u64 time, bool sample_self);
int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
struct perf_evsel *evsel, const union perf_event *event,
struct perf_sample *sample, int max_stack_depth,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 635cd8f..9438617 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2,6 +2,7 @@
#include "hist.h"
#include "comm.h"
#include "symbol.h"
+#include "util.h"

regex_t parent_regex;
const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -54,6 +55,56 @@ static int64_t cmp_null(const void *l, const void *r)
return 1;
}

+/* --sort time */
+
+static int64_t
+sort__time_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ return right->time - left->time;
+}
+
+static u64 get_time_base(struct hist_entry *he)
+{
+ struct hists *hists = he->hists;
+
+ if (!hists->time_base)
+ hists->time_base = he->time;
+
+ return hists->time_base;
+}
+
+static int hist_entry__time_snprintf(struct hist_entry *he, char *bf,
+ size_t size, unsigned int width)
+{
+ char buf[100];
+ u64 time_base = get_time_base(he);
+ unsigned long time_sec, time_usec;
+ unsigned long base_sec, base_usec;
+ long delta_sec, delta_usec;
+ bool neg = (s64)(he->time - time_base) < 0;
+
+ time_sec = nanotime_get_sec(he->time);
+ time_usec = nanotime_get_usec(he->time);
+ base_sec = nanotime_get_sec(time_base);
+ base_usec = nanotime_get_usec(time_base);
+
+ delta_sec = abs(time_sec - base_sec);
+ delta_usec = abs(time_usec - base_usec);
+
+ scnprintf(buf, 100, "%6lu.%06lu %s%06lu.%06lu",
+ time_sec, time_usec,
+ neg ? "-" : "+",
+ delta_sec, delta_usec);
+ return repsep_snprintf(bf, size, "%*s", width, buf);
+}
+
+struct sort_entry sort_time = {
+ .se_header = "Time",
+ .se_cmp = sort__time_cmp,
+ .se_snprintf = hist_entry__time_snprintf,
+ .se_width_idx = HISTC_TIME,
+};
+
/* --sort pid */

static int64_t
@@ -996,6 +1047,7 @@ static struct sort_dimension common_sort_dimensions[] = {
DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
DIM(SORT_TRANSACTION, "transaction", sort_transaction),
+ DIM(SORT_TIME, "time", sort_time),
};

#undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 103748b..4eb684e 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -88,6 +88,7 @@ struct hist_entry {
u64 ip;
u64 transaction;
s32 cpu;
+ u64 time;

struct hist_entry_diff diff;

@@ -163,6 +164,7 @@ enum sort_type {
SORT_LOCAL_WEIGHT,
SORT_GLOBAL_WEIGHT,
SORT_TRANSACTION,
+ SORT_TIME,

/* branch stack specific sort keys */
__SORT_BRANCH_STACK,
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 6995d66..881db9b 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -75,6 +75,9 @@
#include <termios.h>
#include <linux/bitops.h>

+#define NSECS_PER_SEC 1000000000ULL
+#define NSECS_PER_USEC 1000ULL
+
extern const char *graph_line;
extern const char *graph_dotted_line;
extern char buildid_dir[];
@@ -295,6 +298,20 @@ static inline unsigned long next_pow2_l(unsigned long x)
#endif
}

+static inline unsigned long nanotime_get_sec(u64 t)
+{
+ return t / NSECS_PER_SEC;
+}
+
+static inline unsigned long nanotime_get_usec(u64 t)
+{
+ unsigned long long secs;
+
+ secs = t / NSECS_PER_SEC;
+ t -= secs * NSECS_PER_SEC;
+ return t / NSECS_PER_USEC;
+}
+
size_t hex_width(u64 v);
int hex2u64(const char *ptr, u64 *val);

--
1.8.3.1

--
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/