DEBUG: pool: store the memprof bin on alloc() and update it on free()
When looking at "show pools", it's often difficult to know which alloc() corresponds to which free() since it's not often 1:1. But sometimes we have all elements available to maintain a link between alloc and free. Indeed, when the caller is recorded in the allocated area, we can store the pointer to the just created bin instead of the caller address itself, since the caller address is already in the memprof bin. By doing so, we permit the pool_free() call to locate the allocator bin and update its free count when caller tracing is enabled. This for example allows to produce outputs like this on "show profiling" and a process started with -dMcaller: 1391967 1391968 22805987328 22806003712| 0x59f72f process_stream+0x19f/0x3a7a p_alloc(0) [delta=-16384] [pool=buffer] 1391936 1391937 22805479424 22805495808| 0x6e1476 task_run_applet+0x426/0xea2 p_alloc(0) [delta=-16384] [pool=buffer] 1391925 1391925 22805299200 22805299200| 0x58435a main+0xdf07a p_alloc(0) [delta=0] [pool=buffer] 0 2087930 0 34208645120| 0x59b519 stream_release_buffers+0xf9/0x110 p_free(-16384) [pool=buffer] 695993 695992 11403149312 11403132928| 0x66018f main+0x1baeaf p_alloc(0) [delta=16384] [pool=buffer] 0 1391957 0 22805823488| 0x59b47c stream_release_buffers+0x5c/0x110 p_free(-16384) [pool=buffer] 695968 695970 11402739712 11402772480| 0x587b85 h1_io_cb+0x9a5/0xe7c p_alloc(0) [delta=-32768] [pool=buffer] 0 1391923 0 22805266432| 0x57f388 main+0xda0a8 p_free(-16384) [pool=buffer] 695959 695960 11402592256 11402608640| 0x586add main+0xe17fd p_alloc(0) [delta=-16384] [pool=buffer] 0 695978 0 11402903552| 0x59cc58 stream_free+0x178/0x9ea p_free(-16384) [pool=buffer] (...) Here it's quickly visible that all of them got properly released.
This commit is contained in:
parent
68d02e5fa9
commit
5714aff4a6
18
src/pool.c
18
src/pool.c
@ -844,12 +844,20 @@ void *__pool_alloc(struct pool_head *pool, unsigned int flags)
|
||||
if (likely(p)) {
|
||||
#ifdef USE_MEMORY_PROFILING
|
||||
if (unlikely(profiling & HA_PROF_MEMORY)) {
|
||||
extern struct memprof_stats memprof_stats[MEMPROF_HASH_BUCKETS + 1];
|
||||
struct memprof_stats *bin;
|
||||
|
||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_P_ALLOC);
|
||||
_HA_ATOMIC_ADD(&bin->alloc_calls, 1);
|
||||
_HA_ATOMIC_ADD(&bin->alloc_tot, pool->size);
|
||||
_HA_ATOMIC_STORE(&bin->info, pool);
|
||||
/* replace the caller with the allocated bin: this way
|
||||
* we'll the pool_free() call will be able to update our
|
||||
* entry. We only do it for non-colliding entries though,
|
||||
* since thse ones store the true caller location.
|
||||
*/
|
||||
if (bin >= &memprof_stats[0] && bin < &memprof_stats[MEMPROF_HASH_BUCKETS])
|
||||
POOL_DEBUG_TRACE_CALLER(pool, (struct pool_cache_item *)p, bin);
|
||||
}
|
||||
#endif
|
||||
if (unlikely(flags & POOL_F_MUST_ZERO))
|
||||
@ -874,12 +882,22 @@ void __pool_free(struct pool_head *pool, void *ptr)
|
||||
|
||||
#ifdef USE_MEMORY_PROFILING
|
||||
if (unlikely(profiling & HA_PROF_MEMORY) && ptr) {
|
||||
extern struct memprof_stats memprof_stats[MEMPROF_HASH_BUCKETS + 1];
|
||||
struct memprof_stats *bin;
|
||||
|
||||
bin = memprof_get_bin(__builtin_return_address(0), MEMPROF_METH_P_FREE);
|
||||
_HA_ATOMIC_ADD(&bin->free_calls, 1);
|
||||
_HA_ATOMIC_ADD(&bin->free_tot, pool->size);
|
||||
_HA_ATOMIC_STORE(&bin->info, pool);
|
||||
|
||||
/* check if the caller is an allocator, and if so, let's update
|
||||
* its free() count.
|
||||
*/
|
||||
bin = *(struct memprof_stats**)(((char *)ptr) + pool->alloc_sz - sizeof(void*));
|
||||
if (bin >= &memprof_stats[0] && bin < &memprof_stats[MEMPROF_HASH_BUCKETS]) {
|
||||
_HA_ATOMIC_ADD(&bin->free_calls, 1);
|
||||
_HA_ATOMIC_ADD(&bin->free_tot, pool->size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user