Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752434AbdLFXdc (ORCPT ); Wed, 6 Dec 2017 18:33:32 -0500 Received: from mga14.intel.com ([192.55.52.115]:6562 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752326AbdLFXd3 (ORCPT ); Wed, 6 Dec 2017 18:33:29 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,370,1508828400"; d="scan'208";a="9735681" From: kan.liang@intel.com To: acme@kernel.org, peterz@infradead.org, mingo@redhat.com, linux-kernel@vger.kernel.org Cc: jolsa@kernel.org, wangnan0@huawei.com, namhyung@kernel.org, ak@linux.intel.com, yao.jin@linux.intel.com, Kan Liang Subject: [PATCH V2 7/8] perf top: switch default mode to overwrite mode Date: Wed, 6 Dec 2017 15:33:02 -0800 Message-Id: <1512603183-42754-8-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1512603183-42754-1-git-send-email-kan.liang@intel.com> References: <1512603183-42754-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6280 Lines: 179 From: Kan Liang perf_top__mmap_read has severe performance issue in Knights Landing/Mill, when monitoring in heavy load system. It costs several minutes to finish, which is unacceptable. Currently, perf top is non overwrite mode. For non overwrite mode, it tries to read everything in the ringbuffer and doesn't pause the ringbuffer. Once there are lots of samples delivered persistently, the processing time could be very long. Also, the latest samples could be lost when the ringbuffer is full. For overwrite mode, it takes a snapshot for the system by pausing the ringbuffer, which could significantly reducing the processing time. Also, the overwrite mode always keep the latest samples. Considering the real time requirement for perf top, the overwrite mode is more suitable for perf top. Actually, perf top was overwrite mode. It is changed to non overwrite mode since commit 93fc64f14472 ("perf top: Switch to non overwrite mode"). It's better to change it back to overwrite mode by default. For the kernel which doesn't support overwrite mode, it will fall back to non overwrite mode. There would be some records lost in overwrite mode because of pausing the ringbuffer. It has little impact for the accuracy of the snapshot and could be tolerant. The lost events checking is removed. For overwrite mode, unconditionally wait 100 ms before each snapshot. It also reduce the overhead caused by pausing ringbuffer, especially on light load system. Signed-off-by: Kan Liang --- tools/perf/builtin-top.c | 45 ++++++++++++++++++++++++------------------ tools/perf/ui/browsers/hists.c | 12 ++++++++--- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 7c462d6..02c0c7f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -283,16 +283,6 @@ static void perf_top__print_sym_table(struct perf_top *top) printf("%-*.*s\n", win_width, win_width, graph_dotted_line); - if (hists->stats.nr_lost_warned != - hists->stats.nr_events[PERF_RECORD_LOST]) { - hists->stats.nr_lost_warned = - hists->stats.nr_events[PERF_RECORD_LOST]; - color_fprintf(stdout, PERF_COLOR_RED, - "WARNING: LOST %d chunks, Check IO/CPU overload", - hists->stats.nr_lost_warned); - ++printed; - } - if (top->sym_filter_entry) { perf_top__show_details(top); return; @@ -807,15 +797,24 @@ static void perf_event__process_sample(struct perf_tool *tool, static void perf_top__mmap_read_idx(struct perf_top *top, int idx) { + struct record_opts *opts = &top->record_opts; + struct perf_evlist *evlist = top->evlist; struct perf_sample sample; struct perf_evsel *evsel; + struct perf_mmap *md; struct perf_session *session = top->session; union perf_event *event; struct machine *machine; + unsigned long size; + u64 end, start; int ret; - while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { - ret = perf_evlist__parse_sample(top->evlist, event, &sample); + md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx]; + if (perf_mmap__read_catchup(md, opts->overwrite, &start, &end, &size) < 1) + return; + + while ((event = perf_mmap__read_event(md, opts->overwrite, &start, end)) != NULL) { + ret = perf_evlist__parse_sample(evlist, event, &sample); if (ret) { pr_err("Can't parse sample, err = %d\n", ret); goto next_event; @@ -869,16 +868,28 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) } else ++session->evlist->stats.nr_unknown_events; next_event: - perf_evlist__mmap_consume(top->evlist, idx); + perf_mmap__consume(md, opts->overwrite); } + + perf_mmap__read_done(md); } static void perf_top__mmap_read(struct perf_top *top) { + bool overwrite = top->record_opts.overwrite; + struct perf_evlist *evlist = top->evlist; int i; + if (overwrite) + perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_DATA_PENDING); + for (i = 0; i < top->evlist->nr_mmaps; i++) perf_top__mmap_read_idx(top, i); + + if (overwrite) { + perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); + perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING); + } } /* @@ -966,11 +977,6 @@ static int perf_top__start_counters(struct perf_top *top) goto out_err; } - if (opts->overwrite) { - ui__error("not support overwrite mode yet\n"); - goto out_err; - } - evlist__for_each_entry(evlist, counter) { try_again: if (perf_evsel__open(counter, top->evlist->cpus, @@ -1128,7 +1134,7 @@ static int __cmd_top(struct perf_top *top) perf_top__mmap_read(top); - if (hits == top->samples) + if (opts->overwrite || (hits == top->samples)) ret = perf_evlist__poll(top->evlist, 100); if (resize) { @@ -1222,6 +1228,7 @@ int cmd_top(int argc, const char **argv) .uses_mmap = true, }, .proc_map_timeout = 500, + .overwrite = 1, }, .max_stack = sysctl_perf_event_max_stack, .sym_pcnt_filter = 5, diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 68146f4..56023e4 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -638,8 +638,13 @@ int hist_browser__run(struct hist_browser *browser, const char *help) nr_entries = hist_browser__nr_entries(browser); ui_browser__update_nr_entries(&browser->b, nr_entries); - if (browser->hists->stats.nr_lost_warned != - browser->hists->stats.nr_events[PERF_RECORD_LOST]) { + /* + * Don't print lost events warning for perf top, + * because it is overwrite mode. + * Perf top is the only tool which has hbt timer. + */ + if ((browser->hists->stats.nr_lost_warned != + browser->hists->stats.nr_events[PERF_RECORD_LOST]) && !hbt) { browser->hists->stats.nr_lost_warned = browser->hists->stats.nr_events[PERF_RECORD_LOST]; ui_browser__warn_lost_events(&browser->b); @@ -3203,7 +3208,8 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, case K_TIMER: hbt->timer(hbt->arg); - if (!menu->lost_events_warned && menu->lost_events) { + if (!menu->lost_events_warned && + menu->lost_events && !hbt) { ui_browser__warn_lost_events(&menu->b); menu->lost_events_warned = true; } -- 2.5.5