93443689a4
Add the "thread.allocated" and "thread.deallocated" mallctls, which can be used to query the total number of bytes ever allocated/deallocated by the calling thread. Add s2u() and sa2u(), which can be used to compute the usable size that will result from an allocation request of a particular size/alignment. Re-factor ipalloc() to use sa2u(). Enhance the heap profiler to trigger samples based on usable size, rather than request size. This has a subtle, but important, impact on the accuracy of heap sampling. For example, previous to this change, 16- and 17-byte objects were sampled at nearly the same rate, but 17-byte objects actually consume 32 bytes each. Therefore it was possible for the sample to be somewhat skewed compared to actual memory usage of the allocated objects.
106 lines
1.9 KiB
C
106 lines
1.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <pthread.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#define JEMALLOC_MANGLE
|
|
#include "jemalloc_test.h"
|
|
|
|
void *
|
|
thread_start(void *arg)
|
|
{
|
|
int err;
|
|
void *p;
|
|
uint64_t a0, a1, d0, d1;
|
|
size_t sz, usize;
|
|
|
|
sz = sizeof(a0);
|
|
if ((err = JEMALLOC_P(mallctl)("thread.allocated", &a0, &sz, NULL,
|
|
0))) {
|
|
if (err == ENOENT) {
|
|
#ifdef JEMALLOC_STATS
|
|
assert(false);
|
|
#endif
|
|
goto RETURN;
|
|
}
|
|
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
|
|
strerror(err));
|
|
exit(1);
|
|
}
|
|
|
|
sz = sizeof(d0);
|
|
if ((err = JEMALLOC_P(mallctl)("thread.deallocated", &d0, &sz, NULL,
|
|
0))) {
|
|
if (err == ENOENT) {
|
|
#ifdef JEMALLOC_STATS
|
|
assert(false);
|
|
#endif
|
|
goto RETURN;
|
|
}
|
|
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
|
|
strerror(err));
|
|
exit(1);
|
|
}
|
|
|
|
p = JEMALLOC_P(malloc)(1);
|
|
if (p == NULL) {
|
|
fprintf(stderr, "%s(): Error in malloc()\n", __func__);
|
|
exit(1);
|
|
}
|
|
|
|
sz = sizeof(a1);
|
|
JEMALLOC_P(mallctl)("thread.allocated", &a1, &sz, NULL, 0);
|
|
|
|
usize = JEMALLOC_P(malloc_usable_size)(p);
|
|
assert(a0 + usize <= a1);
|
|
|
|
JEMALLOC_P(free)(p);
|
|
|
|
sz = sizeof(d1);
|
|
JEMALLOC_P(mallctl)("thread.deallocated", &d1, &sz, NULL, 0);
|
|
|
|
assert(d0 + usize <= d1);
|
|
|
|
RETURN:
|
|
return (NULL);
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
int ret = 0;
|
|
pthread_t thread;
|
|
|
|
fprintf(stderr, "Test begin\n");
|
|
|
|
thread_start(NULL);
|
|
|
|
if (pthread_create(&thread, NULL, thread_start, NULL)
|
|
!= 0) {
|
|
fprintf(stderr, "%s(): Error in pthread_create()\n", __func__);
|
|
ret = 1;
|
|
goto RETURN;
|
|
}
|
|
pthread_join(thread, (void *)&ret);
|
|
|
|
thread_start(NULL);
|
|
|
|
if (pthread_create(&thread, NULL, thread_start, NULL)
|
|
!= 0) {
|
|
fprintf(stderr, "%s(): Error in pthread_create()\n", __func__);
|
|
ret = 1;
|
|
goto RETURN;
|
|
}
|
|
pthread_join(thread, (void *)&ret);
|
|
|
|
thread_start(NULL);
|
|
|
|
RETURN:
|
|
fprintf(stderr, "Test end\n");
|
|
return (ret);
|
|
}
|