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

From: Namhyung Kim
Date: Sun May 17 2015 - 20:43: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 | 79 ++++++++++++++++++++++++++++++++++-------------
tools/perf/util/tool.h | 1 -
2 files changed, 58 insertions(+), 22 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index dcb9747bbb49..5f6c319bd236 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1679,25 +1679,50 @@ 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 idx = 1;
+ static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
+
+ pthread_mutex_lock(&idx_lock);
+ if (idx < session->header.nr_index)
+ ret = idx++;
+ 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;
- 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,
- offset, size, file_size,
- &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(mtt->session, &mtt->stats,
+ offset, size, file_size,
+ &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;
}

@@ -1717,6 +1742,7 @@ int perf_session__process_events_mt(struct perf_session *session, void *arg)
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");
@@ -1753,15 +1779,18 @@ int perf_session__process_events_mt(struct perf_session *session, void *arg)

tool->ordered_events = false;

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

+ ms->tool = &mt->tool;
ms->file = session->file;
ms->evlist = session->evlist;
ms->header = session->header;
ms->tevent = session->tevent;
+ ms->machines = session->machines;

+ ordered_events__init(&ms->ordered_events, NULL);
memcpy(&mt->tool, tool, sizeof(*tool));

mt->hists = calloc(evlist->nr_entries, sizeof(*mt->hists));
@@ -1772,20 +1801,28 @@ int perf_session__process_events_mt(struct perf_session *session, void *arg)
__hists__init(&mt->hists[k]);

mt->session = ms;
- 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) {
+ 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) {
@@ -1801,7 +1838,7 @@ int perf_session__process_events_mt(struct perf_session *session, void *arg)
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) {
@@ -1829,7 +1866,7 @@ int perf_session__process_events_mt(struct perf_session *session, void *arg)
perf_session__warn_about_errors(session, &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);
}
@@ -1839,7 +1876,7 @@ int perf_session__process_events_mt(struct perf_session *session, void *arg)
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 144a414b1d5b..c96e805b9ff4 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -69,7 +69,6 @@ struct perf_tool_mt {
struct perf_session *session;
struct ui_progress prog;
struct ui_progress *global_prog;
- int idx;

void *priv;
};
--
2.4.0

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