Skip to content

Commit 18a6dbc

Browse files
Saket Kumar Bhaskartyreld
Saket Kumar Bhaskar
authored andcommitted
lparstat: Fix negative values for %idle PURR
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] #103 Signed-off-by: Saket Kumar Bhaskar <[email protected]> Signed-off-by: Tyrel Datwyler <[email protected]>
1 parent 3a40277 commit 18a6dbc

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

src/lparstat.c

+11-6
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ long long get_delta_value(char *se_name)
254254
return (value - old_value);
255255
}
256256

257-
void get_time()
257+
void get_time_ns(void)
258258
{
259259
struct sysentry *se;
260260
struct timespec ts;
@@ -266,7 +266,12 @@ void get_time()
266266

267267
se = get_sysentry("time");
268268
sprintf(se->value, "%lld",
269-
(long long)ts.tv_sec);
269+
(long long)ts.tv_sec * 1000000000LL + (long long)ts.tv_nsec);
270+
}
271+
272+
double get_delta_time(void)
273+
{
274+
return (get_delta_value("time") / 1000000000.0);
270275
}
271276

272277
int get_time_base()
@@ -307,7 +312,7 @@ double get_scaled_tb(void)
307312
se = get_sysentry("online_cores");
308313
online_cores = atoi(se->value);
309314

310-
elapsed = get_delta_value("time");
315+
elapsed = get_delta_time();
311316

312317
se = get_sysentry("timebase");
313318
timebase = atoi(se->value);
@@ -386,7 +391,7 @@ void get_cpu_physc(struct sysentry *unused_se, char *buf)
386391

387392
physc = delta_purr / delta_tb;
388393
} else {
389-
elapsed = get_delta_value("time");
394+
elapsed = get_delta_time();
390395

391396
se = get_sysentry("timebase");
392397
timebase = atoi(se->value);
@@ -415,7 +420,7 @@ void get_cpu_app(struct sysentry *unused_se, char *buf)
415420
float timebase, app, elapsed_time;
416421
long long new_app, old_app;
417422

418-
elapsed_time = get_delta_value("time");
423+
elapsed_time = get_delta_time();
419424

420425
se = get_sysentry("timebase");
421426
timebase = atof(se->value);
@@ -1018,7 +1023,7 @@ void init_sysdata(void)
10181023
{
10191024
int rc = 0;
10201025

1021-
get_time();
1026+
get_time_ns();
10221027
parse_lparcfg();
10231028
parse_proc_stat();
10241029
parse_proc_ints();

0 commit comments

Comments
 (0)