mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
MINOR: activity/memory: count allocations performed under a lock
By checking the current thread's locking status, it becomes possible to know during a memory allocation whether it's performed under a lock or not. Both pools and memprofile functions were instrumented to check for this and to increment the memprofile bin's locked_calls counter. This one, when not zero, is reported on "show profiling memory" with a percentage of all allocations that such locked allocations represent. This way it becomes possible to try to target certain code paths that are particularly expensive. Example: $ socat - /tmp/sock1 <<< "show profiling memory"|grep lock 20297301 0 2598054528 0| 0x62a820fa3991 sockaddr_alloc+0x61/0xa3 p_alloc(128) [pool=sockaddr] [locked=54962 (0.2 %)] 0 20297301 0 2598054528| 0x62a820fa3a24 sockaddr_free+0x44/0x59 p_free(-128) [pool=sockaddr] [locked=34300 (0.1 %)] 9908432 0 1268279296 0| 0x62a820eb8524 main+0x81974 p_alloc(128) [pool=task] [locked=9908432 (100.0 %)] 9908432 0 554872192 0| 0x62a820eb85a6 main+0x819f6 p_alloc(56) [pool=tasklet] [locked=9908432 (100.0 %)] 263001 0 63120240 0| 0x62a820fa3c97 conn_new+0x37/0x1b2 p_alloc(240) [pool=connection] [locked=20662 (7.8 %)] 71643 0 47307584 0| 0x62a82105204d pool_get_from_os_noinc+0x12d/0x161 posix_memalign(660) [locked=5393 (7.5 %)]
This commit is contained in:
parent
9d8c2a888b
commit
8fb5ae5cc6
@ -76,12 +76,12 @@ struct memprof_stats {
|
|||||||
const void *caller;
|
const void *caller;
|
||||||
enum memprof_method method;
|
enum memprof_method method;
|
||||||
/* 4-7 bytes hole here */
|
/* 4-7 bytes hole here */
|
||||||
|
unsigned long long locked_calls;
|
||||||
unsigned long long alloc_calls;
|
unsigned long long alloc_calls;
|
||||||
unsigned long long free_calls;
|
unsigned long long free_calls;
|
||||||
unsigned long long alloc_tot;
|
unsigned long long alloc_tot;
|
||||||
unsigned long long free_tot;
|
unsigned long long free_tot;
|
||||||
void *info; // for pools, ptr to the pool
|
void *info; // for pools, ptr to the pool
|
||||||
void *pad; // pad to 64
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -342,6 +342,8 @@ void *malloc(size_t size)
|
|||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_MALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_MALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -367,6 +369,8 @@ void *calloc(size_t nmemb, size_t size)
|
|||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_CALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_CALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -400,6 +404,8 @@ void *realloc(void *ptr, size_t size)
|
|||||||
size += sizeof(void *);
|
size += sizeof(void *);
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_REALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_REALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
if (size > size_before) {
|
if (size > size_before) {
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size - size_before);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size - size_before);
|
||||||
@ -431,6 +437,8 @@ char *strdup(const char *s)
|
|||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_STRDUP);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_STRDUP);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -461,6 +469,8 @@ void free(void *ptr)
|
|||||||
memprof_free_handler(ptr);
|
memprof_free_handler(ptr);
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_FREE);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_FREE);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->free_calls, 1);
|
_HA_ATOMIC_ADD(&bin->free_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->free_tot, size_before);
|
_HA_ATOMIC_ADD(&bin->free_tot, size_before);
|
||||||
}
|
}
|
||||||
@ -481,6 +491,8 @@ char *strndup(const char *s, size_t size)
|
|||||||
|
|
||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_STRNDUP);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_STRNDUP);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -500,6 +512,8 @@ void *valloc(size_t size)
|
|||||||
|
|
||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_VALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_VALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -519,6 +533,8 @@ void *pvalloc(size_t size)
|
|||||||
|
|
||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_PVALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_PVALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -538,6 +554,8 @@ void *memalign(size_t align, size_t size)
|
|||||||
|
|
||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_MEMALIGN);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_MEMALIGN);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -557,6 +575,8 @@ void *aligned_alloc(size_t align, size_t size)
|
|||||||
|
|
||||||
size = malloc_usable_size(ret) + sizeof(void *);
|
size = malloc_usable_size(ret) + sizeof(void *);
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_ALIGNED_ALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_ALIGNED_ALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -579,6 +599,8 @@ int posix_memalign(void **ptr, size_t align, size_t size)
|
|||||||
|
|
||||||
size = malloc_usable_size(*ptr) + sizeof(void *);
|
size = malloc_usable_size(*ptr) + sizeof(void *);
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_POSIX_MEMALIGN);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_POSIX_MEMALIGN);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, size);
|
||||||
return ret;
|
return ret;
|
||||||
@ -715,6 +737,7 @@ static int cli_parse_set_profiling(char **args, char *payload, struct appctx *ap
|
|||||||
|
|
||||||
/* also flush current profiling stats */
|
/* also flush current profiling stats */
|
||||||
for (i = 0; i < sizeof(memprof_stats) / sizeof(memprof_stats[0]); i++) {
|
for (i = 0; i < sizeof(memprof_stats) / sizeof(memprof_stats[0]); i++) {
|
||||||
|
HA_ATOMIC_STORE(&memprof_stats[i].locked_calls, 0);
|
||||||
HA_ATOMIC_STORE(&memprof_stats[i].alloc_calls, 0);
|
HA_ATOMIC_STORE(&memprof_stats[i].alloc_calls, 0);
|
||||||
HA_ATOMIC_STORE(&memprof_stats[i].free_calls, 0);
|
HA_ATOMIC_STORE(&memprof_stats[i].free_calls, 0);
|
||||||
HA_ATOMIC_STORE(&memprof_stats[i].alloc_tot, 0);
|
HA_ATOMIC_STORE(&memprof_stats[i].alloc_tot, 0);
|
||||||
@ -1125,6 +1148,15 @@ static int cli_io_handler_show_profiling(struct appctx *appctx)
|
|||||||
chunk_appendf(&trash," [pool=%s]", pool->name);
|
chunk_appendf(&trash," [pool=%s]", pool->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry->locked_calls) {
|
||||||
|
unsigned long long tot_calls = entry->alloc_calls + entry->free_calls;
|
||||||
|
|
||||||
|
chunk_appendf(&trash," [locked=%llu (%d.%1d %%)]",
|
||||||
|
entry->locked_calls,
|
||||||
|
(int)(100ULL * entry->locked_calls / tot_calls),
|
||||||
|
(int)((1000ULL * entry->locked_calls / tot_calls) % 10));
|
||||||
|
}
|
||||||
|
|
||||||
chunk_appendf(&trash, "\n");
|
chunk_appendf(&trash, "\n");
|
||||||
|
|
||||||
if (applet_putchk(appctx, &trash) == -1)
|
if (applet_putchk(appctx, &trash) == -1)
|
||||||
|
@ -953,7 +953,7 @@ void pool_gc(struct pool_head *pool_ctx)
|
|||||||
uint64_t mem_wait_start = 0;
|
uint64_t mem_wait_start = 0;
|
||||||
int isolated = thread_isolated();
|
int isolated = thread_isolated();
|
||||||
|
|
||||||
if (th_ctx->flags & TH_FL_TASK_PROFILING)
|
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING))
|
||||||
mem_wait_start = now_mono_time();
|
mem_wait_start = now_mono_time();
|
||||||
|
|
||||||
if (!isolated)
|
if (!isolated)
|
||||||
@ -1031,6 +1031,8 @@ void *__pool_alloc(struct pool_head *pool, unsigned int flags)
|
|||||||
struct memprof_stats *bin;
|
struct memprof_stats *bin;
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_P_ALLOC);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_P_ALLOC);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->alloc_tot, pool->size);
|
_HA_ATOMIC_ADD(&bin->alloc_tot, pool->size);
|
||||||
_HA_ATOMIC_STORE(&bin->info, pool);
|
_HA_ATOMIC_STORE(&bin->info, pool);
|
||||||
@ -1069,6 +1071,8 @@ void __pool_free(struct pool_head *pool, void *ptr)
|
|||||||
struct memprof_stats *bin;
|
struct memprof_stats *bin;
|
||||||
|
|
||||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_P_FREE);
|
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_P_FREE);
|
||||||
|
if (unlikely(th_ctx->lock_level & 0x7F))
|
||||||
|
_HA_ATOMIC_ADD(&bin->locked_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->free_calls, 1);
|
_HA_ATOMIC_ADD(&bin->free_calls, 1);
|
||||||
_HA_ATOMIC_ADD(&bin->free_tot, pool->size);
|
_HA_ATOMIC_ADD(&bin->free_tot, pool->size);
|
||||||
_HA_ATOMIC_STORE(&bin->info, pool);
|
_HA_ATOMIC_STORE(&bin->info, pool);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user