From patchwork Wed Feb 10 09:37:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 12080259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26DABC433DB for ; Wed, 10 Feb 2021 09:38:19 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9458E64DEE for ; Wed, 10 Feb 2021 09:38:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9458E64DEE Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 31FA66E1CE; Wed, 10 Feb 2021 09:38:18 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8667E6EB10; Wed, 10 Feb 2021 09:38:16 +0000 (UTC) IronPort-SDR: KoXvj0hvPTkStH6E2rA8IT7joPcaCz7jbo6Ya7DnrrJnkLXGmg8OuCE72D+avBW5YjC9cPb3Kd AOOfbK1ku18g== X-IronPort-AV: E=McAfee;i="6000,8403,9890"; a="179486360" X-IronPort-AV: E=Sophos;i="5.81,167,1610438400"; d="scan'208";a="179486360" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Feb 2021 01:38:16 -0800 IronPort-SDR: xj0846pMVQlVpJlSUJtwu7IIvOMdaXYAvOFfUKcKG4/AB02FARkz+F94EugZsLSfyR3bPFLmVR OHPg9gAJRSHA== X-IronPort-AV: E=Sophos;i="5.81,167,1610438400"; d="scan'208";a="488705241" Received: from baruchs-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.214.255.101]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Feb 2021 01:38:14 -0800 From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Wed, 10 Feb 2021 09:37:55 +0000 Message-Id: <20210210093756.61424-2-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210210093756.61424-1-tvrtko.ursulin@linux.intel.com> References: <20210210093756.61424-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 2/3] intel_gpu_top: Aggregate clients by PID by default X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Tvrtko Ursulin Implement a default view where clients are aggregated by their PID. Toggled by pressing 'H' similar to top(1). Signed-off-by: Tvrtko Ursulin --- man/intel_gpu_top.rst | 1 + tools/intel_gpu_top.c | 109 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 97 insertions(+), 13 deletions(-) diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst index b145d85c0440..20658e291db0 100644 --- a/man/intel_gpu_top.rst +++ b/man/intel_gpu_top.rst @@ -58,6 +58,7 @@ Supported keys: 'n' Toggle display of numeric client busyness overlay. 's' Toggle between sort modes (runtime, total runtime, pid, client id). 'i' Toggle display of clients which used no GPU time. + 'H' Toggle between per PID aggregation and individual clients. DEVICE SELECTION ================ diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c index 63ef77056341..018e28a66c10 100644 --- a/tools/intel_gpu_top.c +++ b/tools/intel_gpu_top.c @@ -979,17 +979,18 @@ static int client_pid_cmp(const void *_a, const void *_b) static int (*client_cmp)(const void *, const void *) = client_last_cmp; -static void sort_clients(struct clients *clients) +static struct clients *sort_clients(struct clients *clients, + int (*cmp)(const void *, const void *)) { unsigned int active, free; struct client *c; int tmp; if (!clients) - return; + return clients; qsort(clients->client, clients->num_clients, sizeof(*clients->client), - client_cmp); + cmp); /* Trim excessive array space. */ active = 0; @@ -1011,9 +1012,76 @@ static void sort_clients(struct clients *clients) sizeof(*c)); } } + + return clients; +} + +static struct clients *aggregated_clients(struct clients *clients) +{ + struct client *ac, *c, *cp = NULL; + struct clients *aggregated; + int tmp, num = 0; + + /* Sort by pid first to make it easy to aggregate while walking. */ + sort_clients(clients, client_pid_cmp); + + aggregated = calloc(1, sizeof(*clients)); + assert(aggregated); + + ac = calloc(clients->num_clients, sizeof(*c)); + assert(ac); + + aggregated->num_classes = clients->num_classes; + aggregated->class = clients->class; + aggregated->client = ac; + + for_each_client(clients, c, tmp) { + unsigned int i; + + if (c->status == FREE) + break; + + assert(c->status == ALIVE); + + if ((cp && c->pid != cp->pid) || !cp) { + ac = &aggregated->client[num]; + + /* New pid. */ + ac->clients = aggregated; + ac->status = ALIVE; + ac->id = ++num; + ac->pid = c->pid; + strcpy(ac->name, c->name); + strcpy(ac->print_name, c->print_name); + ac->engines = c->engines; + ac->val = calloc(clients->num_classes, + sizeof(ac->val[0])); + assert(ac->val); + ac->samples = 1; + } + + cp = c; + + if (c->samples < 2) + continue; + + ac->samples = 2; /* All what matters for display. */ + ac->total_runtime += c->total_runtime; + ac->last_runtime += c->last_runtime; + + for (i = 0; i < clients->num_classes; i++) + ac->val[i] += c->val[i]; + } + + aggregated->num_clients = num; + aggregated->active_clients = num; + + return sort_clients(aggregated, client_cmp); } -static void scan_clients(struct clients *clients) +static bool aggregate_pids = true; + +static struct clients *scan_clients(struct clients *clients) { struct dirent *dent; struct client *c; @@ -1022,7 +1090,7 @@ static void scan_clients(struct clients *clients) DIR *d; if (!clients) - return; + return clients; for_each_client(clients, c, tmp) { assert(c->status != PROBE); @@ -1034,7 +1102,7 @@ static void scan_clients(struct clients *clients) d = opendir(clients->sysfs_root); if (!d) - return; + return clients; while ((dent = readdir(d)) != NULL) { char name[24], pid[24]; @@ -1077,7 +1145,10 @@ static void scan_clients(struct clients *clients) break; } - sort_clients(clients); + if (aggregate_pids) + return aggregated_clients(clients); + else + return sort_clients(clients, client_cmp); } static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" }; @@ -2227,6 +2298,13 @@ static void process_stdin(unsigned int timeout_us) case 's': select_client_sort(); break; + case 'H': + aggregate_pids ^= true; + if (aggregate_pids) + header_msg = "Aggregating clients."; + else + header_msg = "Showing individual clients."; + break; }; } } @@ -2378,6 +2456,7 @@ int main(int argc, char **argv) codename = igt_device_get_pretty_name(&card, false); while (!stop_top) { + struct clients *disp_clients; bool consumed = false; int j, lines = 0; struct winsize ws; @@ -2400,7 +2479,7 @@ int main(int argc, char **argv) pmu_sample(engines); t = (double)(engines->ts.cur - engines->ts.prev) / 1e9; - scan_clients(clients); + disp_clients = scan_clients(clients); if (stop_top) break; @@ -2416,14 +2495,14 @@ int main(int argc, char **argv) lines = print_engines(engines, t, lines, con_w, con_h); - if (clients) { + if (disp_clients) { int class_w; - lines = print_clients_header(clients, lines, + lines = print_clients_header(disp_clients, lines, con_w, con_h, &class_w); - for_each_client(clients, c, j) { + for_each_client(disp_clients, c, j) { assert(c->status != PROBE); if (c->status != ALIVE) break; /* Active clients are first in the array. */ @@ -2437,8 +2516,9 @@ int main(int argc, char **argv) &class_w); } - lines = print_clients_footer(clients, t, lines, - con_w, con_h); + lines = print_clients_footer(disp_clients, t, + lines, con_w, + con_h); } pops->close_struct(); @@ -2447,6 +2527,9 @@ int main(int argc, char **argv) if (stop_top) break; + if (disp_clients != clients) + free(disp_clients); + if (output_mode == INTERACTIVE) process_stdin(period_us); else