Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Readability of DISK READ/DISK WRITE Columns by Shortening Labels and Values #1557

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

AryanGitHub
Copy link
Contributor

Observations before addressing GitHub issue #991:

  • The column titles for RCHAR & WCHAR take 6 characters, while the titles for DISK READ, DISK WRITE, and DISK R/W (representing total I/O rate in bytes per second) take 12 characters. This PR reduces them to 9 characters.

  • Why not make the column titles for DISK operations consistent with RCHAR & WCHAR?

  • The RCHAR & WCHAR columns use an unsigned long long data type, while DISK READ & DISK WRITE use double, which adds an extra character for the decimal point when printing.

  • The DISK READ & DISK WRITE columns represent rates, which include a time dimension, thus requiring 2 additional characters compared to RCHAR & WCHAR.

  • In total, we need 3 extra characters for DISK READ, DISK WRITE, and DISK R/W compared to RCHAR & WCHAR.

What has this PR changed?

This PR changed the column titles as required and
introduced a dynamic precision variable, adjusting based on the value to be printed. The total number of numerical characters allowed for printing is 4. The precision adjusts as follows:

  • If the value is between 0-9, the precision is 3, e.g., 3.141.
  • If the value is between 10-99, the precision is 2, e.g., 31.41.
  • If the value is greater than 99, the precision is 1, e.g., 314.1.
  • If the value is greater than 999, the precision is 0, e.g., 3141.

@AryanGitHub
Copy link
Contributor Author

I also wanted to know when, while changing the total width of "Row_printRate", do we need to modify this line in ./pcp/PCPDynamicColumn.c:

column->super.width = 11; // Row_printRate

This is because I don't know, what this does. please inform me about this, I will try to make the changes accordingly.

Row.c Outdated
int len = snprintf(buffer, sizeof(buffer), "%7.2f K/s ", rate / ONE_K);
double rateToPrint = rate / ONE_K;
unsigned char precision = Row_getPrecision (rateToPrint);
int len = snprintf(buffer, sizeof(buffer), "%5.*fK/s ", precision, rateToPrint);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. precision takes the type int. You should set the data type properly.
  2. There is a potential of converting this into a loop. You can see the code of Meter_humanUnit() function for how it can be done. There is a global unitPrefixes array that you can utilize.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

| I don't know, what this does. please inform me about this, I will try to make the changes accordingly.

This (11) sets the default column width if none is specified in the configuration file from memory - if we're changing the default reporting width in Row.c its very likely this pcp code will need to change to match it.

Row.c Outdated
static inline unsigned char Row_getPrecision (double displayRate){
if (displayRate < 10) return 3;
else if (displayRate < 100) return 2;
else if (displayRate < 1000) return 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider there is a rounding issue with this approach. Look at Meter_humanUnit() function to see how I addressed that.

@BenBE BenBE added the enhancement Extension or improvement to existing feature label Oct 19, 2024
@BenBE
Copy link
Member

BenBE commented Oct 19, 2024

The spacing for RDISK, WDISK and RW DISK is inconsistent.

Further more, DIOR, DIOW and DIORW would be even shorter and even consistent.

From the display side of things: There's a list of IEC unit prefixes for a reason. Please use that one to avoid code duplication.

Also, the space before B/s is intentional to ease reading 8B/s. Which can be hard to discern with some console fonts.

@AryanGitHub
Copy link
Contributor Author

Row.c:511:13: warning: 6th function call argument is an uninitialized value [core.CallAndMessage]
  511 |       len = snprintf(buffer, sizeof(buffer), "%c/s ", unitPrefixes[unitPrefixIndex]);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/x86_64-linux-gnu/bits/stdio2.h:77:3: note: expanded from macro 'snprintf'
   77 |   __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1,                \
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   78 |                             __glibc_objsize (str), __VA_ARGS__)
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

What is left uninitialized? I am unable to understand.

@Explorer09
Copy link
Contributor

Row.c:511:13: warning: 6th function call argument is an uninitialized value [core.CallAndMessage]
  511 |       len = snprintf(buffer, sizeof(buffer), "%c/s ", unitPrefixes[unitPrefixIndex]);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/x86_64-linux-gnu/bits/stdio2.h:77:3: note: expanded from macro 'snprintf'
   77 |   __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1,                \
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   78 |                             __glibc_objsize (str), __VA_ARGS__)
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

What is left uninitialized? I am unable to understand.

Potential reading out of bounds. unitPrefixes[-1] unhandled (you probably want it to print B instead.)

int len = snprintf(buffer, sizeof(buffer), "%7.2f T/s ", rate / ONE_T);
RichString_appendnAscii(str, largeNumberColor, buffer, len);
int len = snprintf(buffer, sizeof(buffer), "%4.0f B/s ", rate);
RichString_appendnAscii(str, shadowColor, buffer, len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why using shadowColor? Ideally nonzero values should not use that text color -- the visual of that would let users skip that entry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used it because it was mentioned in the Issue.
#991 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well. I would personally disagree with @BenBE unless these small values would practically make a lot of visual noise. But I am not the one to decide on this (I just put my suggestion).

Row.c Outdated
size_t unitPrefixIndex = 0;
do {
if (unitPrefixIndex > ARRAYSIZE(unitPrefixes)-1) {
int len = snprintf(buffer, sizeof(buffer), " INF ");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can spell the word "infinity" out. There is enough space.

Suggested change
int len = snprintf(buffer, sizeof(buffer), " INF ");
int len = snprintf(buffer, sizeof(buffer), "infinity ");

Row.c Outdated
}
}

int len = snprintf(buffer, sizeof(buffer), "%5.*f", precision, rate);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought you would want "%4.*f" as the format. That is, one digit less.

Output example A

   0 B/s - 9999 B/s
9.77 K/s - 9.99 K/s
10.0 K/s - 99.9 K/s
 100 K/s - 9999 K/s
9.77 M/s - 9.99 M/s
     ...
 100 Q/s - 9999 Q/s
infinity

Output example B

   0 B/s - 1023 B/s
1.00 K/s - 9.99 K/s
10.0 K/s - 99.9 K/s
 100 K/s - 1023 K/s
1.00 M/s - 9.99 M/s
     ...
 100 Q/s - 9999 Q/s
infinity

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we actually want 4 digits.
By using "%5.*f", it meant the total width of the output field is 5, including the decimal point and digits.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you would get 999.9 K/s. I bet you didn't test that one out.

Copy link
Contributor Author

@AryanGitHub AryanGitHub Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As its yes for this, should I shift to 4.*f now, or use 5.*f.
I am asking this because for 4.*f I have to change the precision logic and if it stays 5.*f I have to add a column width, currently its 9 (for any kind of Disk IO rates), it will be then 10.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you would get 999.9 K/s. I bet you didn't test that one out.

I wanted to understand, is there any issue with printing 999.9 K/s? I am unable to get it...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For size units we usually just use 3 significant digits as extra precisions are less useful for UI display purpose. Add a decimal point and it becomes 4 characters of width. When the decimal points are not needed, i.e. for numbers in range 100 - 9999, four digits can be shown for the same width, but that's more of a special case.

The numbers jump from one unit to the next in power of 1024, and that was the reason of 3 significant digits.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect, I understood why to use 3 significant digits for UI displays. Will now fix this to make 4.*f.
Thanks.

@AryanGitHub
Copy link
Contributor Author

The spacing for RDISK, WDISK and RW DISK is inconsistent.

Further more, DIOR, DIOW and DIORW would be even shorter and even consistent.

From the display side of things: There's a list of IEC unit prefixes for a reason. Please use that one to avoid code duplication.

Also, the space before B/s is intentional to ease reading 8B/s. Which can be hard to discern with some console fonts.

Should there be space for other values too, like when it is K/s or M/s, like 31.41 K/s? Rn I have space only for B/s.

@Explorer09
Copy link
Contributor

Also, the space before B/s is intentional to ease reading 8B/s. Which can be hard to discern with some console fonts.

Should there be space for other values too, like when it is K/s or M/s, like 31.41 K/s? Rn I have space only for B/s.

I can help answer that. Yes. Because otherwise the numbers can look misaligned, when there is an entire column of the numbers.

@AryanGitHub
Copy link
Contributor Author

AryanGitHub commented Oct 22, 2024

I made the rate to 4.*f and changed INF to infinity, as discussed.

Also ran a small independent test to ensure the printf decimal precision logic always prints 4 characters only. Link for the Test script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Extension or improvement to existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants