[PATCH/RFC 14/16] perf top: Separate struct perf_top_stats

From: Namhyung Kim
Date: Thu Dec 10 2015 - 02:55:55 EST


The perf top maintains various stats regarding samples. Separate out
those stats so that it can be updated concurrently.

Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
---
tools/perf/builtin-top.c | 36 ++++++++++++++++++++++++++++--------
tools/perf/util/top.c | 18 ++++++++----------
tools/perf/util/top.h | 12 ++++++++----
3 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5987986b5203..f3ab46b234b6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -902,8 +902,26 @@ struct reader_arg {
int idx;
struct perf_top *top;
struct hists *hists;
+ struct perf_top_stats stats;
};

+static void perf_top_stats__add(struct perf_top_stats *dst,
+ struct perf_top_stats *src)
+{
+ static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+ pthread_mutex_lock(&stats_lock);
+
+ dst->samples += src->samples;
+ dst->exact_samples += src->exact_samples;
+ dst->kernel_samples += src->kernel_samples;
+ dst->us_samples += src->us_samples;
+ dst->guest_kernel_samples += src->guest_kernel_samples;
+ dst->guest_us_samples += src->guest_us_samples;
+
+ pthread_mutex_unlock(&stats_lock);
+}
+
static void perf_event__process_sample(struct reader_arg *rarg,
const union perf_event *event,
struct perf_evsel *evsel,
@@ -938,7 +956,7 @@ static void perf_event__process_sample(struct reader_arg *rarg,
}

if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
- top->exact_samples++;
+ rarg->stats.exact_samples++;

if (perf_event__preprocess_sample(event, machine, &al, sample) < 0)
return;
@@ -1000,28 +1018,28 @@ static void perf_top__mmap_read(struct reader_arg *rarg)
origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

if (event->header.type == PERF_RECORD_SAMPLE)
- ++top->samples;
+ ++rarg->stats.samples;

switch (origin) {
case PERF_RECORD_MISC_USER:
- ++top->us_samples;
+ ++rarg->stats.us_samples;
if (top->hide_user_symbols)
goto next_event;
machine = &session->machines.host;
break;
case PERF_RECORD_MISC_KERNEL:
- ++top->kernel_samples;
+ ++rarg->stats.kernel_samples;
if (top->hide_kernel_symbols)
goto next_event;
machine = &session->machines.host;
break;
case PERF_RECORD_MISC_GUEST_KERNEL:
- ++top->guest_kernel_samples;
+ ++rarg->stats.guest_kernel_samples;
machine = perf_session__find_machine(session,
sample.pid);
break;
case PERF_RECORD_MISC_GUEST_USER:
- ++top->guest_us_samples;
+ ++rarg->stats.guest_us_samples;
/*
* TODO: we don't process guest user from host side
* except simple counting.
@@ -1065,12 +1083,14 @@ static void *mmap_read_worker(void *arg)
}

while (!done) {
- u64 hits = top->samples;
+ u64 hits = rarg->stats.samples;

perf_top__mmap_read(rarg);

- if (hits == top->samples)
+ if (hits == rarg->stats.samples)
perf_evlist__poll(top->evlist, 100);
+ else
+ perf_top_stats__add(&top->stats, &rarg->stats);
}
return NULL;
}
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 8e517def925b..95d6bba1a2a0 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -30,10 +30,10 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
struct target *target = &opts->target;
size_t ret = 0;

- if (top->samples) {
- samples_per_sec = top->samples / top->delay_secs;
- ksamples_per_sec = top->kernel_samples / top->delay_secs;
- esamples_percent = (100.0 * top->exact_samples) / top->samples;
+ if (top->stats.samples) {
+ samples_per_sec = top->stats.samples / top->delay_secs;
+ ksamples_per_sec = top->stats.kernel_samples / top->delay_secs;
+ esamples_percent = (100.0 * top->stats.exact_samples) / top->stats.samples;
} else {
samples_per_sec = ksamples_per_sec = esamples_percent = 0.0;
}
@@ -49,9 +49,9 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
" exact: %4.1f%% [", samples_per_sec,
ksamples_percent, esamples_percent);
} else {
- float us_samples_per_sec = top->us_samples / top->delay_secs;
- float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs;
- float guest_us_samples_per_sec = top->guest_us_samples / top->delay_secs;
+ float us_samples_per_sec = top->stats.us_samples / top->delay_secs;
+ float guest_kernel_samples_per_sec = top->stats.guest_kernel_samples / top->delay_secs;
+ float guest_us_samples_per_sec = top->stats.guest_us_samples / top->delay_secs;

ret = SNPRINTF(bf, size,
" PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%"
@@ -111,7 +111,5 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)

void perf_top__reset_sample_counters(struct perf_top *top)
{
- top->samples = top->us_samples = top->kernel_samples =
- top->exact_samples = top->guest_kernel_samples =
- top->guest_us_samples = 0;
+ memset(&top->stats, 0, sizeof(top->stats));
}
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index c56a00cff5b4..55eb5aebae59 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -11,18 +11,22 @@ struct perf_evlist;
struct perf_evsel;
struct perf_session;

+struct perf_top_stats {
+ u64 samples;
+ u64 exact_samples;
+ u64 kernel_samples, us_samples;
+ u64 guest_kernel_samples, guest_us_samples;
+};
+
struct perf_top {
struct perf_tool tool;
struct perf_evlist *evlist;
struct record_opts record_opts;
+ struct perf_top_stats stats;
/*
* Symbols will be added here in perf_event__process_sample and will
* get out after decayed.
*/
- u64 samples;
- u64 kernel_samples, us_samples;
- u64 exact_samples;
- u64 guest_us_samples, guest_kernel_samples;
int print_entries, count_filter, delay_secs;
int max_stack;
bool hide_kernel_symbols, hide_user_symbols, zero;
--
2.6.2

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