diff mbox

cpupower, add option to display frequencies and latencies without rounding off values

Message ID 1398349927-18684-1-git-send-email-prarit@redhat.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Prarit Bhargava April 24, 2014, 2:32 p.m. UTC
The command "cpupower frequency-info" can be used when using cpupower to
monitor and test processor behaviour to determine if the processor is
behaving as expected.  This data can be compared to the output of
/proc/cpuinfo or the output of
/sys/devices/system/cpu/cpuX/cpufreq/scaling_available_frequencies
to determine if the cpu is in an expected state.

When doing this I noticed comparison test failures due to the way the
data is displayed in cpupower.  For example,

[root@intel-s3e37-02 cpupower]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
2262000 2261000 2128000 1995000 1862000 1729000 1596000 1463000 1330000
1197000 1064000

compared to

[root@intel-s3e37-02 cpupower]# cpupower frequency-info
analyzing CPU 0:
  driver: acpi-cpufreq
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 10.0 us.
  hardware limits: 1.06 GHz - 2.26 GHz
  available frequency steps: 2.26 GHz, 2.26 GHz, 2.13 GHz, 2.00 GHz, 1.86 GHz, 1.73 GHz, 1.60 GHz, 1.46 GHz, 1.33 GHz, 1.20 GHz, 1.06 GHz
  available cpufreq governors: conservative, userspace, powersave, ondemand, performance
  current policy: frequency should be within 1.06 GHz and 2.26 GHz.
                  The governor "performance" may decide which speed to use
                  within this range.
  current CPU frequency is 2.26 GHz (asserted by call to hardware).
  boost state support:
    Supported: yes
    Active: yes

shows very different values for the available frequency steps.  The cpupower
output rounds off values at 2 decimal points and this causes problems with
test scripts.  For example, with the data above,

1.064 is 1.06
1.197 is 1.20
1.596 is 1.60
1.995 is 2.00
2.128 is 2.13

and most confusingly,

2.261 is 2.26
2.262 is 2.26

Truncating these values serves no real purpose other than making the output
pretty.  Since the default has been to round off these values I am adding
a -n/--no-rounding option to the cpupower utility that will display the
data without rounding off the still significant digits.

After patch,

analyzing CPU 0:
  driver: acpi-cpufreq
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 10.000 us.
  hardware limits: 1.064000 GHz - 2.262000 GHz
  available frequency steps: 2.262000 GHz, 2.261000 GHz, 2.128000 GHz, 1.995000 GHz, 1.862000 GHz, 1.729000 GHz, 1.596000 GHz, 1.463000 GHz, 1.330000 GHz, 1.197000 GHz, 1.064000 GHz
  available cpufreq governors: conservative, userspace, powersave, ondemand, performance
  current policy: frequency should be within 1.064000 GHz and 2.262000 GHz.
                  The governor "performance" may decide which speed to use
                  within this range.
  current CPU frequency is 2.262000 GHz (asserted by call to hardware).
  boost state support:
    Supported: yes
    Active: yes

Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Thomas Renninger <trenn@suse.de>
Cc: linux-pm@vger.kernel.org
Acked-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Prarit Bhargava <prarit@redhat.com>
---
 tools/power/cpupower/man/cpupower-frequency-info.1 |    3 +
 tools/power/cpupower/utils/cpufreq-info.c          |  110 +++++++++++++-------
 2 files changed, 73 insertions(+), 40 deletions(-)

Comments

Rafael J. Wysocki April 30, 2014, 11:41 p.m. UTC | #1
On Thursday, April 24, 2014 10:32:07 AM Prarit Bhargava wrote:
> The command "cpupower frequency-info" can be used when using cpupower to
> monitor and test processor behaviour to determine if the processor is
> behaving as expected.  This data can be compared to the output of
> /proc/cpuinfo or the output of
> /sys/devices/system/cpu/cpuX/cpufreq/scaling_available_frequencies
> to determine if the cpu is in an expected state.
> 
> When doing this I noticed comparison test failures due to the way the
> data is displayed in cpupower.  For example,
> 
> [root@intel-s3e37-02 cpupower]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
> 2262000 2261000 2128000 1995000 1862000 1729000 1596000 1463000 1330000
> 1197000 1064000
> 
> compared to
> 
> [root@intel-s3e37-02 cpupower]# cpupower frequency-info
> analyzing CPU 0:
>   driver: acpi-cpufreq
>   CPUs which run at the same hardware frequency: 0
>   CPUs which need to have their frequency coordinated by software: 0
>   maximum transition latency: 10.0 us.
>   hardware limits: 1.06 GHz - 2.26 GHz
>   available frequency steps: 2.26 GHz, 2.26 GHz, 2.13 GHz, 2.00 GHz, 1.86 GHz, 1.73 GHz, 1.60 GHz, 1.46 GHz, 1.33 GHz, 1.20 GHz, 1.06 GHz
>   available cpufreq governors: conservative, userspace, powersave, ondemand, performance
>   current policy: frequency should be within 1.06 GHz and 2.26 GHz.
>                   The governor "performance" may decide which speed to use
>                   within this range.
>   current CPU frequency is 2.26 GHz (asserted by call to hardware).
>   boost state support:
>     Supported: yes
>     Active: yes
> 
> shows very different values for the available frequency steps.  The cpupower
> output rounds off values at 2 decimal points and this causes problems with
> test scripts.  For example, with the data above,
> 
> 1.064 is 1.06
> 1.197 is 1.20
> 1.596 is 1.60
> 1.995 is 2.00
> 2.128 is 2.13
> 
> and most confusingly,
> 
> 2.261 is 2.26
> 2.262 is 2.26
> 
> Truncating these values serves no real purpose other than making the output
> pretty.  Since the default has been to round off these values I am adding
> a -n/--no-rounding option to the cpupower utility that will display the
> data without rounding off the still significant digits.
> 
> After patch,
> 
> analyzing CPU 0:
>   driver: acpi-cpufreq
>   CPUs which run at the same hardware frequency: 0
>   CPUs which need to have their frequency coordinated by software: 0
>   maximum transition latency: 10.000 us.
>   hardware limits: 1.064000 GHz - 2.262000 GHz
>   available frequency steps: 2.262000 GHz, 2.261000 GHz, 2.128000 GHz, 1.995000 GHz, 1.862000 GHz, 1.729000 GHz, 1.596000 GHz, 1.463000 GHz, 1.330000 GHz, 1.197000 GHz, 1.064000 GHz
>   available cpufreq governors: conservative, userspace, powersave, ondemand, performance
>   current policy: frequency should be within 1.064000 GHz and 2.262000 GHz.
>                   The governor "performance" may decide which speed to use
>                   within this range.
>   current CPU frequency is 2.262000 GHz (asserted by call to hardware).
>   boost state support:
>     Supported: yes
>     Active: yes
> 
> Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
> Cc: Thomas Renninger <trenn@suse.de>
> Cc: linux-pm@vger.kernel.org
> Acked-by: Thomas Renninger <trenn@suse.de>
> Signed-off-by: Prarit Bhargava <prarit@redhat.com>

Thomas, any comments?  Yes, no, don't care?

> ---
>  tools/power/cpupower/man/cpupower-frequency-info.1 |    3 +
>  tools/power/cpupower/utils/cpufreq-info.c          |  110 +++++++++++++-------
>  2 files changed, 73 insertions(+), 40 deletions(-)
> 
> diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
> index 4a1918e..9c85a38 100644
> --- a/tools/power/cpupower/man/cpupower-frequency-info.1
> +++ b/tools/power/cpupower/man/cpupower-frequency-info.1
> @@ -50,6 +50,9 @@ Prints out information like provided by the /proc/cpufreq interface in 2.4. and
>  \fB\-m\fR \fB\-\-human\fR
>  human\-readable output for the \-f, \-w, \-s and \-y parameters.
>  .TP  
> +\fB\-n\fR \fB\-\-no-rounding\fR
> +Output frequencies and latencies without rounding off values.
> +.TP  
>  .SH "REMARKS"
>  .LP 
>  By default only values of core zero are displayed. How to display settings of
> diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
> index 28953c9..b4b90a9 100644
> --- a/tools/power/cpupower/utils/cpufreq-info.c
> +++ b/tools/power/cpupower/utils/cpufreq-info.c
> @@ -82,29 +82,42 @@ static void proc_cpufreq_output(void)
>  	}
>  }
>  
> +static int no_rounding;
>  static void print_speed(unsigned long speed)
>  {
>  	unsigned long tmp;
>  
> -	if (speed > 1000000) {
> -		tmp = speed % 10000;
> -		if (tmp >= 5000)
> -			speed += 10000;
> -		printf("%u.%02u GHz", ((unsigned int) speed/1000000),
> -			((unsigned int) (speed%1000000)/10000));
> -	} else if (speed > 100000) {
> -		tmp = speed % 1000;
> -		if (tmp >= 500)
> -			speed += 1000;
> -		printf("%u MHz", ((unsigned int) speed / 1000));
> -	} else if (speed > 1000) {
> -		tmp = speed % 100;
> -		if (tmp >= 50)
> -			speed += 100;
> -		printf("%u.%01u MHz", ((unsigned int) speed/1000),
> -			((unsigned int) (speed%1000)/100));
> -	} else
> -		printf("%lu kHz", speed);
> +	if (no_rounding) {
> +		if (speed > 1000000)
> +			printf("%u.%06u GHz", ((unsigned int) speed/1000000),
> +				((unsigned int) speed%1000000));
> +		else if (speed > 100000)
> +			printf("%u MHz", (unsigned int) speed);
> +		else if (speed > 1000)
> +			printf("%u.%03u MHz", ((unsigned int) speed/1000),
> +				(unsigned int) (speed%1000));
> +		else
> +			printf("%lu kHz", speed);
> +	} else {
> +		if (speed > 1000000) {
> +			tmp = speed%10000;
> +			if (tmp >= 5000)
> +				speed += 10000;
> +			printf("%u.%02u GHz", ((unsigned int) speed/1000000),
> +				((unsigned int) (speed%1000000)/10000));
> +		} else if (speed > 100000) {
> +			tmp = speed%1000;
> +			if (tmp >= 500)
> +				speed += 1000;
> +			printf("%u MHz", ((unsigned int) speed/1000));
> +		} else if (speed > 1000) {
> +			tmp = speed%100;
> +			if (tmp >= 50)
> +				speed += 100;
> +			printf("%u.%01u MHz", ((unsigned int) speed/1000),
> +				((unsigned int) (speed%1000)/100));
> +		}
> +	}
>  
>  	return;
>  }
> @@ -113,26 +126,38 @@ static void print_duration(unsigned long duration)
>  {
>  	unsigned long tmp;
>  
> -	if (duration > 1000000) {
> -		tmp = duration % 10000;
> -		if (tmp >= 5000)
> -			duration += 10000;
> -		printf("%u.%02u ms", ((unsigned int) duration/1000000),
> -			((unsigned int) (duration%1000000)/10000));
> -	} else if (duration > 100000) {
> -		tmp = duration % 1000;
> -		if (tmp >= 500)
> -			duration += 1000;
> -		printf("%u us", ((unsigned int) duration / 1000));
> -	} else if (duration > 1000) {
> -		tmp = duration % 100;
> -		if (tmp >= 50)
> -			duration += 100;
> -		printf("%u.%01u us", ((unsigned int) duration/1000),
> -			((unsigned int) (duration%1000)/100));
> -	} else
> -		printf("%lu ns", duration);
> -
> +	if (no_rounding) {
> +		if (duration > 1000000)
> +			printf("%u.%06u ms", ((unsigned int) duration/1000000),
> +				((unsigned int) duration%1000000));
> +		else if (duration > 100000)
> +			printf("%u us", ((unsigned int) duration/1000));
> +		else if (duration > 1000)
> +			printf("%u.%03u us", ((unsigned int) duration/1000),
> +				((unsigned int) duration%1000));
> +		else
> +			printf("%lu ns", duration);
> +	} else {
> +		if (duration > 1000000) {
> +			tmp = duration%10000;
> +			if (tmp >= 5000)
> +				duration += 10000;
> +			printf("%u.%02u ms", ((unsigned int) duration/1000000),
> +				((unsigned int) (duration%1000000)/10000));
> +		} else if (duration > 100000) {
> +			tmp = duration%1000;
> +			if (tmp >= 500)
> +				duration += 1000;
> +			printf("%u us", ((unsigned int) duration / 1000));
> +		} else if (duration > 1000) {
> +			tmp = duration%100;
> +			if (tmp >= 50)
> +				duration += 100;
> +			printf("%u.%01u us", ((unsigned int) duration/1000),
> +				((unsigned int) (duration%1000)/100));
> +		} else
> +			printf("%lu ns", duration);
> +	}
>  	return;
>  }
>  
> @@ -525,6 +550,7 @@ static struct option info_opts[] = {
>  	{ .name = "latency",	.has_arg = no_argument,		.flag = NULL,	.val = 'y'},
>  	{ .name = "proc",	.has_arg = no_argument,		.flag = NULL,	.val = 'o'},
>  	{ .name = "human",	.has_arg = no_argument,		.flag = NULL,	.val = 'm'},
> +	{ .name = "no-rounding", .has_arg = no_argument,	.flag = NULL,	.val = 'n'},
>  	{ },
>  };
>  
> @@ -538,7 +564,8 @@ int cmd_freq_info(int argc, char **argv)
>  	int output_param = 0;
>  
>  	do {
> -		ret = getopt_long(argc, argv, "oefwldpgrasmyb", info_opts, NULL);
> +		ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts,
> +				  NULL);
>  		switch (ret) {
>  		case '?':
>  			output_param = '?';
> @@ -575,6 +602,9 @@ int cmd_freq_info(int argc, char **argv)
>  			}
>  			human = 1;
>  			break;
> +		case 'n':
> +			no_rounding = 1;
> +			break;
>  		default:
>  			fprintf(stderr, "invalid or unknown argument\n");
>  			return EXIT_FAILURE;
>
Thomas Renninger May 5, 2014, 4:06 p.m. UTC | #2
On Thursday, May 01, 2014 01:41:34 AM Rafael J. Wysocki wrote:
> On Thursday, April 24, 2014 10:32:07 AM Prarit Bhargava wrote:
...

> > 
> > Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
> > Cc: Thomas Renninger <trenn@suse.de>
> > Cc: linux-pm@vger.kernel.org
> > Acked-by: Thomas Renninger <trenn@suse.de>
> > Signed-off-by: Prarit Bhargava <prarit@redhat.com>
> 
> Thomas, any comments?  Yes, no, don't care?

The patch is ok and introduces a new functionality which
is compatible with the rest by only getting switched on via
an extra parameter.

It should not conflict with my other patches which I forgot
what status there is.
Subject: tools/power/cpupower enhancements/fixes
on linux-pm@lists.linux-foundation.org

Are you going to pick them up, shall I resend?

Thanks,

    Thomas
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki May 6, 2014, 12:24 p.m. UTC | #3
On Monday, May 05, 2014 06:06:01 PM Thomas Renninger wrote:
> On Thursday, May 01, 2014 01:41:34 AM Rafael J. Wysocki wrote:
> > On Thursday, April 24, 2014 10:32:07 AM Prarit Bhargava wrote:
> ...
> 
> > > 
> > > Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
> > > Cc: Thomas Renninger <trenn@suse.de>
> > > Cc: linux-pm@vger.kernel.org
> > > Acked-by: Thomas Renninger <trenn@suse.de>
> > > Signed-off-by: Prarit Bhargava <prarit@redhat.com>
> > 
> > Thomas, any comments?  Yes, no, don't care?
> 
> The patch is ok and introduces a new functionality which
> is compatible with the rest by only getting switched on via
> an extra parameter.

OK, thanks!

> It should not conflict with my other patches which I forgot
> what status there is.
> Subject: tools/power/cpupower enhancements/fixes
> on linux-pm@lists.linux-foundation.org
> 
> Are you going to pick them up, shall I resend?

Please resend.  I've lost track of them, sorry about that.
diff mbox

Patch

diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
index 4a1918e..9c85a38 100644
--- a/tools/power/cpupower/man/cpupower-frequency-info.1
+++ b/tools/power/cpupower/man/cpupower-frequency-info.1
@@ -50,6 +50,9 @@  Prints out information like provided by the /proc/cpufreq interface in 2.4. and
 \fB\-m\fR \fB\-\-human\fR
 human\-readable output for the \-f, \-w, \-s and \-y parameters.
 .TP  
+\fB\-n\fR \fB\-\-no-rounding\fR
+Output frequencies and latencies without rounding off values.
+.TP  
 .SH "REMARKS"
 .LP 
 By default only values of core zero are displayed. How to display settings of
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 28953c9..b4b90a9 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -82,29 +82,42 @@  static void proc_cpufreq_output(void)
 	}
 }
 
+static int no_rounding;
 static void print_speed(unsigned long speed)
 {
 	unsigned long tmp;
 
-	if (speed > 1000000) {
-		tmp = speed % 10000;
-		if (tmp >= 5000)
-			speed += 10000;
-		printf("%u.%02u GHz", ((unsigned int) speed/1000000),
-			((unsigned int) (speed%1000000)/10000));
-	} else if (speed > 100000) {
-		tmp = speed % 1000;
-		if (tmp >= 500)
-			speed += 1000;
-		printf("%u MHz", ((unsigned int) speed / 1000));
-	} else if (speed > 1000) {
-		tmp = speed % 100;
-		if (tmp >= 50)
-			speed += 100;
-		printf("%u.%01u MHz", ((unsigned int) speed/1000),
-			((unsigned int) (speed%1000)/100));
-	} else
-		printf("%lu kHz", speed);
+	if (no_rounding) {
+		if (speed > 1000000)
+			printf("%u.%06u GHz", ((unsigned int) speed/1000000),
+				((unsigned int) speed%1000000));
+		else if (speed > 100000)
+			printf("%u MHz", (unsigned int) speed);
+		else if (speed > 1000)
+			printf("%u.%03u MHz", ((unsigned int) speed/1000),
+				(unsigned int) (speed%1000));
+		else
+			printf("%lu kHz", speed);
+	} else {
+		if (speed > 1000000) {
+			tmp = speed%10000;
+			if (tmp >= 5000)
+				speed += 10000;
+			printf("%u.%02u GHz", ((unsigned int) speed/1000000),
+				((unsigned int) (speed%1000000)/10000));
+		} else if (speed > 100000) {
+			tmp = speed%1000;
+			if (tmp >= 500)
+				speed += 1000;
+			printf("%u MHz", ((unsigned int) speed/1000));
+		} else if (speed > 1000) {
+			tmp = speed%100;
+			if (tmp >= 50)
+				speed += 100;
+			printf("%u.%01u MHz", ((unsigned int) speed/1000),
+				((unsigned int) (speed%1000)/100));
+		}
+	}
 
 	return;
 }
@@ -113,26 +126,38 @@  static void print_duration(unsigned long duration)
 {
 	unsigned long tmp;
 
-	if (duration > 1000000) {
-		tmp = duration % 10000;
-		if (tmp >= 5000)
-			duration += 10000;
-		printf("%u.%02u ms", ((unsigned int) duration/1000000),
-			((unsigned int) (duration%1000000)/10000));
-	} else if (duration > 100000) {
-		tmp = duration % 1000;
-		if (tmp >= 500)
-			duration += 1000;
-		printf("%u us", ((unsigned int) duration / 1000));
-	} else if (duration > 1000) {
-		tmp = duration % 100;
-		if (tmp >= 50)
-			duration += 100;
-		printf("%u.%01u us", ((unsigned int) duration/1000),
-			((unsigned int) (duration%1000)/100));
-	} else
-		printf("%lu ns", duration);
-
+	if (no_rounding) {
+		if (duration > 1000000)
+			printf("%u.%06u ms", ((unsigned int) duration/1000000),
+				((unsigned int) duration%1000000));
+		else if (duration > 100000)
+			printf("%u us", ((unsigned int) duration/1000));
+		else if (duration > 1000)
+			printf("%u.%03u us", ((unsigned int) duration/1000),
+				((unsigned int) duration%1000));
+		else
+			printf("%lu ns", duration);
+	} else {
+		if (duration > 1000000) {
+			tmp = duration%10000;
+			if (tmp >= 5000)
+				duration += 10000;
+			printf("%u.%02u ms", ((unsigned int) duration/1000000),
+				((unsigned int) (duration%1000000)/10000));
+		} else if (duration > 100000) {
+			tmp = duration%1000;
+			if (tmp >= 500)
+				duration += 1000;
+			printf("%u us", ((unsigned int) duration / 1000));
+		} else if (duration > 1000) {
+			tmp = duration%100;
+			if (tmp >= 50)
+				duration += 100;
+			printf("%u.%01u us", ((unsigned int) duration/1000),
+				((unsigned int) (duration%1000)/100));
+		} else
+			printf("%lu ns", duration);
+	}
 	return;
 }
 
@@ -525,6 +550,7 @@  static struct option info_opts[] = {
 	{ .name = "latency",	.has_arg = no_argument,		.flag = NULL,	.val = 'y'},
 	{ .name = "proc",	.has_arg = no_argument,		.flag = NULL,	.val = 'o'},
 	{ .name = "human",	.has_arg = no_argument,		.flag = NULL,	.val = 'm'},
+	{ .name = "no-rounding", .has_arg = no_argument,	.flag = NULL,	.val = 'n'},
 	{ },
 };
 
@@ -538,7 +564,8 @@  int cmd_freq_info(int argc, char **argv)
 	int output_param = 0;
 
 	do {
-		ret = getopt_long(argc, argv, "oefwldpgrasmyb", info_opts, NULL);
+		ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts,
+				  NULL);
 		switch (ret) {
 		case '?':
 			output_param = '?';
@@ -575,6 +602,9 @@  int cmd_freq_info(int argc, char **argv)
 			}
 			human = 1;
 			break;
+		case 'n':
+			no_rounding = 1;
+			break;
 		default:
 			fprintf(stderr, "invalid or unknown argument\n");
 			return EXIT_FAILURE;