Skip to content

Commit 6751dbb

Browse files
authored
Add I/O read per second, fix bug sizing of io overview (#61)
* add read per second, fix bug sizing of io overview * demo updated
1 parent 93a21ab commit 6751dbb

3 files changed

Lines changed: 84 additions & 9 deletions

File tree

docs/demo.gif

-177 KB
Loading

src/proclens.c

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <string.h>
55
#include <stdlib.h>
66
#include <signal.h>
7+
#include <limits.h>
78
#include <sys/select.h>
89
#include <termios.h>
910
#include <time.h>
@@ -130,11 +131,13 @@ struct overview_metrics {
130131
unsigned long long rss_kb;
131132
unsigned long long rx_bytes;
132133
unsigned long long tx_bytes;
134+
unsigned long long read_bytes;
133135
unsigned long long write_bytes;
134136
int has_cpu;
135137
int has_rss;
136138
int has_rx;
137139
int has_tx;
140+
int has_read;
138141
int has_write;
139142
};
140143

@@ -469,6 +472,48 @@ static int parse_first_u64(const char *line, unsigned long long *value)
469472
return sscanf(cursor, "%llu", value) == 1;
470473
}
471474

475+
static int parse_size_field_bytes(const char *line, unsigned long long *value)
476+
{
477+
char unit[8] = {0};
478+
const char *cursor;
479+
unsigned long long number;
480+
unsigned long long multiplier = 1;
481+
482+
if (!line || !value)
483+
return 0;
484+
485+
cursor = line;
486+
while (*cursor && (*cursor < '0' || *cursor > '9'))
487+
cursor++;
488+
489+
if (*cursor == '\0')
490+
return 0;
491+
492+
if (sscanf(cursor, "%llu %7s", &number, unit) < 1)
493+
return 0;
494+
495+
if (unit[0] != '\0') {
496+
if (strcmp(unit, "B") == 0)
497+
multiplier = 1;
498+
else if (strcmp(unit, "KB") == 0)
499+
multiplier = 1024ULL;
500+
else if (strcmp(unit, "MB") == 0)
501+
multiplier = 1024ULL * 1024ULL;
502+
else if (strcmp(unit, "GB") == 0)
503+
multiplier = 1024ULL * 1024ULL * 1024ULL;
504+
else if (strcmp(unit, "TB") == 0)
505+
multiplier = 1024ULL * 1024ULL * 1024ULL * 1024ULL;
506+
else
507+
return 0;
508+
}
509+
510+
if (number > (ULLONG_MAX / multiplier))
511+
return 0;
512+
513+
*value = number * multiplier;
514+
return 1;
515+
}
516+
472517
static void extract_overview_metrics(const struct live_snapshot *snapshot,
473518
struct overview_metrics *metrics)
474519
{
@@ -495,17 +540,22 @@ static void extract_overview_metrics(const struct live_snapshot *snapshot,
495540
}
496541

497542
if (copy_line_with_prefix(snapshot->det_content, "rx_bytes:", line, sizeof(line)) &&
498-
parse_first_u64(line, &metrics->rx_bytes)) {
543+
parse_size_field_bytes(line, &metrics->rx_bytes)) {
499544
metrics->has_rx = 1;
500545
}
501546

502547
if (copy_line_with_prefix(snapshot->det_content, "tx_bytes:", line, sizeof(line)) &&
503-
parse_first_u64(line, &metrics->tx_bytes)) {
548+
parse_size_field_bytes(line, &metrics->tx_bytes)) {
504549
metrics->has_tx = 1;
505550
}
506551

552+
if (copy_line_with_prefix(snapshot->det_content, "read_bytes:", line, sizeof(line)) &&
553+
parse_size_field_bytes(line, &metrics->read_bytes)) {
554+
metrics->has_read = 1;
555+
}
556+
507557
if (copy_line_with_prefix(snapshot->det_content, "write_bytes:", line, sizeof(line)) &&
508-
parse_first_u64(line, &metrics->write_bytes)) {
558+
parse_size_field_bytes(line, &metrics->write_bytes)) {
509559
metrics->has_write = 1;
510560
}
511561
}
@@ -592,6 +642,7 @@ static int collect_overview_series(const struct live_snapshot *history,
592642
unsigned long long *rss_values,
593643
unsigned long long *rx_rate_values,
594644
unsigned long long *tx_rate_values,
645+
unsigned long long *read_rate_values,
595646
unsigned long long *write_rate_values,
596647
int max_values)
597648
{
@@ -636,6 +687,13 @@ static int collect_overview_series(const struct live_snapshot *history,
636687
tx_rate_values[points] = 0;
637688
}
638689

690+
if (have_previous && metrics.has_read && previous_metrics.has_read &&
691+
metrics.read_bytes >= previous_metrics.read_bytes) {
692+
read_rate_values[points] = metrics.read_bytes - previous_metrics.read_bytes;
693+
} else {
694+
read_rate_values[points] = 0;
695+
}
696+
639697
if (have_previous && metrics.has_write && previous_metrics.has_write &&
640698
metrics.write_bytes >= previous_metrics.write_bytes) {
641699
write_rate_values[points] =
@@ -662,47 +720,56 @@ static void print_overview_plots(const struct live_snapshot *snapshot,
662720
unsigned long long rss_values[OVERVIEW_PLOT_WIDTH];
663721
unsigned long long rx_rate_values[OVERVIEW_PLOT_WIDTH];
664722
unsigned long long tx_rate_values[OVERVIEW_PLOT_WIDTH];
723+
unsigned long long read_rate_values[OVERVIEW_PLOT_WIDTH];
665724
unsigned long long write_rate_values[OVERVIEW_PLOT_WIDTH];
666725
struct overview_metrics current_metrics;
667726
char cpu_plot[OVERVIEW_PLOT_BUF_SIZE];
668727
char rss_plot[OVERVIEW_PLOT_BUF_SIZE];
669728
char rx_plot[OVERVIEW_PLOT_BUF_SIZE];
670729
char tx_plot[OVERVIEW_PLOT_BUF_SIZE];
730+
char read_plot[OVERVIEW_PLOT_BUF_SIZE];
671731
char write_plot[OVERVIEW_PLOT_BUF_SIZE];
672732
char rss_label[32];
673733
char rx_label[32];
674734
char tx_label[32];
735+
char read_label[32];
675736
char write_label[32];
676737
unsigned long long current_rx_rate = 0;
677738
unsigned long long current_tx_rate = 0;
739+
unsigned long long current_read_rate = 0;
678740
unsigned long long current_write_rate = 0;
679741
int point_count;
680742

681743
memset(cpu_values, 0, sizeof(cpu_values));
682744
memset(rss_values, 0, sizeof(rss_values));
683745
memset(rx_rate_values, 0, sizeof(rx_rate_values));
684746
memset(tx_rate_values, 0, sizeof(tx_rate_values));
747+
memset(read_rate_values, 0, sizeof(read_rate_values));
685748
memset(write_rate_values, 0, sizeof(write_rate_values));
686749

687-
point_count = collect_overview_series(
688-
history, history_count, history_next, browse_offset, cpu_values, rss_values,
689-
rx_rate_values, tx_rate_values, write_rate_values, ARRAY_SIZE(cpu_values));
750+
point_count = collect_overview_series(history, history_count, history_next, browse_offset,
751+
cpu_values, rss_values, rx_rate_values,
752+
tx_rate_values, read_rate_values, write_rate_values,
753+
ARRAY_SIZE(cpu_values));
690754
render_sparkline(cpu_values, point_count, cpu_plot, sizeof(cpu_plot));
691755
render_sparkline(rss_values, point_count, rss_plot, sizeof(rss_plot));
692756
render_sparkline(rx_rate_values, point_count, rx_plot, sizeof(rx_plot));
693757
render_sparkline(tx_rate_values, point_count, tx_plot, sizeof(tx_plot));
758+
render_sparkline(read_rate_values, point_count, read_plot, sizeof(read_plot));
694759
render_sparkline(write_rate_values, point_count, write_plot, sizeof(write_plot));
695760

696761
extract_overview_metrics(snapshot, &current_metrics);
697762
if (point_count > 0) {
698763
current_rx_rate = rx_rate_values[point_count - 1];
699764
current_tx_rate = tx_rate_values[point_count - 1];
765+
current_read_rate = read_rate_values[point_count - 1];
700766
current_write_rate = write_rate_values[point_count - 1];
701767
}
702768

703769
format_compact_size(current_metrics.rss_kb * 1024ULL, rss_label, sizeof(rss_label), NULL);
704770
format_compact_size(current_rx_rate, rx_label, sizeof(rx_label), "/s");
705771
format_compact_size(current_tx_rate, tx_label, sizeof(tx_label), "/s");
772+
format_compact_size(current_read_rate, read_label, sizeof(read_label), "/s");
706773
format_compact_size(current_write_rate, write_label, sizeof(write_label), "/s");
707774

708775
printf("%s%sTRENDS%s\n", color_code(C_CYAN), color_code(C_BOLD), color_code(C_RESET));
@@ -725,6 +792,9 @@ static void print_overview_plots(const struct live_snapshot *snapshot,
725792
printf("%s TX/s |%s| %s%s\n", color_code(C_CYAN), tx_plot, tx_label,
726793
color_code(C_RESET));
727794
puts("");
795+
printf("%s RD/s |%s| %s%s\n", color_code(C_CYAN), read_plot, read_label,
796+
color_code(C_RESET));
797+
puts("");
728798
printf("%s WR/s |%s| %s%s\n", color_code(C_CYAN), write_plot, write_label,
729799
color_code(C_RESET));
730800
puts("");

src/proclens_tests.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,8 @@ static void test_overview_view_combines_sections(void)
422422
"[io]\n"
423423
"syscr: 12\n"
424424
"syscw: 13\n"
425-
"read_bytes: 1024\n"
426-
"write_bytes: 2048\n"
425+
"read_bytes: 1 GB\n"
426+
"write_bytes: 2 GB\n"
427427
"io_intensity: 3072\n";
428428
const char *det_older_1 = "Process ID: 4321\n"
429429
"Name: demo\n"
@@ -437,6 +437,7 @@ static void test_overview_view_combines_sections(void)
437437
" none\n"
438438
"Open Sockets:\n"
439439
"[io]\n"
440+
"read_bytes: 100 MB\n"
440441
"write_bytes: 300\n";
441442
const char *det_older_2 = "Process ID: 4321\n"
442443
"Name: demo\n"
@@ -450,7 +451,8 @@ static void test_overview_view_combines_sections(void)
450451
" none\n"
451452
"Open Sockets:\n"
452453
"[io]\n"
453-
"write_bytes: 900\n";
454+
"read_bytes: 512 MB\n"
455+
"write_bytes: 900 MB\n";
454456
const char *threads =
455457
"TID NAME CPU(%) STATE PRIORITY NICE CPU_AFFINITY\n"
456458
"----- --------------- ------- ----- -------- ---- ----------------\n"
@@ -492,6 +494,7 @@ static void test_overview_view_combines_sections(void)
492494
assert(strstr(output_buf, "█|"));
493495
assert(strstr(output_buf, "RX/s"));
494496
assert(strstr(output_buf, "TX/s"));
497+
assert(strstr(output_buf, "RD/s"));
495498
{
496499
char *rx_line = strstr(output_buf, "RX/s |");
497500
char *tx_line = strstr(output_buf, "TX/s |");
@@ -511,6 +514,8 @@ static void test_overview_view_combines_sections(void)
511514
assert(has_blank_line);
512515
}
513516
assert(strstr(output_buf, "WR/s"));
517+
assert(strstr(output_buf, "512 MB/s"));
518+
assert(strstr(output_buf, "1 GB/s"));
514519
assert(strstr(output_buf, "MEMORY SNAPSHOT"));
515520
assert(strstr(output_buf, "NETWORK SNAPSHOT"));
516521
assert(strstr(output_buf, "I/O SNAPSHOT"));

0 commit comments

Comments
 (0)