summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2013-07-12 11:28:11 +0200
committerTobias Klauser <tklauser@distanz.ch>2013-07-12 11:30:14 +0200
commit971b1d95e2e3d1ddc640e33f8cab06396cf10661 (patch)
treec54fdd1cb3f8c22dabbab450501b5a1b21de50ea
parent863800b1019cc92d6c20de4a9d5cd02682ad9177 (diff)
ifpps: Optionally display median values for CPU load and interrupts
Using the -m/--median command line option, median values across all CPUs are displayed for CPU load, interrupts per interval, sw interrupts per interval and absolute number of interrupts. Also update the manpage accordingly. Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--ifpps.87
-rw-r--r--ifpps.c92
2 files changed, 97 insertions, 2 deletions
diff --git a/ifpps.8 b/ifpps.8
index 16bbf6d..c151899 100644
--- a/ifpps.8
+++ b/ifpps.8
@@ -41,7 +41,8 @@ the number of CPUs exceeds 5 or the number specified by the user with the
heavy hitters. The topmost heavy hitter CPU will be marked with \[lq]+\[rq].
The least heavy hitter will always be displayed and is marked with
\[lq]-\[rq]. In addition, the average for all the above per-CPU data is
-shown.
+shown. Optionally the median values can be displayed using the \[lq]\-m\[rq]
+command line option.
.PP
ifpps also supports directly the gnuplot(1) data sample format. This
facilitates creation of gnuplot figures from ifpps time series.
@@ -70,6 +71,10 @@ is only available, if option \[lq]\-c\[rq] is given. For \[lq]\-l\[rq] it is
usually recommended to redirect the output into a file that is to be be
processed later with gnuplot(1).
.PP
+.SS -m, --median
+Show median values across all CPUs for CPU load, interrupts (per interval and
+absolute) and software interrupts.
+.PP
.SS -W, --no-warn
Suppress possible warnings in the ncurses output, e.g. about a too low sampling
interval that could cause performance regression.
diff --git a/ifpps.c b/ifpps.c
index eb9b899..0c684e6 100644
--- a/ifpps.c
+++ b/ifpps.c
@@ -72,10 +72,11 @@ static struct ifstat stats_old, stats_new, stats_delta;
static struct cpu_hit *cpu_hits;
static struct avg_stat stats_avg;
static int stats_loop = 0;
+static int show_median = 0;
static WINDOW *stats_screen = NULL;
static struct utsname uts;
-static const char *short_options = "d:t:n:vhclpW";
+static const char *short_options = "d:t:n:vhclpmW";
static const struct option long_options[] = {
{"dev", required_argument, NULL, 'd'},
{"interval", required_argument, NULL, 't'},
@@ -83,6 +84,7 @@ static const struct option long_options[] = {
{"promisc", no_argument, NULL, 'p'},
{"csv", no_argument, NULL, 'c'},
{"loop", no_argument, NULL, 'l'},
+ {"median", no_argument, NULL, 'm'},
{"no-warn", no_argument, NULL, 'W'},
{"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
@@ -798,6 +800,14 @@ static void screen_percpu_states_one(WINDOW *screen, const struct ifstat *rel,
100.0 * rel->cpu_iow[idx] / all);
}
+#define MEDIAN_EVEN(member) do { \
+ m_##member = (rel->member[i] + rel->member[j]) / 2; \
+} while (0)
+
+#define MEDIAN_ODD(member) do { \
+ m_##member = rel->member[i]; \
+} while (0)
+
static void screen_percpu_states(WINDOW *screen, const struct ifstat *rel,
const struct avg_stat *avg, int top_cpus,
int *voff)
@@ -834,6 +844,40 @@ static void screen_percpu_states(WINDOW *screen, const struct ifstat *rel,
100.0 * avg->cpu_sys / all,
100.0 * avg->cpu_idle /all,
100.0 * avg->cpu_iow / all);
+
+ if (show_median) {
+ long double m_cpu_user, m_cpu_nice, m_cpu_sys, m_cpu_idle, m_cpu_iow;
+
+ i = cpu_hits[cpus / 2].idx;
+ if (cpus % 2 == 0) {
+ /* take the mean of the 2 middle entries */
+ int j = cpu_hits[(cpus / 2) - 1].idx;
+
+ MEDIAN_EVEN(cpu_user);
+ MEDIAN_EVEN(cpu_nice);
+ MEDIAN_EVEN(cpu_sys);
+ MEDIAN_EVEN(cpu_idle);
+ MEDIAN_EVEN(cpu_iow);
+ } else {
+ /* take the middle entry as is */
+ MEDIAN_ODD(cpu_user);
+ MEDIAN_ODD(cpu_nice);
+ MEDIAN_ODD(cpu_sys);
+ MEDIAN_ODD(cpu_idle);
+ MEDIAN_ODD(cpu_iow);
+ }
+
+ all = m_cpu_user + m_cpu_sys + m_cpu_nice + m_cpu_idle + m_cpu_iow;
+ mvwprintw(screen, (*voff)++, 2,
+ "med: %14.1lf%% "
+ "%9.1lf%% "
+ "%10.1lf%% "
+ "%11.1lf%%",
+ 100.0 * (m_cpu_user + m_cpu_nice) / all,
+ 100.0 * m_cpu_sys / all,
+ 100.0 * m_cpu_idle /all,
+ 100.0 * m_cpu_iow / all);
+ }
}
static void screen_percpu_irqs_rel_one(WINDOW *screen, const struct ifstat *rel,
@@ -875,6 +919,31 @@ static void screen_percpu_irqs_rel(WINDOW *screen, const struct ifstat *rel,
"%17.1Lf "
"%17.1Lf", max_padd, "",
avg->irqs_rel, avg->irqs_srx_rel, avg->irqs_stx_rel);
+
+ if (show_median) {
+ long double m_irqs, m_irqs_srx, m_irqs_stx;
+
+ i = cpu_hits[cpus / 2].idx;
+ if (cpus % 2 == 0) {
+ /* take the mean of the 2 middle entries */
+ int j = cpu_hits[(cpus / 2) - 1].idx;
+
+ MEDIAN_EVEN(irqs);
+ MEDIAN_EVEN(irqs_srx);
+ MEDIAN_EVEN(irqs_stx);
+ } else {
+ /* take the middle entry as is */
+ MEDIAN_ODD(irqs);
+ MEDIAN_ODD(irqs_srx);
+ MEDIAN_ODD(irqs_stx);
+ }
+
+ mvwprintw(screen, (*voff)++, 2,
+ "med:%*s%17.1Lf "
+ "%17.1Lf "
+ "%17.1Lf", max_padd, "",
+ m_irqs, m_irqs_srx, m_irqs_stx);
+ }
}
static void screen_percpu_irqs_abs_one(WINDOW *screen, const struct ifstat *abs,
@@ -908,6 +977,24 @@ static void screen_percpu_irqs_abs(WINDOW *screen, const struct ifstat *abs,
mvwprintw(screen, (*voff)++, 2,
"avg:%*s%17.1Lf", max_padd, "", avg->irqs_abs);
+
+ if (show_median) {
+ long double m_irqs;
+
+ i = cpu_hits[cpus / 2].idx;
+ if (cpus % 2 == 0) {
+ /* take the mean of the 2 middle entries */
+ int j = cpu_hits[(cpus / 2) - 1].idx;
+
+ m_irqs = (abs->irqs[i] + abs->irqs[j]) / 2;
+ } else {
+ /* take the middle entry as is */
+ m_irqs = abs->irqs[i];
+ }
+
+ mvwprintw(screen, (*voff)++, 2,
+ "med:%*s%17.1Lf", max_padd, "", m_irqs);
+ }
}
static void screen_wireless(WINDOW *screen, const struct ifstat *rel,
@@ -1225,6 +1312,9 @@ int main(int argc, char **argv)
case 'p':
promisc = 1;
break;
+ case 'm':
+ show_median = 1;
+ break;
case 'c':
func_main = term_main;
break;