mirror of
https://github.com/cryb-to/cryb-to.git
synced 2024-11-25 23:25:42 +00:00
Gather memory allocation statistics and print them at the end if verbose.
This commit is contained in:
parent
4a4726f9d6
commit
bf087fd70e
3 changed files with 41 additions and 1 deletions
3
t/t.h
3
t/t.h
|
@ -116,5 +116,8 @@ extern const uint8_t t_seq8[256];
|
||||||
*/
|
*/
|
||||||
extern int t_malloc_fail;
|
extern int t_malloc_fail;
|
||||||
extern int t_malloc_fatal;
|
extern int t_malloc_fatal;
|
||||||
|
#ifdef _IONBF /* proxy for <stdio.h> */
|
||||||
|
void t_malloc_printstats(FILE *);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -203,5 +203,12 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
/* clean up and exit */
|
/* clean up and exit */
|
||||||
t_cleanup();
|
t_cleanup();
|
||||||
|
for (n = 0; n < t_plan_len; ++n) {
|
||||||
|
free(t_plan[n]->desc);
|
||||||
|
free(t_plan[n]);
|
||||||
|
}
|
||||||
|
free(t_plan);
|
||||||
|
if (verbose)
|
||||||
|
t_malloc_printstats(stderr);
|
||||||
exit(fail > 0 ? 1 : 0);
|
exit(fail > 0 ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
32
t/t_malloc.c
32
t/t_malloc.c
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -91,6 +92,8 @@ struct bucket {
|
||||||
void *top; /* top of bucket */
|
void *top; /* top of bucket */
|
||||||
void *free; /* first free block */
|
void *free; /* first free block */
|
||||||
void *unused; /* first never-used block */
|
void *unused; /* first never-used block */
|
||||||
|
unsigned long nalloc;
|
||||||
|
unsigned long nfree;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mapping {
|
struct mapping {
|
||||||
|
@ -104,6 +107,7 @@ static struct bucket buckets[BUCKET_MAX_SHIFT + 1];
|
||||||
|
|
||||||
/* mapping metadata */
|
/* mapping metadata */
|
||||||
static struct mapping *mappings;
|
static struct mapping *mappings;
|
||||||
|
unsigned long nmapalloc, nmapfree;
|
||||||
|
|
||||||
/* if non-zero, all allocations fail */
|
/* if non-zero, all allocations fail */
|
||||||
int t_malloc_fail;
|
int t_malloc_fail;
|
||||||
|
@ -128,6 +132,7 @@ t_malloc_null(void)
|
||||||
b->top = b->base + BUCKET_SIZE;
|
b->top = b->base + BUCKET_SIZE;
|
||||||
b->free = b->unused = b->base;
|
b->free = b->unused = b->base;
|
||||||
}
|
}
|
||||||
|
++b->nalloc;
|
||||||
return (b->base);
|
return (b->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +159,7 @@ t_malloc_mapped(size_t size)
|
||||||
m->next = mappings;
|
m->next = mappings;
|
||||||
m->prev = NULL;
|
m->prev = NULL;
|
||||||
mappings = m;
|
mappings = m;
|
||||||
|
++nmapalloc;
|
||||||
return (m->base);
|
return (m->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +211,7 @@ t_malloc_bucket(size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* done! */
|
/* done! */
|
||||||
|
++b->nalloc;
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,8 +347,10 @@ free(void *p)
|
||||||
unsigned int shift;
|
unsigned int shift;
|
||||||
|
|
||||||
/* was this a zero-size allocation? */
|
/* was this a zero-size allocation? */
|
||||||
if (p == buckets[0].base)
|
if (p == buckets[0].base) {
|
||||||
|
++buckets[0].nfree;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* was this a direct mapping? */
|
/* was this a direct mapping? */
|
||||||
for (m = mappings; m != NULL; m = m->next) {
|
for (m = mappings; m != NULL; m = m->next) {
|
||||||
|
@ -357,6 +366,7 @@ free(void *p)
|
||||||
mappings = m->next;
|
mappings = m->next;
|
||||||
/* fall through and free metadata */
|
/* fall through and free metadata */
|
||||||
p = m;
|
p = m;
|
||||||
|
++nmapfree;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert(p < m->base || p >= m->top);
|
assert(p < m->base || p >= m->top);
|
||||||
|
@ -372,6 +382,7 @@ free(void *p)
|
||||||
/* connect the block to the free list */
|
/* connect the block to the free list */
|
||||||
*(char **)p = b->free;
|
*(char **)p = b->free;
|
||||||
b->free = p;
|
b->free = p;
|
||||||
|
++b->nfree;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,3 +390,22 @@ free(void *p)
|
||||||
/* oops */
|
/* oops */
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print allocator statistics
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
t_malloc_printstats(FILE *f)
|
||||||
|
{
|
||||||
|
struct bucket *b;
|
||||||
|
unsigned int shift;
|
||||||
|
|
||||||
|
fprintf(f, "%6s %9s %9s %9s\n", "bucket", "alloc", "free", "leak");
|
||||||
|
for (shift = 0; shift <= BUCKET_MAX_SHIFT; ++shift) {
|
||||||
|
b = &buckets[shift];
|
||||||
|
if (b->nalloc > 0)
|
||||||
|
fprintf(f, " 1^%-3u %9lu %9lu %9lu\n",
|
||||||
|
shift, b->nalloc, b->nfree,
|
||||||
|
b->nalloc - b->nfree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue