Re: [Intel-gfx] [PATCH i-g-t] intel-gpu-top: Add support for per client stats

2021-12-06 Thread Tvrtko Ursulin



On 04/12/2021 01:38, Dixit, Ashutosh wrote:

On Fri, 03 Dec 2021 07:54:56 -0800, Tvrtko Ursulin wrote:


From: Tvrtko Ursulin 

Use the i915 exported data in /proc//fdinfo to show GPU utilization
per DRM client.


Didn't we just remove it? Adding it back now? Sorry for the probably dumb
question :/


Same feature two implementation flavours. :) Removed the version using 
API removed from i915 back in April (or so), proposing to add a version 
using different API (https://patchwork.freedesktop.org/series/92574/).


Regards,

Tvrtko


Re: [Intel-gfx] [PATCH i-g-t] intel-gpu-top: Add support for per client stats

2021-12-03 Thread Dixit, Ashutosh
On Fri, 03 Dec 2021 07:54:56 -0800, Tvrtko Ursulin wrote:
>
> From: Tvrtko Ursulin 
>
> Use the i915 exported data in /proc//fdinfo to show GPU utilization
> per DRM client.

Didn't we just remove it? Adding it back now? Sorry for the probably dumb
question :/


[Intel-gfx] [PATCH i-g-t] intel-gpu-top: Add support for per client stats

2021-12-03 Thread Tvrtko Ursulin
From: Tvrtko Ursulin 

Use the i915 exported data in /proc//fdinfo to show GPU utilization
per DRM client.

Example of the output:

intel-gpu-top: Intel Tigerlake (Gen12) @ /dev/dri/card0 -  220/ 221 MHz
70% RC6;  0.62/ 7.08 W;  760 irqs/s

 ENGINES BUSY MI_SEMA MI_WAIT
   Render/3D   23.06% |██▊  |  0%  0%
 Blitter0.00% | |  0%  0%
   Video5.40% |█▋   |  0%  0%
VideoEnhance   20.67% |██   |  0%  0%

   PID  NAME  Render/3DBlitter  VideoVideoEnhance
  3082   mpv |  ||  ||▌ ||██|
  3117 neverball |█▉||  ||  ||  |
 1   systemd |▍ ||  ||  ||  |
  2338   gnome-shell |  ||  ||  ||  |

Signed-off-by: Tvrtko Ursulin 
---
 man/intel_gpu_top.rst |   4 +
 tools/intel_gpu_top.c | 866 +-
 2 files changed, 868 insertions(+), 2 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index b3b765b05feb..f4dbfc5b44d9 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -56,6 +56,10 @@ Supported keys:
 'q'Exit from the tool.
 'h'Show interactive help.
 '1'Toggle between aggregated engine class and physical engine mode.
+'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 81c724d1fe1c..5c9a195ea275 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "igt_perf.h"
 
@@ -309,7 +310,8 @@ static int engine_cmp(const void *__a, const void *__b)
return a->instance - b->instance;
 }
 
-#define is_igpu_pci(x) (strcmp(x, ":00:02.0") == 0)
+#define IGPU_PCI ":00:02.0"
+#define is_igpu_pci(x) (strcmp(x, IGPU_PCI) == 0)
 #define is_igpu(x) (strcmp(x, "i915") == 0)
 
 static struct engines *discover_engines(char *device)
@@ -633,6 +635,613 @@ static void pmu_sample(struct engines *engines)
}
 }
 
+enum client_status {
+   FREE = 0, /* mbz */
+   ALIVE,
+   PROBE
+};
+
+struct clients;
+
+struct client {
+   struct clients *clients;
+
+   enum client_status status;
+   unsigned int id;
+   unsigned int pid;
+   char name[24];
+   char print_name[24];
+   unsigned int samples;
+   unsigned long total_runtime;
+   unsigned long last_runtime;
+   struct engines *engines;
+   unsigned long *val;
+   uint64_t *last;
+};
+
+struct clients {
+   unsigned int num_clients;
+   unsigned int active_clients;
+
+   unsigned int num_classes;
+   struct engine_class *class;
+
+   char pci_slot[64];
+
+   struct client *client;
+};
+
+#define for_each_client(clients, c, tmp) \
+   for ((tmp) = (clients)->num_clients, c = (clients)->client; \
+(tmp > 0); (tmp)--, (c)++)
+
+static struct clients *init_clients(const char *pci_slot)
+{
+   struct clients *clients;
+
+   clients = malloc(sizeof(*clients));
+   if (!clients)
+   return NULL;
+
+   memset(clients, 0, sizeof(*clients));
+
+   strncpy(clients->pci_slot, pci_slot, sizeof(clients->pci_slot));
+
+   return clients;
+}
+
+static struct client *
+find_client(struct clients *clients, enum client_status status, unsigned int 
id)
+{
+   unsigned int start, num;
+   struct client *c;
+
+   start = status == FREE ? clients->active_clients : 0; /* Free block at 
the end. */
+   num = clients->num_clients - start;
+
+   for (c = >client[start]; num; c++, num--) {
+   if (status != c->status)
+   continue;
+
+   if (status == FREE || c->id == id)
+   return c;
+   }
+
+   return NULL;
+}
+
+static void
+update_client(struct client *c, unsigned int pid, char *name, uint64_t val[16])
+{
+   unsigned int i;
+
+   if (c->pid != pid)
+   c->pid = pid;
+
+   if (strcmp(c->name, name)) {
+   char *p;
+
+   strncpy(c->name, name, sizeof(c->name) - 1);
+   strncpy(c->print_name, name, sizeof(c->print_name) - 1);
+
+   p = c->print_name;
+   while (*p) {
+   if (!isprint(*p))
+   *p = '*';
+   p++;
+   }
+   }
+
+   c->last_runtime = 0;
+   c->total_runtime = 0;
+
+   for (i = 0; i <