]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: activity: report the number of failed pool/buffer allocations
authorWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 15:04:16 +0000 (17:04 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 15:25:21 +0000 (17:25 +0200)
Haproxy is designed to be able to continue to run even under very low
memory conditions. However this can sometimes have a serious impact on
performance that it hard to diagnose. Let's report counters of failed
pool and buffer allocations per thread in show activity.

include/common/buffer.h
include/types/activity.h
src/cli.c
src/memory.c

index ce6d38c63e3d01f239ae1f4035b62aabfa706353..960402633f3c47f2f72dd1064fd3d0f8d519b078 100644 (file)
@@ -33,6 +33,7 @@
 #include <common/istbuf.h>
 #include <common/memory.h>
 
+#include <proto/activity.h>
 
 /* an element of the <buffer_wq> list. It represents an object that need to
  * acquire a buffer to continue its process. */
@@ -77,8 +78,10 @@ static inline struct buffer *b_alloc(struct buffer *buf)
 
        *buf = BUF_WANTED;
        area = pool_alloc_dirty(pool_head_buffer);
-       if (unlikely(!area))
+       if (unlikely(!area)) {
+               activity[tid].buf_wait++;
                return NULL;
+       }
 
        buf->area = area;
        buf->size = pool_head_buffer->size;
@@ -175,8 +178,10 @@ static inline struct buffer *b_alloc_margin(struct buffer *buf, int margin)
        HA_SPIN_UNLOCK(POOL_LOCK, &pool_head_buffer->lock);
 #endif
 
-       if (unlikely(!area))
+       if (unlikely(!area)) {
+               activity[tid].buf_wait++;
                return NULL;
+       }
 
  done:
        buf->area = area;
index 618785da863abdd49476696f16b51659edcf54dd..37251502e2ff0f5b960a63c3f2883d342e6fabd3 100644 (file)
@@ -54,6 +54,8 @@ struct activity {
        unsigned int accepted;     // accepted incoming connections
        unsigned int accq_pushed;  // accept queue connections pushed
        unsigned int accq_full;    // accept queue connection not pushed because full
+       unsigned int pool_fail;    // failed a pool allocation
+       unsigned int buf_wait;     // waited on a buffer allocation
 #if defined(DEBUG_DEV)
        /* keep these ones at the end */
        unsigned int ctr0;         // general purposee debug counter
index 41f403b10439095d583989a1c0de192af5ed492e..9949a885aeb255ee06935086801f092c5b2b8004 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -1117,6 +1117,8 @@ static int cli_io_handler_show_activity(struct appctx *appctx)
        chunk_appendf(&trash, "fd_lock:");      SHOW_TOT(thr, activity[thr].fd_lock);
        chunk_appendf(&trash, "conn_dead:");    SHOW_TOT(thr, activity[thr].conn_dead);
        chunk_appendf(&trash, "stream:");       SHOW_TOT(thr, activity[thr].stream);
+       chunk_appendf(&trash, "pool_fail:");    SHOW_TOT(thr, activity[thr].pool_fail);
+       chunk_appendf(&trash, "buf_wait:");     SHOW_TOT(thr, activity[thr].buf_wait);
        chunk_appendf(&trash, "empty_rq:");     SHOW_TOT(thr, activity[thr].empty_rq);
        chunk_appendf(&trash, "long_rq:");      SHOW_TOT(thr, activity[thr].long_rq);
        chunk_appendf(&trash, "ctxsw:");        SHOW_TOT(thr, activity[thr].ctxsw);
index 6555913de6335fc5c52e810d7bb6af37fd006d06..6331c84456749c45a9c7f387c91ebd7cf06cb9b8 100644 (file)
@@ -25,6 +25,8 @@
 #include <common/mini-clist.h>
 #include <common/standard.h>
 
+#include <types/activity.h>
+
 #include <proto/applet.h>
 #include <proto/cli.h>
 #include <proto/channel.h>
@@ -160,14 +162,17 @@ void *__pool_refill_alloc(struct pool_head *pool, unsigned int avail)
        while (1) {
                if (limit && allocated >= limit) {
                        _HA_ATOMIC_ADD(&pool->allocated, allocated - allocated_orig);
+                       activity[tid].pool_fail++;
                        return NULL;
                }
 
                ptr = malloc(size + POOL_EXTRA);
                if (!ptr) {
                        _HA_ATOMIC_ADD(&pool->failed, 1);
-                       if (failed)
+                       if (failed) {
+                               activity[tid].pool_fail++;
                                return NULL;
+                       }
                        failed++;
                        pool_gc(pool);
                        continue;
@@ -317,14 +322,18 @@ void *__pool_refill_alloc(struct pool_head *pool, unsigned int avail)
        avail += pool->used;
 
        while (1) {
-               if (pool->limit && pool->allocated >= pool->limit)
+               if (pool->limit && pool->allocated >= pool->limit) {
+                       activity[tid].pool_fail++;
                        return NULL;
+               }
 
                ptr = pool_alloc_area(pool->size + POOL_EXTRA);
                if (!ptr) {
                        pool->failed++;
-                       if (failed)
+                       if (failed) {
+                               activity[tid].pool_fail++;
                                return NULL;
+                       }
                        failed++;
                        pool_gc(pool);
                        continue;