File lparstat-Fix-negative-values-for-idle-PURR.patch of Package powerpc-utils.37742

From 18a6dbca81b443d3cb7037d8bd39da014b4055ee Mon Sep 17 00:00:00 2001
From: Saket Kumar Bhaskar <skb99@linux.ibm.com>
Date: Mon, 13 Jan 2025 13:43:39 +0530
Subject: [PATCH] lparstat: Fix negative values for %idle PURR

Patch-mainline: expected 1.3.14
Git-commit: 18a6dbca81b443d3cb7037d8bd39da014b4055ee

In certain scenarios, the %idle PURR metric displays negative values [1],
while %busy PURR exceeds 100% giving users false impression of resource
utilisation. This occurs when delta_purr becomes greater than delta_tb,
causing the following expression to yield a negative value, particularly
during 100% system utilization for %idle PURR:

%idle = (delta_tb - delta_purr + delta_idle_purr) / delta_tb * 100;

Without change:

./lparstat -E 1 30

System Configuration
type=Shared mode=Uncapped smt=8 lcpu=20 mem=208057792 kB cpus=42 ent=2.00

---Actual---                 -Normalized-
%busy  %idle   Frequency     %busy  %idle
------ ------  ------------- ------ ------
103.88  -3.88  2.75GHz[ 98%] 101.80   0.00
103.46  -3.46  2.67GHz[ 95%]  98.28   1.49
101.53  -1.53  2.74GHz[ 98%]  99.50   0.51
103.41  -3.41  2.70GHz[ 96%]  99.27   0.37

The delta_tb is computed using get_scaled_tb, which calculates the
timebase for a given time difference. Previously, nanoseconds were
ignored in the calculation of time difference, which led to delta_tb
being underestimated.

This patch addresses the issue by incorporating nanoseconds into the
time difference, ensuring precise calculations.

Also, rename get_time() to get_time_ns() to denote it returns time in
nanoseconds. get_delta_time() is introduced as a wrapper to get delta
time in seconds.

With change:
./lparstat -E 1 30

System Configuration
type=Shared mode=Uncapped smt=8 lcpu=20 mem=208057792 kB cpus=42 ent=2.00

---Actual---                 -Normalized-
%busy  %idle   Frequency     %busy  %idle
------ ------  ------------- ------ ------
 99.52   0.48  2.74GHz[ 98%]  97.53   2.66
 99.53   0.47  2.71GHz[ 97%]  96.54   3.67
 99.49   0.51  2.71GHz[ 97%]  96.51   3.87
 99.51   0.49  2.70GHz[ 97%]  96.53   3.90
 99.48   0.52  2.69GHz[ 96%]  95.50   4.38

[1] https://github.com/ibm-power-utilities/powerpc-utils/issues/103

Signed-off-by: Saket Kumar Bhaskar <skb99@linux.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
 src/lparstat.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/lparstat.c b/src/lparstat.c
index fe8b0fc..db22316 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -254,7 +254,7 @@ long long get_delta_value(char *se_name)
 	return (value - old_value);
 }
 
-void get_time()
+void get_time_ns(void)
 {
 	struct sysentry *se;
 	struct timespec ts;
@@ -266,7 +266,12 @@ void get_time()
 
 	se = get_sysentry("time");
 	sprintf(se->value, "%lld",
-		(long long)ts.tv_sec);
+		(long long)ts.tv_sec * 1000000000LL + (long long)ts.tv_nsec);
+}
+
+double get_delta_time(void)
+{
+	return (get_delta_value("time") / 1000000000.0);
 }
 
 int get_time_base()
@@ -307,7 +312,7 @@ double get_scaled_tb(void)
 	se = get_sysentry("online_cores");
 	online_cores = atoi(se->value);
 
-	elapsed = get_delta_value("time");
+	elapsed = get_delta_time();
 
 	se = get_sysentry("timebase");
 	timebase = atoi(se->value);
@@ -386,7 +391,7 @@ void get_cpu_physc(struct sysentry *unused_se, char *buf)
 
 		physc = delta_purr / delta_tb;
 	} else {
-		elapsed = get_delta_value("time");
+		elapsed = get_delta_time();
 
 		se = get_sysentry("timebase");
 		timebase = atoi(se->value);
@@ -415,7 +420,7 @@ void get_cpu_app(struct sysentry *unused_se, char *buf)
 	float timebase, app, elapsed_time;
 	long long new_app, old_app;
 
-	elapsed_time = get_delta_value("time");
+	elapsed_time = get_delta_time();
 
 	se = get_sysentry("timebase");
 	timebase = atof(se->value);
@@ -1018,7 +1023,7 @@ void init_sysdata(void)
 {
 	int rc = 0;
 
-	get_time();
+	get_time_ns();
 	parse_lparcfg();
 	parse_proc_stat();
 	parse_proc_ints();
-- 
2.47.1

openSUSE Build Service is sponsored by