[PATCH 37/38] perf session: Handle index files generally

From: Namhyung Kim
Date: Mon Mar 02 2015 - 22:12:46 EST


The current code assumes that the number of index item and cpu are
matched so it creates that number of threads. But it's not the case
of non-system-wide session or data came from different machine.

Just creates threads at most number of online cpus and process data.

Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
---
tools/perf/util/session.c | 76 +++++++++++++++++++++++++++++++++--------------
tools/perf/util/tool.h | 1 -
2 files changed, 54 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a9e3dd309d4d..3c999bae8e52 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1501,26 +1501,51 @@ static struct ui_progress_ops mt_progress__ops = {
.update = mt_progress__update,
};

+static int perf_session__get_index(struct perf_session *session)
+{
+ int ret;
+ static unsigned index = 1;
+ static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
+
+ pthread_mutex_lock(&idx_lock);
+ if (index < session->header.nr_index)
+ ret = index++;
+ else
+ ret = -1;
+ pthread_mutex_unlock(&idx_lock);
+
+ return ret;
+}
+
static void *processing_thread_idx(void *arg)
{
struct perf_tool_mt *mt_tool = arg;
struct perf_session *session = mt_tool->session;
int fd = perf_data_file__fd(session->file);
- u64 offset = session->header.index[mt_tool->idx].offset;
- u64 size = session->header.index[mt_tool->idx].size;
u64 file_size = perf_data_file__size(session->file);
+ int idx;

- ui_progress__init(&mt_tool->prog, size, "");
+ while ((idx = perf_session__get_index(session)) >= 0) {
+ u64 offset = session->header.index[idx].offset;
+ u64 size = session->header.index[idx].size;
+ struct perf_tool_mt *mtt = &mt_tool[idx];

- pr_debug("processing samples using thread [%d]\n", mt_tool->idx);
- if (__perf_session__process_events(session, &mt_tool->stats,
- fd, offset, size, file_size,
- &mt_tool->tool, &mt_tool->prog) < 0) {
- pr_err("processing samples failed (thread [%d])\n", mt_tool->idx);
- return NULL;
+ if (size == 0)
+ continue;
+
+ pr_debug("processing samples [index %d]\n", idx);
+
+ ui_progress__init(&mtt->prog, size, "");
+
+ if (__perf_session__process_events(session, &mtt->stats,
+ fd, offset, size, file_size,
+ &mtt->tool, &mtt->prog) < 0) {
+ pr_err("processing samples failed [index %d]\n", idx);
+ return NULL;
+ }
+ pr_debug("processing samples done [index %d]\n", idx);
}

- pr_debug("processing samples done for thread [%d]\n", mt_tool->idx);
return arg;
}

@@ -1538,6 +1563,7 @@ int perf_session__process_events_mt(struct perf_session *session,
int err, i, k;
int nr_index = session->header.nr_index;
u64 size = perf_data_file__size(file);
+ int nr_thread = sysconf(_SC_NPROCESSORS_ONLN);

if (perf_data_file__is_pipe(file) || !session->header.index) {
pr_err("data file doesn't contain the index table\n");
@@ -1561,15 +1587,11 @@ int perf_session__process_events_mt(struct perf_session *session,
ui_progress__ops = &mt_progress__ops;
ui_progress__ops->finish = orig_progress__ops->finish;

- th_id = calloc(nr_index, sizeof(*th_id));
- if (th_id == NULL)
- goto out;
-
mt_tools = calloc(nr_index, sizeof(*mt_tools));
if (mt_tools == NULL)
goto out;

- for (i = 1; i < nr_index; i++) {
+ for (i = 0; i < nr_index; i++) {
mt = &mt_tools[i];

memcpy(&mt->tool, tool, sizeof(*tool));
@@ -1583,20 +1605,30 @@ int perf_session__process_events_mt(struct perf_session *session,

mt->session = session;
mt->tool.ordered_events = false;
- mt->idx = i;
mt->priv = arg;
mt->global_prog = &prog;
-
- pthread_create(&th_id[i], NULL, processing_thread_idx, mt);
}

- for (i = 1; i < nr_index; i++) {
+ if (nr_thread > nr_index - 1)
+ nr_thread = nr_index - 1;
+
+ th_id = calloc(nr_thread, sizeof(*th_id));
+ if (th_id == NULL)
+ goto out;
+
+ for (i = 0; i < nr_thread; i++)
+ pthread_create(&th_id[i], NULL, processing_thread_idx, mt_tools);
+
+ for (i = 0; i < nr_thread; i++) {
pthread_join(th_id[i], (void **)&mt);
if (mt == NULL) {
err = -EINVAL;
continue;
}
+ }

+ for (i = 0; i < nr_index; i++) {
+ mt = &mt_tools[i];
events_stats__add(&evlist->stats, &mt->stats);

evlist__for_each(evlist, evsel) {
@@ -1612,7 +1644,7 @@ int perf_session__process_events_mt(struct perf_session *session,
ui_progress__ops = orig_progress__ops;
ui_progress__init(&prog, nr_entries, "Merging related events...");

- for (i = 1; i < nr_index; i++) {
+ for (i = 0; i < nr_index; i++) {
mt = &mt_tools[i];

evlist__for_each(evlist, evsel) {
@@ -1640,7 +1672,7 @@ int perf_session__process_events_mt(struct perf_session *session,
perf_tool__warn_about_errors(tool, &evlist->stats);

if (mt_tools) {
- for (i = 1; i < nr_index; i++)
+ for (i = 0; i < nr_index; i++)
free(mt_tools[i].hists);
free(mt_tools);
}
@@ -1649,7 +1681,7 @@ int perf_session__process_events_mt(struct perf_session *session,
return err;

err:
- while (i-- > 1) {
+ while (i-- > 0) {
pthread_cancel(th_id[i]);
pthread_join(th_id[i], NULL);
}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index aa7f110b9425..e52c936d1b9e 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -55,7 +55,6 @@ struct perf_tool_mt {
struct perf_session *session;
struct ui_progress prog;
struct ui_progress *global_prog;
- int idx;

void *priv;
};
--
2.2.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/