Hi Tvrtko,
On 2023-10-12 at 09:15:46 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursu...@intel.com>
> 
> JSON output has the full breakdown but for now the interactive mode only
> shows total and resident aggregated for all memory regions.
> 
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursu...@intel.com>

Reviewed-by: Kamil Konieczny <kamil.koniec...@linux.intel.com>

> ---
>  tools/intel_gpu_top.c | 114 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 112 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index b2e81d5f9ffb..2c09895c79dd 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -133,11 +133,24 @@ struct intel_clients {
>       const char *pci_slot;
>       struct igt_drm_client_engines classes;
>       struct igt_drm_clients *clients;
> +     struct igt_drm_client_regions *regions; /* Borrowed from first client */
>  };
>  
>  static struct termios termios_orig;
>  static bool class_view;
>  
> +/* Maps i915 fdinfo names to indices */
> +static const char *memory_region_map[] = {
> +     "system0",
> +     "local0",
> +};
> +
> +/* For JSON, 1:1 with indices above. */
> +static const char *json_memory_region_names[] = {
> +     "system",
> +     "local",
> +};
> +
>  __attribute__((format(scanf,3,4)))
>  static int igt_sysfs_scanf(int dir, const char *attr, const char *fmt, ...)
>  {
> @@ -882,6 +895,9 @@ static struct igt_drm_clients *display_clients(struct 
> igt_drm_clients *clients)
>                       ac->val = calloc(c->engines->max_engine_id + 1,
>                                        sizeof(ac->val[0]));
>                       assert(ac->val);
> +                     ac->regions = c->regions;
> +                     ac->memory = calloc(c->regions->max_region_id + 1,
> +                                         sizeof(ac->memory[0]));
>                       ac->samples = 1;
>               }
>  
> @@ -896,6 +912,14 @@ static struct igt_drm_clients *display_clients(struct 
> igt_drm_clients *clients)
>  
>               for (i = 0; i <= c->engines->max_engine_id; i++)
>                       ac->val[i] += c->val[i];
> +
> +             for (i = 0; i <= c->regions->max_region_id; i++) {
> +                     ac->memory[i].total += c->memory[i].total;
> +                     ac->memory[i].shared += c->memory[i].shared;
> +                     ac->memory[i].resident += c->memory[i].resident;
> +                     ac->memory[i].purgeable += c->memory[i].purgeable;
> +                     ac->memory[i].active += c->memory[i].active;
> +             }
>       }
>  
>       aggregated->num_clients = num;
> @@ -920,8 +944,10 @@ static void free_display_clients(struct igt_drm_clients 
> *clients)
>        * "display" clients are not proper clients and have un-initialized
>        * or borrowed fields which we don't want the library to try and free.
>        */
> -     igt_for_each_drm_client(clients, c, tmp)
> +     igt_for_each_drm_client(clients, c, tmp) {
>               free(c->val);
> +             free(c->memory);
> +     }
>  
>       free(clients->client);
>       free(clients);
> @@ -2016,6 +2042,9 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>               if (lines++ >= con_h || len >= con_w)
>                       return lines;
>  
> +             if (iclients->regions)
> +                     len += printf("     MEM      RSS ");
> +
>               if (iclients->classes.num_engines) {
>                       unsigned int i;
>                       int width;
> @@ -2059,6 +2088,20 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>  static bool numeric_clients;
>  static bool filter_idle;
>  
> +static int print_size(uint64_t sz)
> +{
> +     char units[] = { ' ', 'K', 'M', 'G' };
> +     unsigned int u;
> +
> +     for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> +             if (sz & 1023 || sz < 1024)
> +                     break;
> +             sz /= 1024;
> +     }
> +
> +     return printf("%7"PRIu64"%c ", sz, units[u]);
> +}
> +
>  static int
>  print_client(struct igt_drm_client *c, struct engines *engines, double t, 
> int lines,
>            int con_w, int con_h, unsigned int period_us, int *class_w)
> @@ -2076,6 +2119,18 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>  
>               len = printf("%*s ", clients->max_pid_len, c->pid_str);
>  
> +             if (iclients->regions) {
> +                     uint64_t sz;
> +
> +                     for (sz = 0, i = 0; i <= c->regions->max_region_id; i++)
> +                             sz += c->memory[i].total;
> +                     len += print_size(sz);
> +
> +                     for (sz = 0, i = 0; i <= c->regions->max_region_id; i++)
> +                             sz += c->memory[i].resident;
> +                     len += print_size(sz);
> +             }
> +
>               for (i = 0; i <= iclients->classes.max_engine_id; i++) {
>                       double pct, max;
>  
> @@ -2115,6 +2170,42 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>               snprintf(buf, sizeof(buf), "%u", c->pid);
>               __json_add_member("pid", buf);
>  
> +             if (iclients->regions) {
> +                     pops->open_struct("memory");
> +
> +                     for (i = 0; i < ARRAY_SIZE(json_memory_region_names);
> +                          i++) {
> +                             if (i > c->regions->max_region_id)
> +                                     break;
> +
> +                             pops->open_struct(json_memory_region_names[i]);
> +
> +                             snprintf(buf, sizeof(buf), "%" PRIu64,
> +                                      c->memory[i].total);
> +                             __json_add_member("total", buf);
> +
> +                             snprintf(buf, sizeof(buf), "%" PRIu64,
> +                                      c->memory[i].shared);
> +                             __json_add_member("shared", buf);
> +
> +                             snprintf(buf, sizeof(buf), "%" PRIu64,
> +                                      c->memory[i].resident);
> +                             __json_add_member("resident", buf);
> +
> +                             snprintf(buf, sizeof(buf), "%" PRIu64,
> +                                      c->memory[i].purgeable);
> +                             __json_add_member("purgeable", buf);
> +
> +                             snprintf(buf, sizeof(buf), "%" PRIu64,
> +                                      c->memory[i].active);
> +                             __json_add_member("active", buf);
> +
> +                             pops->close_struct();
> +                     }
> +
> +                     pops->close_struct();
> +             }
> +
>               if (c->samples > 1) {
>                       pops->open_struct("engine-classes");
>  
> @@ -2460,10 +2551,29 @@ static void intel_scan_clients(struct intel_clients 
> *iclients)
>               "video-enhance",
>               "compute",
>       };
> +     struct igt_drm_client *c;
> +     unsigned int i;
>  
>       igt_drm_clients_scan(iclients->clients, client_match,
>                            engine_map, ARRAY_SIZE(engine_map),
> -                          NULL, 0);
> +                          memory_region_map, ARRAY_SIZE(memory_region_map));
> +
> +     iclients->regions = NULL;
> +
> +     if (!iclients->clients)
> +             return;
> +
> +     /*
> +      * Borrow memory region data from first client so we can use it
> +      * when displaying stuff. All regions are the same due our client_match.
> +      */
> +     igt_for_each_drm_client(iclients->clients, c, i) {
> +             if (c->status == IGT_DRM_CLIENT_ALIVE) {
> +                     if (c->regions->num_regions)
> +                             iclients->regions = c->regions;
> +                     break;
> +             }
> +     }
>  }
>  
>  int main(int argc, char **argv)
> -- 
> 2.39.2
> 

Reply via email to