src/oping.c: Add median and 'n'th percentile, remove average and stddev.
[liboping.git] / src / oping.c
index 6496331..ff06670 100644 (file)
@@ -95,6 +95,9 @@
 # define OPING_YELLOW_HIST 5
 # define OPING_RED_HIST 6
 
+double const threshold_green = 0.8;
+double const threshold_yellow = 0.95;
+
 static char const * const hist_symbols_utf8[] = {
        "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" };
 static size_t const hist_symbols_utf8_num = sizeof (hist_symbols_utf8)
@@ -160,7 +163,6 @@ typedef struct ping_context
        double latency_min;
        double latency_max;
        double latency_total;
-       double latency_total_square;
 
 /* 1000 + one "infinity" bucket. */
 #define OPING_HISTOGRAM_BUCKETS 1001
@@ -216,7 +218,6 @@ static ping_context_t *context_create (void) /* {{{ */
        ret->latency_min   = -1.0;
        ret->latency_max   = -1.0;
        ret->latency_total = 0.0;
-       ret->latency_total_square = 0.0;
 
        ret->latency_histogram_size = (size_t) OPING_HISTOGRAM_BUCKETS;
        ret->histogram_counters = calloc (ret->latency_histogram_size,
@@ -258,26 +259,13 @@ static void context_destroy (ping_context_t *context) /* {{{ */
        free (context);
 } /* }}} void context_destroy */
 
-static double context_get_average (ping_context_t *ctx) /* {{{ */
-{
-       double num_total;
-
-       if (ctx == NULL)
-               return (-1.0);
-
-       if (ctx->req_rcvd < 1)
-               return (-0.0);
-
-       num_total = (double) ctx->req_rcvd;
-       return (ctx->latency_total / num_total);
-} /* }}} double context_get_average */
-
 static double context_get_percentile (ping_context_t *ctx, /* {{{ */
                double percentile)
 {
        double threshold = percentile / 100.0;
        double index_to_ms_factor;
        size_t i;
+       double ret;
 
        if (ctx->histogram_ratio == NULL)
                return (NAN);
@@ -295,26 +283,14 @@ static double context_get_percentile (ping_context_t *ctx, /* {{{ */
 
        /* Multiply with i+1, because we're interested in the _upper_ bound of
         * each bucket. */
-       return (index_to_ms_factor * ((double) (i + 1)));
-} /* }}} double context_get_percentile */
-
-static double context_get_stddev (ping_context_t *ctx) /* {{{ */
-{
-       double num_total;
+       ret = (index_to_ms_factor * ((double) (i + 1)));
 
-       if (ctx == NULL)
-               return (-1.0);
-
-       if (ctx->req_rcvd < 1)
-               return (-0.0);
-       else if (ctx->req_rcvd < 2)
-               return (0.0);
+       /* Avoid reporting a higher latency than latency_max. */
+       if (ret > ctx->latency_max)
+               ret = ctx->latency_max;
 
-       num_total = (double) ctx->req_rcvd;
-       return (sqrt (((num_total * ctx->latency_total_square)
-                                       - (ctx->latency_total * ctx->latency_total))
-                               / (num_total * (num_total - 1.0))));
-} /* }}} double context_get_stddev */
+       return (ret);
+} /* }}} double context_get_percentile */
 
 static double context_get_packet_loss (const ping_context_t *ctx) /* {{{ */
 {
@@ -1020,9 +996,13 @@ static int update_graph_histogram (ping_context_t *ctx) /* {{{ */
 
                if (has_colors () == TRUE)
                {
-                       if ((ratio_this <= 0.5) || ((ratio_prev < 0.5) && (ratio_this > 0.5)))
+                       if ((ratio_this <= threshold_green)
+                                       || ((ratio_prev < threshold_green)
+                                               && (ratio_this > threshold_green)))
                                color = OPING_GREEN;
-                       else if ((ratio_this <= 0.95) || ((ratio_prev < 0.95) && (ratio_this > 0.95)))
+                       else if ((ratio_this <= threshold_yellow)
+                                       || ((ratio_prev < threshold_yellow)
+                                               && (ratio_this > threshold_yellow)))
                                color = OPING_YELLOW;
                        else
                                color = OPING_RED;
@@ -1081,23 +1061,17 @@ static int update_stats_from_context (ping_context_t *ctx, pingobj_iter_t *iter)
                        ctx->latency_total);
        if (ctx->req_rcvd != 0)
        {
-               double average;
-               double deviation;
+               double median;
                double percentile;
 
-               average = context_get_average (ctx);
-               deviation = context_get_stddev (ctx);
+               median = context_get_percentile (ctx, 50.0);
                percentile = context_get_percentile (ctx, opt_percentile);
 
                mvwprintw (ctx->window, /* y = */ 2, /* x = */ 2,
-                               "rtt min/avg/%.0f%%/max/sdev = "
-                               "%.3f/%.3f/%.0f/%.3f/%.3f ms\n",
-                               opt_percentile,
-                               ctx->latency_min,
-                               average,
-                               percentile,
-                               ctx->latency_max,
-                               deviation);
+                               "RTT[ms]: min = %.0f, median = %.0f, p(%.0f) = %.0f, max = %.0f",
+                               ctx->latency_min, median,
+                               opt_percentile, percentile,
+                               ctx->latency_max);
        }
 
        if (opt_show_graph == 1)
@@ -1320,7 +1294,6 @@ static void update_context (ping_context_t *context, double latency) /* {{{ */
 
        context->req_rcvd++;
        context->latency_total += latency;
-       context->latency_total_square += (latency * latency);
 
        if ((context->latency_max < 0.0) || (context->latency_max < latency))
                context->latency_max = latency;
@@ -1406,11 +1379,13 @@ static void update_host_hook (pingobj_iter_t *iter, /* {{{ */
                        else
                                ratio_prev = 0.0;
 
-                       if ((ratio_this <= 0.5) ||
-                                       ((ratio_prev < 0.5) && (ratio_this > 0.5)))
+                       if ((ratio_this <= threshold_green)
+                                       || ((ratio_prev < threshold_green)
+                                               && (ratio_this > threshold_green)))
                                color = OPING_GREEN;
-                       else if ((ratio_this <= 0.95) ||
-                                       ((ratio_prev < 0.95) && (ratio_this > 0.95)))
+                       else if ((ratio_this <= threshold_yellow)
+                                       || ((ratio_prev < threshold_yellow)
+                                               && (ratio_this > threshold_yellow)))
                                color = OPING_YELLOW;
                        else
                                color = OPING_RED;
@@ -1447,7 +1422,7 @@ static void update_host_hook (pingobj_iter_t *iter, /* {{{ */
                }
 #endif
        }
-       else
+       else /* if (!(latency > 0.0)) */
        {
 #if USE_NCURSES
                if (has_colors () == TRUE)
@@ -1512,22 +1487,16 @@ static int post_loop_hook (pingobj_t *ping) /* {{{ */
 
                if (context->req_rcvd != 0)
                {
-                       double average;
-                       double deviation;
+                       double median;
                        double percentile;
 
-                       average = context_get_average (context);
-                       deviation = context_get_stddev (context);
+                       median = context_get_percentile (context, 50.0);
                        percentile = context_get_percentile (context, opt_percentile);
 
-                       printf ("rtt min/avg/%.0f%%/max/sdev = "
-                                       "%.3f/%.3f/%.0f/%.3f/%.3f ms\n",
-                                       opt_percentile,
-                                       context->latency_min,
-                                       average,
-                                       percentile,
-                                       context->latency_max,
-                                       deviation);
+                       printf ("RTT[ms]: min = %.0f, median = %.0f, p(%.0f) = %.0f, max = %.0f\n",
+                                       context->latency_min, median,
+                                       opt_percentile, percentile,
+                                       context->latency_max);
                }
 
                ping_iterator_set_context (iter, NULL);
@@ -1743,6 +1712,9 @@ int main (int argc, char **argv) /* {{{ */
                exit (EXIT_FAILURE);
        }
 
+       if (host_num == 0)
+               exit (EXIT_FAILURE);
+
 #if _POSIX_SAVED_IDS
        saved_set_uid = (uid_t) -1;
 #endif