Compare commits

...

2 Commits

Author SHA1 Message Date
Ondřej Surý
56346b1f85 WIP: enable tracklines 2021-12-13 22:27:02 +01:00
Ondřej Surý
ec8d1e344b WIP: very crude per-file mem stats 2021-12-13 22:04:12 +01:00
2 changed files with 77 additions and 16 deletions

View File

@@ -32,7 +32,7 @@ typedef void (*isc_mem_water_t)(void *, int);
* allocation and freeing by file and line number.
*/
#ifndef ISC_MEM_TRACKLINES
#define ISC_MEM_TRACKLINES 0
#define ISC_MEM_TRACKLINES 1
#endif /* ifndef ISC_MEM_TRACKLINES */
extern unsigned int isc_mem_debugging;

View File

@@ -105,8 +105,10 @@ struct element {
};
struct stats {
char *file;
atomic_size_t gets;
atomic_size_t totalgets;
atomic_size_t inuse;
};
#define MEM_MAGIC ISC_MAGIC('M', 'e', 'm', 'C')
@@ -132,6 +134,7 @@ struct isc_mem {
isc_mutex_t lock;
bool checkfree;
struct stats stats[STATS_BUCKETS + 1];
struct stats file_stats[STATS_BUCKETS * 2];
isc_refcount_t references;
char name[16];
atomic_size_t total;
@@ -387,11 +390,29 @@ mem_realloc(isc_mem_t *ctx, void *old_ptr, size_t old_size, size_t new_size) {
? &ctx->stats[STATS_BUCKETS] \
: &ctx->stats[size / STATS_BUCKET_SIZE])
static struct stats *
stats_file_bucket(isc_mem_t *ctx, const char *file) {
uint32_t h = isc_hash32(file, strlen(file), false);
int idx = h % STATS_BUCKETS;
while (ctx->file_stats[idx].file != NULL &&
strcmp(ctx->file_stats[idx].file, file) != 0)
{
idx = (idx + 1) % STATS_BUCKETS;
}
if (ctx->file_stats[idx].file == NULL) {
ctx->file_stats[idx].file = strdup(file);
}
return (&ctx->file_stats[idx]);
}
/*!
* Update internal counters after a memory get.
*/
static inline void
mem_getstats(isc_mem_t *ctx, size_t size) {
mem_getstats(isc_mem_t *ctx, size_t size FLARG) {
struct stats *stats = stats_bucket(ctx, size);
atomic_fetch_add_relaxed(&ctx->total, size);
@@ -400,6 +421,10 @@ mem_getstats(isc_mem_t *ctx, size_t size) {
atomic_fetch_add_relaxed(&stats->gets, 1);
atomic_fetch_add_relaxed(&stats->totalgets, 1);
UNUSED(line);
stats = stats_file_bucket(ctx, file);
atomic_fetch_add_release(&stats->inuse, size);
increment_malloced(ctx, size);
}
@@ -407,7 +432,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) {
* Update internal counters after a memory put.
*/
static inline void
mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {
mem_putstats(isc_mem_t *ctx, void *ptr, size_t size FLARG) {
struct stats *stats = stats_bucket(ctx, size);
UNUSED(ptr);
@@ -416,6 +441,10 @@ mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {
INSIST(atomic_fetch_sub_release(&stats->gets, 1) >= 1);
UNUSED(line);
stats = stats_file_bucket(ctx, file);
atomic_fetch_sub_release(&stats->inuse, size);
decrement_malloced(ctx, size);
}
@@ -479,6 +508,9 @@ mem_create(isc_mem_t **ctxp, unsigned int flags) {
atomic_init(&ctx->stats[i].gets, 0);
atomic_init(&ctx->stats[i].totalgets, 0);
}
for (size_t i = 0; i < STATS_BUCKETS; i++) {
atomic_init(&ctx->file_stats[i].inuse, 0);
}
ISC_LIST_INIT(ctx->pools);
#if ISC_MEM_TRACKLINES
@@ -521,6 +553,11 @@ destroy(isc_mem_t *ctx) {
ctx->magic = 0;
INSIST(ISC_LIST_EMPTY(ctx->pools));
for (i = 0; i < (size_t)STATS_BUCKETS; i++) {
if (ctx->file_stats[i].file != NULL) {
free(ctx->file_stats[i].file);
}
}
#if ISC_MEM_TRACKLINES
if (ctx->debuglist != NULL) {
@@ -629,7 +666,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
DELETE_TRACE(ctx, ptr, size, file, line);
mem_putstats(ctx, ptr, size);
mem_putstats(ctx, ptr, size FLARG_PASS);
mem_put(ctx, ptr, size);
if (isc_refcount_decrement(&ctx->references) == 1) {
@@ -752,7 +789,7 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
ptr = mem_get(ctx, size);
mem_getstats(ctx, size);
mem_getstats(ctx, size FLARG_PASS);
ADD_TRACE(ctx, ptr, size, file, line);
CALL_HI_WATER(ctx);
@@ -766,7 +803,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) {
DELETE_TRACE(ctx, ptr, size, file, line);
mem_putstats(ctx, ptr, size);
mem_putstats(ctx, ptr, size FLARG_PASS);
mem_put(ctx, ptr, size);
CALL_LO_WATER(ctx);
@@ -889,7 +926,7 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
/* Recalculate the real allocated size */
size = sallocx(ptr, 0);
mem_getstats(ctx, size);
mem_getstats(ctx, size FLARG_PASS);
ADD_TRACE(ctx, ptr, size, file, line);
CALL_HI_WATER(ctx);
@@ -909,11 +946,11 @@ isc__mem_reget(isc_mem_t *ctx, void *old_ptr, size_t old_size,
isc__mem_put(ctx, old_ptr, old_size FLARG_PASS);
} else {
DELETE_TRACE(ctx, old_ptr, old_size, file, line);
mem_putstats(ctx, old_ptr, old_size);
mem_putstats(ctx, old_ptr, old_size FLARG_PASS);
new_ptr = mem_realloc(ctx, old_ptr, old_size, new_size);
mem_getstats(ctx, new_size);
mem_getstats(ctx, new_size FLARG_PASS);
ADD_TRACE(ctx, new_ptr, new_size, file, line);
/*
@@ -942,14 +979,14 @@ isc__mem_reallocate(isc_mem_t *ctx, void *old_ptr, size_t new_size FLARG) {
size_t old_size = sallocx(old_ptr, 0);
DELETE_TRACE(ctx, old_ptr, old_size, file, line);
mem_putstats(ctx, old_ptr, old_size);
mem_putstats(ctx, old_ptr, old_size FLARG_PASS);
new_ptr = mem_realloc(ctx, old_ptr, old_size, new_size);
/* Recalculate the real allocated size */
new_size = sallocx(new_ptr, 0);
mem_getstats(ctx, new_size);
mem_getstats(ctx, new_size FLARG_PASS);
ADD_TRACE(ctx, new_ptr, new_size, file, line);
/*
@@ -974,7 +1011,7 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
DELETE_TRACE(ctx, ptr, size, file, line);
mem_putstats(ctx, ptr, size);
mem_putstats(ctx, ptr, size FLARG_PASS);
mem_put(ctx, ptr, size);
CALL_LO_WATER(ctx);
@@ -1242,7 +1279,7 @@ isc__mempool_destroy(isc_mempool_t **restrict mpctxp FLARG) {
item = mpctx->items;
mpctx->items = item->next;
mem_putstats(mctx, item, mpctx->size);
mem_putstats(mctx, item, mpctx->size FLARG_PASS);
mem_put(mctx, item, mpctx->size);
}
@@ -1297,7 +1334,7 @@ isc__mempool_get(isc_mempool_t *restrict mpctx FLARG) {
*/
for (size_t i = 0; i < fillcount; i++) {
item = mem_get(mctx, mpctx->size);
mem_getstats(mctx, mpctx->size);
mem_getstats(mctx, mpctx->size FLARG_PASS);
item->next = mpctx->items;
mpctx->items = item;
mpctx->freecount++;
@@ -1339,7 +1376,7 @@ isc__mempool_put(isc_mempool_t *restrict mpctx, void *mem FLARG) {
* If our free list is full, return this to the mctx directly.
*/
if (freecount >= freemax) {
mem_putstats(mctx, mem, mpctx->size);
mem_putstats(mctx, mem, mpctx->size FLARG_PASS);
mem_put(mctx, mem, mpctx->size);
return;
}
@@ -1623,7 +1660,7 @@ json_renderctx(isc_mem_t *ctx, summarystat_t *summary, json_object *array) {
REQUIRE(summary != NULL);
REQUIRE(array != NULL);
json_object *ctxobj, *obj;
json_object *ctxobj, *obj, *fileobj, *filearray;
char buf[1024];
MCTXLOCK(ctx);
@@ -1643,6 +1680,30 @@ json_renderctx(isc_mem_t *ctx, summarystat_t *summary, json_object *array) {
ctxobj = json_object_new_object();
CHECKMEM(ctxobj);
filearray = json_object_new_array();
CHECKMEM(filearray);
for (int i = 0; i < (int)STATS_BUCKETS; i++) {
if (ctx->file_stats[i].file == NULL) {
continue;
}
fileobj = json_object_new_object();
CHECKMEM(fileobj);
obj = json_object_new_string(ctx->file_stats[i].file);
CHECKMEM(obj);
json_object_object_add(fileobj, "file", obj);
obj = json_object_new_int64(ctx->file_stats[i].inuse);
CHECKMEM(obj);
json_object_object_add(fileobj, "inuse", obj);
json_object_array_add(filearray, fileobj);
}
json_object_object_add(ctxobj, "files", filearray);
snprintf(buf, sizeof(buf), "%p", ctx);
obj = json_object_new_string(buf);
CHECKMEM(obj);