]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: activity: report the number of times poll() reports I/O
authorWilly Tarreau <w@1wt.eu>
Wed, 17 Jun 2020 18:25:18 +0000 (20:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 17 Jun 2020 18:25:18 +0000 (20:25 +0200)
The "show activity" output mentions a number of indicators to explain
wake up reasons but doesn't have the number of times poll() sees some
I/O. And given that multiple events can happen simultaneously, it's
not always possible to deduce this metric by subtracting.

This patch adds a new "poll_io" counter that allows one to see how
often poll() returns with at least one active FD. This should help
detect stuck events and measure various ratios of poll sub-metrics.

include/haproxy/activity-t.h
src/cli.c
src/ev_epoll.c
src/ev_evports.c
src/ev_kqueue.c
src/ev_poll.c
src/ev_select.c

index 3020806ed01e916410bfbb0b463d255b1d6e4e96..4e2f9f0935f35460f9b03180b7a5a179b65597df 100644 (file)
@@ -40,6 +40,7 @@ struct activity {
        unsigned int loops;        // complete loops in run_poll_loop()
        unsigned int wake_tasks;   // active tasks prevented poll() from sleeping
        unsigned int wake_signal;  // pending signal prevented poll() from sleeping
+       unsigned int poll_io;      // number of times poll() reported I/O events
        unsigned int poll_exp;     // number of times poll() sees an expired timeout (includes wake_*)
        unsigned int poll_drop;    // poller dropped a dead FD from the update list
        unsigned int poll_dead;    // poller woke up with a dead FD
@@ -51,7 +52,7 @@ struct activity {
        unsigned int empty_rq;     // calls to process_runnable_tasks() with nothing for the thread
        unsigned int long_rq;      // process_runnable_tasks() left with tasks in the run queue
        unsigned int cpust_total;  // sum of half-ms stolen per thread
-       /* two unused entries left before end of first cache line */
+       /* one unused entry left before end of first cache line */
        ALWAYS_ALIGN(64);
 
        struct freq_ctr cpust_1s;  // avg amount of half-ms stolen over last second
index 22fc7716bf2f5e3a0b8ea6047d30985b12db0768..1939ec3e6d621dada17226b8f53a099b5907b8b0 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -1129,6 +1129,7 @@ static int cli_io_handler_show_activity(struct appctx *appctx)
        chunk_appendf(&trash, "loops:");        SHOW_TOT(thr, activity[thr].loops);
        chunk_appendf(&trash, "wake_tasks:");   SHOW_TOT(thr, activity[thr].wake_tasks);
        chunk_appendf(&trash, "wake_signal:");  SHOW_TOT(thr, activity[thr].wake_signal);
+       chunk_appendf(&trash, "poll_io:");      SHOW_TOT(thr, activity[thr].poll_io);
        chunk_appendf(&trash, "poll_exp:");     SHOW_TOT(thr, activity[thr].poll_exp);
        chunk_appendf(&trash, "poll_drop:");    SHOW_TOT(thr, activity[thr].poll_drop);
        chunk_appendf(&trash, "poll_dead:");    SHOW_TOT(thr, activity[thr].poll_dead);
index 2501dd5b885d14d35646b61a28fa91548e665c09..e5437a28d822485ec982dcd84763c3ae5c7c76aa 100644 (file)
@@ -180,8 +180,10 @@ static void _do_poll(struct poller *p, int exp, int wake)
                status = epoll_wait(epoll_fd[tid], epoll_events, global.tune.maxpollevents, timeout);
                tv_update_date(timeout, status);
 
-               if (status)
+               if (status) {
+                       activity[tid].poll_io++;
                        break;
+               }
                if (timeout || !wait_time)
                        break;
                if (signal_queue_len || wake)
index 6b14ea0694238245528938428e3e139873e6aa88..50d9a1e7d91a2ff0777c64a2c0e505a682702d0d 100644 (file)
@@ -207,6 +207,9 @@ static void _do_poll(struct poller *p, int exp, int wake)
 
        thread_harmless_end();
 
+       if (nevlist > 0)
+               activity[tid].poll_io++;
+
        for (i = 0; i < nevlist; i++) {
                unsigned int n = 0;
                int events, rebind_events;
index 3a0b0a3fa885fb2cf7dc218dd0de39b4bad52be5..9df987aa847766363d8c1b7e8ea554859df9642e 100644 (file)
@@ -161,8 +161,10 @@ static void _do_poll(struct poller *p, int exp, int wake)
                                &timeout_ts); // const struct timespec *timeout
                tv_update_date(timeout, status);
 
-               if (status)
+               if (status) {
+                       activity[tid].poll_io++;
                        break;
+               }
                if (timeout || !wait_time)
                        break;
                if (signal_queue_len || wake)
index 03d32b008947d50d092dae800336a1941eab3da9..69368ce4e3647b88066fe46b479d04a7f8de562e 100644 (file)
@@ -211,6 +211,9 @@ static void _do_poll(struct poller *p, int exp, int wake)
 
        thread_harmless_end();
 
+       if (status > 0)
+               activity[tid].poll_io++;
+
        for (count = 0; status > 0 && count < nbfd; count++) {
                unsigned int n;
                int e = poll_events[count].revents;
index adc8160046efa6e83cc650d4c5d676bb91dde4ab..d79f09b2e2e4a529add1136f236193b6b1c28753 100644 (file)
@@ -188,6 +188,8 @@ static void _do_poll(struct poller *p, int exp, int wake)
        if (status <= 0)
                return;
 
+       activity[tid].poll_io++;
+
        for (fds = 0; (fds * BITS_PER_INT) < maxfd; fds++) {
                if ((((int *)(tmp_evts[DIR_RD]))[fds] | ((int *)(tmp_evts[DIR_WR]))[fds]) == 0)
                        continue;