diff mbox series

[i-g-t,9/9] tools/intel_gpu_top: Add ability to show memory region breakdown

Message ID 20231012081547.852052-10-tvrtko.ursulin@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series Client memory fdinfo test and intel_gpu_top support | expand

Commit Message

Tvrtko Ursulin Oct. 12, 2023, 8:15 a.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Similar as we can toggle between aggregated engines and clients, add the
capability to toggle between aggregated and per memory region stats.

It starts in aggregated mode by default and interactive command 'm' and
command line switch '-m' can be used to toggle that.

Both only affect the interactive view, while JSON output always contains
separate memory regions.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 man/intel_gpu_top.rst |  4 ++++
 tools/intel_gpu_top.c | 55 ++++++++++++++++++++++++++++++++++---------
 2 files changed, 48 insertions(+), 11 deletions(-)

Comments

Kamil Konieczny Nov. 3, 2023, 7:04 p.m. UTC | #1
Hi Tvrtko,
On 2023-10-12 at 09:15:47 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> Similar as we can toggle between aggregated engines and clients, add the
> capability to toggle between aggregated and per memory region stats.
> 
> It starts in aggregated mode by default and interactive command 'm' and
> command line switch '-m' can be used to toggle that.
> 
> Both only affect the interactive view, while JSON output always contains
> separate memory regions.
> 
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

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

> ---
>  man/intel_gpu_top.rst |  4 ++++
>  tools/intel_gpu_top.c | 55 ++++++++++++++++++++++++++++++++++---------
>  2 files changed, 48 insertions(+), 11 deletions(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index 9499f87f1b4d..44a54a5f219d 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -55,6 +55,9 @@ OPTIONS
>  -p
>     Default to showing physical engines instead of aggregated classes.
>  
> +-m
> +   Default to showing all memory regions separately.
> +
>  RUNTIME CONTROL
>  ===============
>  
> @@ -68,6 +71,7 @@ Supported keys:
>  |    '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.
> +|    'm'    Toggle between aggregated memory regions and full breakdown.
>  
>  DEVICE SELECTION
>  ================
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 2c09895c79dd..046ead15a122 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -138,6 +138,7 @@ struct intel_clients {
>  
>  static struct termios termios_orig;
>  static bool class_view;
> +static bool aggregate_regions;
>  
>  /* Maps i915 fdinfo names to indices */
>  static const char *memory_region_map[] = {
> @@ -1050,6 +1051,7 @@ usage(const char *appname)
>  		"\t[-L]            List all cards.\n"
>  		"\t[-d <device>]   Device filter, please check manual page for more details.\n"
>  		"\t[-p]            Default to showing physical engines instead of classes.\n"
> +		"\t[-m]            Default to showing all memory regions.\n"
>  		"\n",
>  		appname, DEFAULT_PERIOD_MS);
>  	igt_device_print_filter_types();
> @@ -2032,6 +2034,7 @@ print_clients_header(struct igt_drm_clients *clients, int lines,
>  
>  	if (output_mode == INTERACTIVE) {
>  		int len, num_active = 0;
> +		unsigned int i;
>  
>  		if (lines++ >= con_h)
>  			return lines;
> @@ -2042,11 +2045,17 @@ 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->regions) {
> +			if (aggregate_regions) {
> +				len += printf("     MEM      RSS ");
> +			} else {
> +				len += printf("     RAM      RSS ");
> +				if (iclients->regions->num_regions > 1)
> +					len += printf("    VRAM     VRSS ");
> +			}
> +		}
>  
>  		if (iclients->classes.num_engines) {
> -			unsigned int i;
>  			int width;
>  
>  			for (i = 0; i <= iclients->classes.max_engine_id; i++) {
> @@ -2120,15 +2129,26 @@ 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;
> +			if (aggregate_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].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 (sz = 0, i = 0;
> +				     i <= c->regions->max_region_id; i++)
> +					sz += c->memory[i].resident;
> +				len += print_size(sz);
> +			} else {
> +				len += print_size(c->memory[0].total);
> +				len += print_size(c->memory[0].resident);
> +				if (c->regions->num_regions > 1) {
> +					len += print_size(c->memory[1].total);
> +					len += print_size(c->memory[1].resident);
> +				}
> +			}
>  		}
>  
>  		for (i = 0; i <= iclients->classes.max_engine_id; i++) {
> @@ -2405,6 +2425,13 @@ static void process_normal_stdin(void)
>  			else
>  				header_msg = "Showing individual clients.";
>  			break;
> +		case 'm':
> +			aggregate_regions ^= true;
> +			if (aggregate_regions)
> +				header_msg = "Aggregating memory regions.";
> +			else
> +				header_msg = "Showing memory regions.";
> +			break;
>  		};
>  	}
>  }
> @@ -2453,6 +2480,7 @@ static void show_help_screen(void)
>  "    's'    Toggle between sort modes (runtime, total runtime, pid, client id).\n"
>  "    'i'    Toggle display of clients which used no GPU time.\n"
>  "    'H'    Toggle between per PID aggregation and individual clients.\n"
> +"    'm'    Toggle between aggregated memory regions and full breakdown.\n"
>  "\n"
>  "    'h' or 'q'    Exit interactive help.\n"
>  "\n");
> @@ -2580,6 +2608,7 @@ int main(int argc, char **argv)
>  {
>  	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
>  	bool physical_engines = false;
> +	bool separate_regions = false;
>  	struct intel_clients iclients;
>  	int con_w = -1, con_h = -1;
>  	char *output_path = NULL;
> @@ -2592,7 +2621,7 @@ int main(int argc, char **argv)
>  	struct timespec ts;
>  
>  	/* Parse options */
> -	while ((ch = getopt(argc, argv, "o:s:d:pcJLlh")) != -1) {
> +	while ((ch = getopt(argc, argv, "o:s:d:mpcJLlh")) != -1) {
>  		switch (ch) {
>  		case 'o':
>  			output_path = optarg;
> @@ -2606,6 +2635,9 @@ int main(int argc, char **argv)
>  		case 'p':
>  			physical_engines = true;
>  			break;
> +		case 'm':
> +			separate_regions = true;
> +			break;
>  		case 'c':
>  			output_mode = CSV;
>  			break;
> @@ -2649,6 +2681,7 @@ int main(int argc, char **argv)
>  		fprintf(stderr, "Failed to install signal handler!\n");
>  
>  	class_view = !physical_engines;
> +	aggregate_regions = !separate_regions;
>  
>  	switch (output_mode) {
>  	case INTERACTIVE:
> -- 
> 2.39.2
>
diff mbox series

Patch

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index 9499f87f1b4d..44a54a5f219d 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -55,6 +55,9 @@  OPTIONS
 -p
    Default to showing physical engines instead of aggregated classes.
 
+-m
+   Default to showing all memory regions separately.
+
 RUNTIME CONTROL
 ===============
 
@@ -68,6 +71,7 @@  Supported keys:
 |    '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.
+|    'm'    Toggle between aggregated memory regions and full breakdown.
 
 DEVICE SELECTION
 ================
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 2c09895c79dd..046ead15a122 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -138,6 +138,7 @@  struct intel_clients {
 
 static struct termios termios_orig;
 static bool class_view;
+static bool aggregate_regions;
 
 /* Maps i915 fdinfo names to indices */
 static const char *memory_region_map[] = {
@@ -1050,6 +1051,7 @@  usage(const char *appname)
 		"\t[-L]            List all cards.\n"
 		"\t[-d <device>]   Device filter, please check manual page for more details.\n"
 		"\t[-p]            Default to showing physical engines instead of classes.\n"
+		"\t[-m]            Default to showing all memory regions.\n"
 		"\n",
 		appname, DEFAULT_PERIOD_MS);
 	igt_device_print_filter_types();
@@ -2032,6 +2034,7 @@  print_clients_header(struct igt_drm_clients *clients, int lines,
 
 	if (output_mode == INTERACTIVE) {
 		int len, num_active = 0;
+		unsigned int i;
 
 		if (lines++ >= con_h)
 			return lines;
@@ -2042,11 +2045,17 @@  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->regions) {
+			if (aggregate_regions) {
+				len += printf("     MEM      RSS ");
+			} else {
+				len += printf("     RAM      RSS ");
+				if (iclients->regions->num_regions > 1)
+					len += printf("    VRAM     VRSS ");
+			}
+		}
 
 		if (iclients->classes.num_engines) {
-			unsigned int i;
 			int width;
 
 			for (i = 0; i <= iclients->classes.max_engine_id; i++) {
@@ -2120,15 +2129,26 @@  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;
+			if (aggregate_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].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 (sz = 0, i = 0;
+				     i <= c->regions->max_region_id; i++)
+					sz += c->memory[i].resident;
+				len += print_size(sz);
+			} else {
+				len += print_size(c->memory[0].total);
+				len += print_size(c->memory[0].resident);
+				if (c->regions->num_regions > 1) {
+					len += print_size(c->memory[1].total);
+					len += print_size(c->memory[1].resident);
+				}
+			}
 		}
 
 		for (i = 0; i <= iclients->classes.max_engine_id; i++) {
@@ -2405,6 +2425,13 @@  static void process_normal_stdin(void)
 			else
 				header_msg = "Showing individual clients.";
 			break;
+		case 'm':
+			aggregate_regions ^= true;
+			if (aggregate_regions)
+				header_msg = "Aggregating memory regions.";
+			else
+				header_msg = "Showing memory regions.";
+			break;
 		};
 	}
 }
@@ -2453,6 +2480,7 @@  static void show_help_screen(void)
 "    's'    Toggle between sort modes (runtime, total runtime, pid, client id).\n"
 "    'i'    Toggle display of clients which used no GPU time.\n"
 "    'H'    Toggle between per PID aggregation and individual clients.\n"
+"    'm'    Toggle between aggregated memory regions and full breakdown.\n"
 "\n"
 "    'h' or 'q'    Exit interactive help.\n"
 "\n");
@@ -2580,6 +2608,7 @@  int main(int argc, char **argv)
 {
 	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
 	bool physical_engines = false;
+	bool separate_regions = false;
 	struct intel_clients iclients;
 	int con_w = -1, con_h = -1;
 	char *output_path = NULL;
@@ -2592,7 +2621,7 @@  int main(int argc, char **argv)
 	struct timespec ts;
 
 	/* Parse options */
-	while ((ch = getopt(argc, argv, "o:s:d:pcJLlh")) != -1) {
+	while ((ch = getopt(argc, argv, "o:s:d:mpcJLlh")) != -1) {
 		switch (ch) {
 		case 'o':
 			output_path = optarg;
@@ -2606,6 +2635,9 @@  int main(int argc, char **argv)
 		case 'p':
 			physical_engines = true;
 			break;
+		case 'm':
+			separate_regions = true;
+			break;
 		case 'c':
 			output_mode = CSV;
 			break;
@@ -2649,6 +2681,7 @@  int main(int argc, char **argv)
 		fprintf(stderr, "Failed to install signal handler!\n");
 
 	class_view = !physical_engines;
+	aggregate_regions = !separate_regions;
 
 	switch (output_mode) {
 	case INTERACTIVE: